Code with Jason

268 - Joel Drapper

Jason Swett

In this episode I talk with Joel Drapper about open source development, the joy of coding without constraints, AI tools like GitHub Copilot, and our shared discomfort with the phrase "duplication is better than the wrong abstraction." We explore abstraction, technical debt versus "technical poison," and our mutual search for high-quality work environments.

Speaker 1:

Hey, it's Jason, host of the Code with Jason podcast. You're a developer. You like to listen to podcasts. You're listening to one right now. Maybe you like to read blogs and subscribe to email newsletters and stuff like that. Keep in touch.

Speaker 1:

Email newsletters are a really nice way to keep on top of what's going on in the programming world, except they're actually not. I don't know about you, but the last thing that I want to do after a long day of staring at the screen is sit there and stare at the screen some more. That's why I started a different kind of newsletter. It's a snail mail programming newsletter. That's right. I send an actual envelope in the mail containing a paper newsletter that you can hold in your hands. You can read it on your living room couch, at your kitchen table, in your bed or in someone else's bed, and when they say what are you doing in my bed, you can say I'm reading Jason's newsletter. What does it look like? You might wonder what you might find in this snail mail programming newsletter. You can read about all kinds of programming topics, like object-oriented programming, testing, devops, ai. Most of it's pretty technology agnostic. You can also read about other non-programming topics like philosophy, evolutionary theory, business, marketing, economics, psychology, music, cooking, history, geology, language, culture, robotics and farming.

Speaker 1:

The name of the newsletter is Nonsense Monthly. Here's what some of my readers are saying about it. Helmut Kobler, from Los Angeles, says thanks much for sending the newsletter. I got it about a week ago and read it on my sofa. It was a totally different experience than reading it on my computer or iPad. It felt more relaxed, more meaningful, something special and out of the ordinary. I'm sure that's what you were going for, so just wanted to let you know that you succeeded, looking forward to more. Drew Bragg, from Philadelphia, says Nonsense Monthly is the only newsletter I deliberately set aside time to read. I read a lot of great newsletters, but there's just something about receiving a piece of mail, physically opening it and sitting down to read it on paper.

Speaker 1:

That is just so awesome Feels like a lost luxury. Chris Sonnier from Dickinson, texas, says just finished reading my first nonsense monthly snail mail newsletter and truly enjoyed it. Something about holding a physical piece of paper that just feels good. Thank you for this. Can't wait for the next one. Dear listener, if you would like to get letters in the mail from yours truly every month, you can go sign up at NonsenseMonthlycom. That's NonsenseMonthlycom. I'll say it one more time NonsenseMonthlycom. And now, without further ado, here is today's episode. Hey, today I'm here with Joel Drapper. Joel, welcome. Hey, so you've been on the show before, but that was a long time ago. So for anybody who is not aware of who you are, can you tell us a little bit about yourself?

Speaker 2:

Yeah, sure, I am a software engineer, live in Oxfordshire in the UK and I work on a bunch of different open source libraries in the Ruby ecosystem, like Flex, literal, quickdraw. Some of them are newer and more experimental than others. I do open source mostly for myself, just to experiment and have fun and kind of just enjoy coding. Um, especially if you're working somewhere where, like, coding is exhausting, it's nice to have a place where you can kind of like just really like I don't know, perfect something small oh, oh, man Without limitations.

Speaker 1:

I like that resonates so much with me. I haven't really like articulated that to myself before, but, like you said, working somewhere where, like, coding is exhausting that's basically everywhere and so to have a project that is just like your own and you don't have to deal with anybody else's bullshit and stuff like that.

Speaker 2:

It is just so nice to have that outlet, yeah, yeah, because otherwise, like, if it can, I I think it can feel. Like coding is like this exhausting thing full of compromise, um, and I just think there's so much joy to be found in kind of like just really not caring about, like is this reinventing the wheel? Or, you know, like is this premature optimization? Or any of these like keywords and buzzwords that people throw around to destroy your motivation. Like, instead of that, you can just say, well, I'm doing this for me, I, I'm going to make it as fast as possible, I'm going to make it as good as possible, I'm going to like do ridiculous things, like I'm just going to write a SQLite parser from scratch in order to have a slightly, ever so slightly better migration experience, or something like that.

Speaker 1:

Yeah, yeah, you know it's interesting migration experience or something like that. Yeah, yeah, you know it's interesting. There are a number of things that are like completely insane and unreasonable and yet, at the same time, extremely rational and smart to do. And there's a lot of stuff where it's like the correct opinion is the minority opinion and so, like you'll never get away with it anywhere else. Like for me, um, on on saturn ci, my ci platform I'm working on, I'm not using tailwind or bootstrap or anything. Um, for my css library I'm using nothing. Um, because, well, we could get into a whole side conversation about this. But like, uh, long story short, if you have a library, it's probably till death. Do us part. Like if you adopted bootstrap eight years ago, you probably still have bootstrap now, even if you that's true even if you decided to switch to tailwind, um, probably what you have now is tailwind and bootstrap.

Speaker 1:

Yep, um, I I bet that I just poked a sore spot with a lot of listeners just now, because they have that exact situation and apologies, dear listener, but you're never going to get off a bootstrap. It's just going to be bootstrap and tailwind and then, in three years, when something new comes out, you're going to have all three and it's going to be bootstrap and tailwind. And then, in three years, when something new comes out, you're going to have all three and it's going to be terrible, that as well right, yeah, so I'm just saying, fuck all that.

Speaker 1:

I'm not going to have any library, it's just going to be my own lightweight, like um, tailwind, ish, set of utility classes or something like that, and then I'll never have to upgrade, never have to deal with any of that stuff. Right?

Speaker 2:

that makes sense also, like from, I think I like just getting into tailwind very briefly the. The advantage that I think that it really brings you, uh, when there's a team, is because the css is generated from the html. It's very like you can delete the html and the css is deleted for you, right? Because because it's generated that way, whereas I feel like if you are writing css by hand, with a team that's not disciplined, it's very difficult to know. For example, is it safe to delete this css or am I going to completely mess up something because someone had, like, reached out and set some global thing that is now depended on in all of these 25 different places? But it's subtle, like it's.

Speaker 1:

It's tricky yeah, that's a good point, but there's no reason I couldn't replicate that aspect of tailwind right, exactly, yeah, but you'll never get away with that. On like, yeah, anybody else's production project, they'll be like, right, that's insane, we're not going to do that. Uh, just use tailwind right, um, yeah, do you have any other, like you mentioned, the writing, a SQLite parser thing? Do you have any other examples of like crazy things that you would do or have done that you wouldn't get away with?

Speaker 2:

That's a good. That is a good question. I think that I have a bunch of examples, but I'm struggling to come up with specific ones.

Speaker 1:

We'll probably come across it in our conversation somehow um, yeah, you know, you and I have talked like maybe three times total yeah um, but I'm already getting an impression that you are kind of a uh well, actually, I'll make a statement about myself and instead, instead of about you, and you can tell me how much it resonates with you um I have, like, very strong opinions and for for things that I don't know much about um I don't have very strong opinions like, for example, these like as we record this, there's this like trump tariff stuff going on a lot of people have really strong opinions about that stuff.

Speaker 1:

I'm like well, I don't know like I don't know anything about tariffs and so like I don't have to. I'm like, well, I don't know, Like I don't know anything about tariffs and so like I don't have to have an opinion on that, because you don't have to have an opinion on everything, Like I'm just going to mind my business and wait and see what happens. Anyway, when I don't know much about the thing, my opinions are weak. But when I know the thing, when I know something about the thing that I have an opinion on, my opinions are weak. But when I know the thing when I know something about the thing that I have an opinion on, my opinions are often very strong, um, and they often like go against the grain a bit yeah um, and I'm not.

Speaker 1:

I don't really have a problem with saying like fuck you everybody. I know that you think this, but I think this, and so you're gonna zig, but I'm gonna zag. And I know that's gonna cause problems for me, but like I don't care because I'm not gonna go along with stupid shit. I'm curious how much that resonates with your way of thinking yeah, um, very much so.

Speaker 2:

um, I I would say I'm not like just because you have a strong opinion about something doesn't mean you're completely closed to talking about it. It just it just means that if you're going to do something that way, like you're confident that you know how to do it, I think, and like you can engage in a conversation about it.

Speaker 1:

Yeah, yeah, ok, so this is actually a really interesting topic in itself. So I kind of hate that saying strong opinions loosely held, because I think it gets some important things very wrong. Okay, so I think all of a person's beliefs should be tentative. No matter how strong or weak your beliefs are, they should be tentative in light of new information. And so some of my beliefs are like, really strongly held but they're still tentative. Like I believe that the earth is round and not flat. I hold that belief pretty strongly, right, but it's tentative. If somehow I gain some new information that made me believe the earth was actually flat, then I would update my belief. Terrible example, because surely you know there's no way that that particular thing is going to change.

Speaker 2:

But you know what I mean.

Speaker 2:

Yeah, exactly, yeah, is going to change.

Speaker 2:

But you know what I mean yeah, exactly yeah, um, yeah, and the one thing that, um, I do try to watch out for is, uh, to, like, you have a sort of opinion cache as well, which is that you can, you can, develop an opinion on something and you can cache the result, uh, and then you have to be careful, uh, that, as information does change which it does like all the time, especially in our industry that you're able to at the right kind of layer of um, uh, you know, not too often, right, but you need to regularly re-evaluate some of the opinions. Yeah, in light of new information, I've changed some fairly strong opinions, uh, for example, uh, I used to have a fairly strong opinion that, basically, single page applications were a bad idea, pretty much 100 of the time, um, and in light of spelt five, I've changed that opinion. I think that, uh, there are. It has solved things that were not solved before in a way that had not been solved before, where I think, like, actually, this is a very reasonable way to do things now interesting.

Speaker 1:

Yeah, I have. Um, I've had that experience too. Um, that belief cache thing, I think, is a really valuable way of looking at it. I experienced that myself kind of recently. Obviously everybody's starting to use AI now for programming and I tried out GitHub Copilot when it was relatively new and I didn't find it to be that great. You know, it was like kind of a fancy autocomplete and my finding at the time was that the suggestions were not all that high quality and in practice, the way that I observed most people using it was, frankly, pretty dumb, because they were just writing code speculatively, and by that I mean they weren't starting with a concrete need and then deciding what they wanted to do and then writing an automated test to encode that specification and then writing just barely enough code to meet that specification.

Speaker 1:

Yep, you know if you go through that whole process, but then you go beyond and you write more code than what's needed to satisfy that specification then you're coding speculatively because that code, that extra code, coding speculatively because that code, that extra code you're writing, might not be needed, and now you're going to have a carrying cost for this code that you don't know has a value. Yep, and it's obviously even more speculative when you just write code with no tests at all, because then it's all speculative. And that was the number one use case that I saw for GitHub Copilot. People would just type something and they'd get like a whole method and they'd be like, okay, I guess, great, and then commit that and push it to production and that's like insane. And so I was like anti-GitHub copilot. But then I kind of cashed that belief.

Speaker 2:

And.

Speaker 1:

I held on to the belief a little bit too long. But then later I used SuperMaven with Vim, one of my well, no, no, no, that's not how it went. I used Cursor and I found Cursor's suggestions to be much smarter. And you know, with both GitHub Copilot and with Cursor you can have it help you write tests Like that's a great use case for it, because that's not coding speculatively Although I found that GitHub Copilot didn't write all that great of tests, but Cursor is better at it.

Speaker 1:

And then with Cursor I could even do things like write a test and then tell it to. I wouldn't even have to tell it, I would just like begin to write the code to make the test pass. And it was smart enough to connect the new code that I was writing to the test and write specifically the code that was needed for that, rather than a guess. That only took into account the context of the file that I was currently on, and so now I'm a total convert. Like I can't imagine going back to typing everything manually instead of having an AI autocomplete.

Speaker 1:

So I busted the cache on that and now I have a different opinion. But again I maintained that cache a little too long.

Speaker 2:

Yeah, yeah, I mean you have to have a cache, otherwise you're just going to be constantly thinking about things you've already thought about in the past, which is useless. Just on Copilot. A couple of interesting thoughts about this. One of them is if you're using so Copilot and Supermaven and, I'm sure, all of the other tools out there they try to pick up context from the file that you're in probably the whole project that you're in and so if you're working in a code base that is full of really low quality code, then you're going to get really low quality predictions.

Speaker 2:

That has been my experience anyway. Interesting, um, and so even like when you first tried it, like if you were trying it, say, at work with a really low quality code base, and then, um, you know, your opinion is like this is this sucks, whereas if you tried it on a smaller project where you'd be very careful to, you know, write code in the way that you want it to be, like maintainable code, um, then you may have found you had a completely different experience then you may have found you had a completely different experience.

Speaker 1:

Yeah, that's interesting. I think I've only really ever used it, mainly on on one project on saturn ci, and then like I've dabbled a little bit in other like tiny ephemeral projects, so I haven't seen the the difference.

Speaker 2:

But that makes total sense that it would work that way, yeah um, the thing, yeah, um the thing about copilot is at least, uh, or at least like, if we're talking about the predictive copilot, at least it's generating a small amount of code that you will hopefully read that like I've seen so much, so much shit, uh, generated by ai that people have just like, clearly, without thinking about, just put straight into their program.

Speaker 2:

It's really interesting, like I, for example. Uh, a few months ago I ran into a uh, I was I was working on a bug. It was like a CSV passing problem and I was so confused how this could possibly happen. Like, apparently, if the CSV columns contained commas, it would all break. And so I was like looking through the controller trying to find where we did the CSV pass, and all I could see was JSON pass. And I was like what this is so weird? Are we passing CSVs with a JSON parser? That can't like. That wouldn't work at all.

Speaker 2:

No, what we were doing is we were passing CSVs in the front end in a piece of inline JavaScript that was in the slim template, and the inline JavaScript just split the string at every new line and then split the string again at every comma, and that was a CSV parser. Like, obviously wouldn't work at all, but it's exactly the kind of thing that you would get if you asked like GPT or something to generate this feature for you and then didn't read it. I think it's really important to know what you're trying to build and then if it predicts what you were going to type anyway, like that's great, that's a time saver.

Speaker 2:

But if you're not even reading through and understanding what it's doing yeah, and it seems so obvious, but, like we've been coding since before, ai was a thing and I think like it's, it's almost um, it's too easy to like. If you're junior engineer and you've got these pressures to ship this feature and you can copy and paste some code and it works and it gets through qa. Um, like you're not really learning anything if you're doing that, whereas I almost think that you should. It's great to be able to talk to these chatbots and things, but you should ban yourself from copying and pasting until you really understand what you're doing. But again, maybe that's an opinion that will eventually be uh, you know, irrelevant, because, because it will be better at coding than we are one day.

Speaker 1:

Well, Well, I've talked about this before. There's like a distinction between things that are a good idea or bad idea or possible or not possible with the current technology. And then there's the idea of things that are a good idea or bad idea, or possible or not possible in principle.

Speaker 1:

And I think it's useful to make a distinction between those two. Things Like, for example, the idea of just doing away with automated tests. I don't think that's ever going to be a smart idea, even in principle. Yeah, no matter how good the AI gets and same thing with just like uncritically accepting AI generated code.

Speaker 2:

I don't think that's ever going to be a good idea, even in principle. Yeah, never, yeah, basically for nothing.

Speaker 1:

Um yeah, and I think, like I think, if you imagine developers having some kind of skill coefficient or something like that, if you're kind of mediocre, your coefficient is like, oh wait, zero. Let's say your coefficient is oh okay, my mathematical metaphor isn't working out so well. Well, but I'll say it in a different way, like if you're really good already, ai is going to make you way better and if you suck, ai is going to make you worse, and if you're in the middle, ai is just going to have like a null effect.

Speaker 1:

Yeah, that bothers me. Now, how do you? How do you express that mathematically? So if you're, in the middle and it has a null effect. The coefficient would have to be like one, right? Yeah, I don't know. Well, I want to figure this out because I'm frustrated that I couldn't figure it out just now.

Speaker 1:

And then yeah, yeah, yeah, Okay. So it's just like the middle is one, and then maybe it goes up exponentially from one and down and gets like exponentially closer to zero, because if it gets to zero then that's like no value at all but, actually, if you do a bad enough job, it's gonna have negative value.

Speaker 1:

who cares about the math thing? I'm not gonna going to figure it out, but people. I'm sure it's happening right now. I just haven't witnessed it with my own eyes Like people are going to use AI and create such an abominable mess.

Speaker 2:

Oh, I've witnessed it. Yeah, I've witnessed it for sure. Yeah, tell me about that. I mean it's. You can get by, um, you know you can get by for a for a while just by using essentially like copying and pasting from gpt and you can build an application and you can get customers to pay you for it, but then maintaining it just becomes exponentially worse and worse over the years and you eventually need to fix it and, honestly, fixing a code base that is that fucked is really difficult, if not impossible. I think you've talked about this on the show before. Basically, you're probably never, never gonna fix your technical debt, whatever, whatever beliefs or like value system you had. That meant that you got that technical debt.

Speaker 2:

They're not going to change just because you decide you need to get rid of this technical debt, like right um, it's, it's very, very difficult, um, and I, I don't know, I I'm I used to think, like you know, it would be a fun challenge to be hired at a company that had a lot of technical debt but was, like, open to learning and was open to um, you know, let's, let's do these long-term refactors, let's start doing testing, let's start, you know, caring about performance and database architecture and like, try to, you know, upgrade the engineering by mentoring everyone in the company and like just really focusing on quality.

Speaker 2:

But, like, it's never worked out for me. Uh, like, if the idea of, yes, like this is a good opportunity, they're going to pay well, and uh, I have the skills that mean I can actually like turn the ship around. Just, it never happens, unless, unless, I think, maybe, unless you are the most senior person if you're being hired as a new cto or director of engineering or someone who can really make like decisions that might seem very, uh, it might be very unpopular initially, but will eventually eventually pan out, if you've got a year to do your thing and then see the value from that investment. Because, let's be honest, if you spend a year investing in technical debt, you're not going to see any significant changes to the product. But what you will see is now we can build features four times faster than we could before and now.

Speaker 1:

And now, like we don't have any bugs, like there are no exceptions in production at all, they're gone yeah, this is a fascinating area, so fascinating, um, because, like, I used to think the same thing, like I used to think it would be interesting to get hired somewhere and they have problems and I help them with their their problems, um, but there's this, uh quote I've been repeating so much lately uh, jerry weinberg no matter what the problem is, it's always a people problem um because, like, if the company has technical debt, um, I don't like that metaphor, by the way.

Speaker 2:

No, I don't either. Actually I call it technical poison, Technical poison.

Speaker 1:

I love it Because it's not like debt.

Speaker 2:

Debt can be good, right, it can be good to get into debt. I don't think it's ever good to have technical debt, as people so call it. It's poisonous, it you know it. It spreads, it gets copied.

Speaker 1:

Well, here's here's my metaphor. I use, um, I use a blade metaphor of like you, you have a shed full of blades, and some of them are sharp and some of them are dull, um, and it's never preferable to have a dull blade instead of the sharp one, right, yeah, um, anyway, you have a company with a bunch of dull blades, um, and the idea is you can come in and you can help them and help them undergo, undergo some kind of transformation, um, and that's kind of like partly what I was hired to do when I was working as a consultant which I still may continue and do more of in the future is they would hire me to help with their technical problems, but the problem was always something different than what the presenting problem was which, which is famously, like always the case, it's like hey, jason, we need help with our test suite.

Speaker 1:

it's like okay, well, yes, I can see that that needs help. Um, but, like, the bigger problem is that your developers aren't writing tests, because in order to write a test, you need to decide what you're going to do before you do it, and your developers aren't deciding what they're going to do before they start coding. They just start coding, and the managers are doing bad too, because they're giving developers assignments that are extremely vague and the developers have neither the skills nor the purview to be able to determine on their own what needs to be done um and so it's just not even it's not even usually one thing like yeah

Speaker 2:

you can't even point to like. This is the problem and if you fix this, then people are going to find it easier to write tests. It's like a bunch of different things and you know what usually you'll you'll find it that kind of situation will coincide with your developers are in too many meetings every day. Like you need to give them time to do their work. Like encourage people to pair with each other on the problems. Don't get 25 developers into an hour-long meeting once a day, because that's like gonna destroy their productivity and the funny thing is, this stuff is such common sense.

Speaker 1:

Yeah, but it's, it's defied so often and that's the you know man.

Speaker 1:

Okay, so many thoughts um I I think I mentioned this yesterday when you and I talked offline Sometimes I feel just like a total cynic, but really I think I'm a realist and most people they only have most people delude themselves to a certain degree, because I think we're like biologically hardwired for a certain degree of self-delusion, because if you don't, then you'll just like go crazy and you can't function. Um, and so people are like overly optimistic. They're groundlessly optimistic about things. Um, it's like, hey, you know what? Like everything's been shit every single day for the last five years, but tomorrow's gonna be great. I think tomorrow's gonna be great, I think tomorrow's going to be great.

Speaker 1:

We can pull it together. It's like why, do you think that Anyway?

Speaker 2:

Because otherwise, like, what is the point of coming to work and doing anything today?

Speaker 1:

Yeah, Right, exactly, and like I'm, usually the only one around who's willing to say like hey guys, like just because you have a problem and just because it's absolutely unacceptable for this problem not to be fixed, it doesn't logically follow that the problem can be fixed. And so it's like see that brick wall in front of us, like we're headed toward that brick wall, we're sliding on ice toward the brick wall. There's nothing in the world that can stop us. We're going to hit that brick wall and that's just the way it is, and people no I think we can no, I think we can do it.

Speaker 1:

We're not gonna hit the brick wall. It's like all right. Well, that's just like not reality but anyway um, the root of the cause with almost all these problems is at the top. Um, there's just people who aren't that smart and they're running the show and they're making really poor decisions. Um and and the unfortunate thing with people who aren't that smart is they make poor hiring decisions, and so they hire a bunch of developers who aren't very good, and so it's like okay you want to fix this problem.

Speaker 1:

Well, even though this sounds crazy, you need to fire 80% of your team. Um, and your productivity will actually go up, because those people are just dragging everybody else down and eating up everybody's time and stuff like that.

Speaker 1:

You need to fire 80% of your team and then, really, like, your CTO and CEO need to quit and we need to get different people Like you need to just change out everyone, but obviously that's never going to happen, and so the only thing to do is just move on to a different client I mean it could happen in theory, but, like you said, like it's not, it's never going to happen in practice.

Speaker 2:

Like, even if you like could convince someone that that was like in. You can have all the evidence and all the you know, all the logic that points to that being a logical way to progress. But that doesn't mean that the company is going to do that. No one's going to listen to you about, like, firing 80% of your team.

Speaker 2:

I'm a big advocate for hiring junior engineers and mentoring them, but you can't do that if your company isn't setting a good example. If you don't have it like, if your engineering practice is poor, then you're not benefiting any junior engineer that you hire into that company. You're, you're you're harming their career. Um, and I think it's actually really important to like get to a point where, like you've, you've solved the problem for yourself. Now you're in a position to be able to help other people. Now you're in a position to be able to help other people, now you're in a position to be able to teach, and then that's when you want to hire junior engineers, is when you're actually doing really well and your engineers are empowered to mentor people, if that makes sense.

Speaker 1:

Yeah, I mean it makes so much sense. The whole hiring junior things is also a really interesting topic. I'm also a fan of that and, like, because I'm wildly irresponsible, I'm already thinking about, like Saturn CI, even though it's pre-revenue Like when it comes time for me to hire people who might I hire, when it comes time for me to hire people who might I hire. And there's certain like really senior people who I'm thinking about, who like maybe would be good to hire. But then I think there's also something to be said for just hiring somebody with raw talent and brainwashing them and indoctrinating them with your belief system, because they're like kind of a blank slate. If you hire somebody who's too experienced, it might be hard to disabuse them of the things that they already believe.

Speaker 2:

Um, yeah, unless they, unless their beliefs are compatible enough with your own that you know you can have a really productive like amalgamation of those beliefs, I guess yeah, um yeah, and it's not as though there's nobody out there who would be like compatible enough with me for me to care I.

Speaker 2:

I think if that were not the case, then that would be a clue that I'm like off my rocker yeah, yeah, like, like I probably have very different beliefs to you, um, or like I know that you test first and I almost never test first, for example, right, and you probably think that's crazy, but we could work really well together, I think, um, because I understand why you test first and I really respect it. I just need to sketch the thing out, because that's how I get the idea from my brain onto paper, like, and that's how I get to those requirements.

Speaker 1:

Yeah.

Speaker 2:

And then I want to go into the test to like and obviously like I don't want to get too into the weeds talking about TDD no we should.

Speaker 1:

We should Okay, because I want to address a big misconception yeah, okay, you do write the test first. Okay, um, because what you're doing you know. You said, what did you say like you.

Speaker 2:

So my process is typically I will think about what I want and then I will, uh, think about what objects I want to be sending, what messages, and I will sketch out all of those objects and try to make them speak to each other, and I won't run the code.

Speaker 2:

Sometimes for hours, sometimes for days, I won't even run the code. Often I am running the code like a lot of a lot of stuff, of stuff you do in a few minutes you wrap up a specific feature, but sometimes it's like, no, I'm just really sketching out all of these different parts. And now that I've got this sketch, it's like if you're an architect, you could try to figure out the specific, like how much weight the staircase can take, or whatever. Or you could, you know, sketch what you want the building to look like, roughly, like it needs to have these bits, we need to have these walkways. And then you start making it concrete by figuring out like, okay, if people are going to be walking across that bridge, it needs to be strong enough to take their weight. That's kind of the way I look at it yeah, yeah.

Speaker 1:

So I think a big misconception about tdd is like where the development of specifications phase ends and the writing of the test phase begins. I was thinking about this in the car the other day. I'm like kind of unhappy with this idea of the red-green refactor loop.

Speaker 2:

It's not that it's wrong.

Speaker 1:

It's just that it's like maybe not exactly the thing, and I started to think about, like, if I were to replace that idea with a better one, what would the idea be? Um? And maybe the loop would be like specify, encode, um. And I had a third one, but I don't remember it um, but it's like first come up with the specifications, then encode the specifications so like what I mean by that is like come up with the specifications, then encode the specifications.

Speaker 1:

So like what I mean by that is like come up with the specifications either just in your imagination, or like write them down, or something like that. Or write some code to come up with the specifications. You can like, mess around and come up with the specifications that way, yeah, and then encode the specifications, write them into a test. Oh, I remember the third one was fulfill.

Speaker 1:

Specify, encode, fulfill. So that third step is you write the code to fulfill the specifications, and so I'm obviously assuming a lot about your process and I'm not sure if I have it right, but I think a lot of what people think of as coding and it's like, oh, I write the code and then I write the test.

Speaker 2:

Just coming up with a spec.

Speaker 1:

Yeah, what they think of as coding is really just coming up with the specification. You're just using code as a medium to come up with the specification.

Speaker 2:

Fair enough? Yeah, well, in. In which case, that's what I do and the way that I typically will do a red green test. Uh is I will assert the wrong thing, wait for the test to fail, look at the error message, make sure it's what I expected and then copy the error message back into my test and I'm watching it go green yeah so I kind of like do it the the wrong way around well, you're doing the, the red step of red, green refactor the right way which is you're testing the validity of your test right yeah, yeah, but I do it by making my test wrong and then correcting my test, rather than making my code wrong and then correcting my code.

Speaker 2:

Yeah, that's which is probably like it's probably a gap there where, like it's possible that I could the the act of correcting my test um actually made it so that it's a kind of false positive um, some kind of like mistake in correcting the test, whereas if your test stays fixed and you just change the code, but for the most part it's, it's worked out and I've I've not found that that's an issue for me and it just works pretty well. But then on some things I'm working on, like if it's like lower level stuff, like particularly in the SQLite pasta I've been working on, and for stuff like that a lot of the time I do write the test first because I know exactly what I want. Like I've already defined, I've already done my kind of like object oriented design phase right. I know the shape of the object, I know what messages it needs to send. I'm just testing a different case with the same shape.

Speaker 1:

Okay, I want to go back a little bit because so many times I've seen people try to go through red green refactor and they're like, oh, I need to see the test fail. I'll like fuck with my test and make it not pass. It's like no, that's not, you're missing the point. The idea is to test the validity of your test. So you don't want to like intentionally make your test like wildly wrong because that doesn't give you the information that you're after yeah, but the way I messed up well, I suspect that you were doing it in a smarter way because, like, there's logically valid and invalid ways of doing that.

Speaker 1:

Like, yeah, if you have a test where the structure of the test is all the same, but you're expecting, like, foo instead of bar or something like that, like that's still valid.

Speaker 1:

But if you change the test to like expect something completely different. Then, like, all bets are off, yep, yeah, so I wanted to touch on that, um, and then I had more thoughts on the next thing you said, but I forgot what the other thing you said was uh, it was about um object shape like oh, when I when I do find tdd or like writing my tests before writing the code.

Speaker 2:

Uh, to work very well is if I've already. I've already like got the shape figured out right. I know either I'm implementing a new object that is going to implement the same shape as something I've done before. I'm just testing that variant. Or, like I have a method that you know needs to respond in a different way if it's given a different thing or something like that, and I'm not making kind of like design decisions At that point. I'm just testing out all of the different edge cases and in those scenarios I will like just try to enumerate the edge cases in my tests and then follow the tests until the code is correct yeah, so like I'm not saying this is the way that people should do it.

Speaker 2:

I honestly think that tdd is a very good idea and, in fact, um, the I love, was it. I think you had a podcast episode with who was it? You were talking about how you don't need code coverage if you do TDD.

Speaker 1:

Oh yeah. I mean if you have strong TDD habits, you'll just naturally end up with good code coverage.

Speaker 2:

Yeah, like some of these things, they make so much sense. Sometimes it just doesn't work for me. I mean, I need that like creative, like no constraints, thinking about the big picture. How do I want this to feel? What's the? You know, aesthetics are really important to me in programming, um, and so, um, a lot of the time I'm like experimenting with can I even like, is it even possible to make this work? Um, like, uh, I often will use things like, like, I often will use things like the fact that you can, if you put an ampersand behind something, it's going to call to proc on that thing or that kind of thing.

Speaker 2:

And like, that isn't me thinking, oh, I need to make this object respond to proc. Like that's a requirement. Um, it's more like I want to be able to pass this object in as a proc using this, this like syntax, because it's beautiful. And now, how do I make that work? Okay, I'm gonna need it to respond to two proc. Okay, now I'm gonna need to test that if you call two proc on it, it's correct um, I was gonna say something about, oh yeah, I remember.

Speaker 1:

Um, not really. Anything you have said is incompatible with my way of looking at things. Like here's a bigger picture comment. Like I've come to the opinion that, like programmers think about programming uh way too much in terms of code. Like code is just a medium, um, what we're doing, like it's kind of like if you're uh, if you're an artist, you're like a sculptor who works in metal, um, it's kind of like, referring to yourself as a welder, it's like I'm going to go do some welding today. It's like, okay, well, sure, you're doing some welding, but that's not really it. You're a sculptor and you're trying to make a sculpture.

Speaker 1:

It's just like the mechanical task you're doing is welding and that's a skill and all that, but that's not really it, whereas with coding it's like, yes, we're coding, but what we're really doing is um. We're designing a machine um to perform, to, to meet a certain need in the world.

Speaker 2:

Yeah, um and, but with one. I would always add an additional requirement that where it is always a joy to work on that machine let me come back to that, because I think that's a related but separate thing.

Speaker 1:

Um, it's, it's a machine and the the. The way that you design this machine is by. You know, a software system is superficially made out of code, but it's really made out of ideas, and so you're like coming up with the ideas that go into this system in a way that's going to make the system sufficiently easy to understand and work with. And I haven't thought completely to the bottom of this, but I think maybe what I'm talking about is abstraction, like I came across a good example the other day.

Speaker 1:

I was rereading Sandy Metz's practical object-oriented design Pooter um, and I think it's like overall a pretty good book, but there are a lot of things that I like take umbrage with in the book um and it's one of those things where it's like such a popular book that I want to like shout from the rooftops like hey guys, like yes, sure it's a good book, but like there's some certain things that you should really know, because you shouldn't be uncritically accepting everything out of a book, even if it's a good book. Um, anyway, I'm I'm like meandering wildly, but I came across this example on page 20 if you happen to have the book, um, of this gear class oh, I meant if you listener happen to have the book.

Speaker 1:

Um, there's this gear class with methods like ratio and gear inches. Um, which I find frustrating because it's like uh, oh, there's, there's attributes like cog, rim and tire. You might expect those to be objects, like a cog object and a rim object, but no, they're actually scalers.

Speaker 1:

They're like uh, values like inches which is, uh, to me kind of surprising and I don't think it's really a tidy abstraction, um, but anyway, this whole bicycle, uh, domain made me think about abstraction and bicycles, because this class is called gear and I asked myself, like hang on, what exactly is a gear? Because I don't think a bike has any part that's called a gear. It just has sprockets and chain rings and all that stuff and what we call a gear on a bike, I think it's borrowed from automobiles, where a car's transmission has different gears, but even that's not really a gear, it's just a gear configuration. And so, on a bike, we have a configuration of a chain ring and I don't know the terminology, I'm just going to call them all sprockets, it's, it's a configuration of two sprockets, um, which gives you like that is a gear a sprocket is a gear.

Speaker 2:

well, I don't know, uh, what the technical term is uh like or what the technical definition of a is, but the way I think about it is a gear is an abstract concept that relates to the relationship between two moving parts. Right, it is a multiplier on a leverage variable. Essentially, Right, right, you're saying for each turn of the pedal. Depending on the gear the wheel is going to turn this many times.

Speaker 1:

Yeah, so mechanically. In reality, what we have is two sprockets of a certain size connected by a chain. You could call it like a drivetrain configuration or something like that, but that's too much of a mouthful so we just call it a gear. So that is an abstraction that doesn't have anything to do with computers that people use in the everyday world. It's like what gear are you in? But there's no physical entity called a gear. A gear is a collection of physical entities yeah.

Speaker 2:

Yeah, a gear, it's. A gear is a collection of physical entities. Yeah, yeah, um so, almost like gear. Gear should be computed from the state of, uh, different objects as as like an abstract way of describing their relationship I have no comment on that.

Speaker 1:

Maybe so, maybe not, but I the only reason I brought that up is because, like, I want to be really clear about what an abstraction is. It's such an overloaded term in the industry and people. I saw this fucking tweet the other day. It was like it was some meme. It was like hard pills to swallow, stop abstracting. And it's like god damn it like that's such oh it's painting with such a broad brush, it's like I get it.

Speaker 1:

You probably saw a lot of really dumb abstractions and sort of like wow, people are applying this principle really badly, like 99 of the time. Therefore it's a bad idea, but it's like no, just because people abuse the idea doesn't mean it's a bad idea. Just means people need to have a better understanding of the time. Therefore, it's a bad idea, but it's like no, just because people abuse the idea doesn't mean it's a bad idea. It just means people need to have a better understanding of the idea and use the idea better 100%.

Speaker 2:

Yeah, I hate like related to this. I hate the. I don't think that this was ever the original intention of this phrase, but the phrase duplication is better than the wrong abstraction. The way that people use that now, I absolutely hate it.

Speaker 1:

Thank you so much.

Speaker 2:

It is so mistaken because, to start with God, I don't even know where to break this down. It's just so wrong To start with. This idea that you can have a wrong abstraction assumes that you can have knowledge of the future. It assumes that at some point, you're going to know all of the ways that this should ever change. Um, and and you're, at some point you're going to be able to find the right abstraction which would involve looking forward into the future.

Speaker 2:

Um, and it's like you, if you're building your, if you're making your abstraction based on the state of things as they are today, it's not the wrong abstraction I feel, like it's so often used as a way to discourage you from uh, from doing from.

Speaker 2:

Like, yeah, I don't, I don't know it's hard, it's hard to describe this, but like the to me, um, the, the art of of writing software is literally the art of making abstractions. Like that is what everything is built on, like from the most basic logic gates all the way up to where we're able to write Ruby using arrays and hashes and all this stuff. Like.

Speaker 1:

It's all just abstraction upon abstraction, layers and layers of abstraction yeah, and what's really funny is like I don't think most people really know what an abstraction is in myself until recently, like if you ask me what's an abstraction, I wouldn't be able to tell you okay, and I want to put how do you define it right now? Well, before I give my definition, I want to put you on the spot and see are. Are you able to give a definition?

Speaker 2:

Okay, I'll do my best, Okay. So an abstraction to me is it is a very difficult thing to define, so I'll do my best. It is taking a concept and it is shrinking it and it is shrinking it. So this is really yeah, it's really hard to describe.

Speaker 1:

All right you want me to give mine? Yeah, go on, give yours, let's see if I can remember it. I have it written down, but let's see if I can actually remember it, because I don't know where it's written down. Abstraction is the act of replacing low level information with high level information in order to better understand a certain part of the world yeah, that's.

Speaker 2:

That's very good. I would almost I would swap information with, uh, maybe interface. Actually, the word I used was idea. I wanted it to be yeah idea is good.

Speaker 1:

Yeah, um it's.

Speaker 2:

It's the act of replacing low level ideas, lower level ideas, with higher level ideas in order to make a certain part of the world easier to understand so a a very um primitive example of this is there are certain um, there's certain like binary, uh computations that you can do. That give you logic, right, you can. There's certain arrangements of computations in zeros and ones, and we have we have basically put these, these things together and named them, things like and, or exclusive, or, etc. And these are called logic gates, and many of the logic gates are formed by using other logic gates. And then on top of that you have other things that compose them together and they have very much smaller interfaces and they're hiding a lot of the complexity.

Speaker 2:

But conceptually, we can just think about this thing. As you know, I have this method that takes two things and it gives me the answer, which is like adding them together. Right, I don't care about what it's doing to the ones and zeros behind the scenes, like, the way to describe that idea is add, like I'm just adding things. That is like an abstraction.

Speaker 1:

Yeah, and there's this podcast episode of the podcast Mindscapes with Sean Carroll. And he said in that episode, episode, I forget if he was dealing exclusive with, exclusively with the idea of emergence, or if he was talking about both emergence and abstraction, um, but of one of these two ideas he said um, you're throwing away information.

Speaker 1:

And I thought that was interesting because with the logic gates, when you're referring to them by their higher level ideas and or and stuff like that, you are throwing away information because there's, like, the details of how it works. But if you just speak in terms of and and or and stuff, you're throwing away those details. But what you're left with is something that still does the job, but in a way that's easier to talk about and work with, and all that stuff.

Speaker 2:

Exactly. You're saying the way that this works is irrelevant to this other piece, so I can hide it away and the other piece doesn't need to know how it works, it just needs to know that it works.

Speaker 1:

Oh, and something really important about abstraction. I think there's a misconception that abstracting that to abstract something, means to make it more vague or more general. And that's not necessarily the case.

Speaker 2:

Yeah, a lot of the time it makes it clearer because, like you know the, if you're like I don't know, like, let's say you, you have an array and you're grabbing the first item and you're grabbing the second item, uh, what are you doing? It's not clear. You're grabbing position 0 and position 1. Well, if you name those things as you pull them out, now in a sense you've done a bit of an abstraction there, like you've made a single word that describes what it's doing or describes what it is that refers to the first item in that array. But now when you see that word, word, it's clear what it is. It's not like I square brackets, zero, it's like buffer or whatever, whatever you've called the first thing in that array. That's an abstraction right there, like it's the simplest kind maybe let's even use a more concrete example.

Speaker 1:

We can go back to the bicycle gear thing. Um, the abstraction of gear is like so much more clear than if you have to say like okay, now I'm gonna push this lever so like the chain moves from one uh chain ring to the next chain ring or whatever. Instead you can just say, like I'm going to shift to a different gear, like that's so much clearer.

Speaker 2:

Yeah, yeah, exactly, and whether it's like behavior or data, you can kind of do the same thing. I was kind of talking about behavior mostly in my examples, but data it's like the same kind of thing. You have, um, you have a lot of data kind of sitting uh unstructured, and you can, uh, you can find ways to take you know three things and make them one thing, um, like uh, you might have you know street, um, city, county, country, postcode, right everywhere. If you pass those around, you're passing five things around. But if you make an object called address that has those properties and now you can just pass one address around, yeah, that's a great example you can just think about it as an address and you've minified all the complexities of what an address is into.

Speaker 2:

I'm just thinking about this as an address. It's not like these five different of what an address is into. I'm just thinking about this as an address. It's not like these five different properties of an address, it's just an address.

Speaker 1:

That's an abstraction um, okay, so I want to bring this back to.

Speaker 1:

Duplication is the wrong abstraction um because I just have like such a seething white, hot hatred for um, this expression and everything, all the effects that it has had. Um, I think that has a lot to do with the misconception that an abstraction is a generalization. Because, okay, there's the question of, like, why are we connecting abstraction with duplication? Like, to me those are two orthogonal things. They don't have to. There's no reason those have to be connected. But I think they do have to be connected if you believe that an abstraction is when you take, for example, two special purpose things and unify them into one general purpose.

Speaker 2:

General purpose.

Speaker 1:

Yep, yeah. And again this is an instance of seeing seeing a practice being applied in a very like confused, harmful way and having an overreaction to that and saying like whoa, whoa, like somebody spilled juice on the carpet one time, like no more juice of any kind in any situation um and so like that, it makes that uh sentiment make a little bit more sense once you think of it like okay, duplication is better than unifying two unlike things into this kind of frankenstein machine.

Speaker 1:

Unlike things into this kind of Frankenstein machine. Yeah, it's like. Yes, that is true.

Speaker 2:

Just don't do that, don't do that, don't do bad abstractions.

Speaker 2:

Yeah, but you can do good abstractions as early as you like, it doesn't matter. The other thing that is kind of in that expression duplication is better than the wrong abstraction is this idea that it's easier to go and fix 10 different things or change 10 different things than to change one thing. If you're doing abstraction, if you need to change your requirements later, you've made it easier by making it abstract requirements later. You've made it easier by making it abstract right. Like if I have 10 different implementations of a button that all have exactly the same or ever so slightly different sets of classes and attributes on them and now I have this requirement that buttons are to be different, it's not more difficult if I've made a single button component where I can go and update that you know that property like that's not. That's not more difficult than updating 10 different implementations that I might not be able to find um or like, might not be able to update in a consistent way that brings up a really the whole thing.

Speaker 1:

Yeah, it brings up a really interesting point. First of all, I'm realizing that I think a lot of people who repeat duplication is cheaper than the wrong abstraction. They might not even know what duplication or abstraction are and what is duplication? It seems obvious it's like the same code multiple times. But that's not even the right answer. Duplication is multiple instances of the same behavior and that could be identical code or it could be different code.

Speaker 1:

But if it's the same behavior, meaning that a change in one instance of the behavior means there's a logical necessity that the other behavior has to change also right, that's duplication and you can also have instances where the same exact code appears multiple times, but it's not duplication, like for example, rails controllers repeat a lot of the same code, and one thing that I also just hate so much is when people try to dry up controllers.

Speaker 2:

Oh yeah, by like moving stuff into abstract controllers.

Speaker 1:

Yeah, because it's like dude. That is not duplication, it's because you know one thing changing doesn't logically mean that another controller has to change it's yes it looks the same, but it's not the same behavior anyway. Um, there's also so many nuances to duplication, like it's not exactly that duplication is bad or that it's not bad. Um it's that duplication has costs and you have to weigh the costs with the alternatives.

Speaker 1:

Like, for example, if you have a piece of duplication where the the two pieces of of behavior are really close to each other yeah, like they're separated by like one line and it's abundantly clear that what you're looking at is duplication, and you're never going to miss one, just one of the two. You're always going to see them as a pair, and if it's really cheap to keep them in sync with each other, and if the alternative is to do something that's like even worse, then like that is a case of duplication that I would just accept because it's it's not worse. But take it. Take it to, um, the other extreme, if you have two pieces of duplication that are really far apart from each other and like you would never in a million years notice the other piece of duplication um or if it's really costly to keep the two pieces of duplication in sync with each other.

Speaker 1:

Yeah, and we should also mention, like, the consequences of those two things going out of sync, like if the consequences are high, then that's a really risky piece of duplication. So there's all these factors that go into it. Some pieces of duplication are absolutely fine and some pieces of duplication are disastrous, and so to make a statement like duplication is cheaper than the wrong abstraction, it's like you can't make a statement like that because duplication varies so much in its costs.

Speaker 2:

Some duplication isn't disastrous in the short term, but it's disastrous in the long term, like best example I can think of is in your views. So it really isn't a big deal if you have. You know, if every time you put a button into your views, you're copying and pasting I don't know hand lines of HTML and it's probably not a big deal. If they vary ever so slightly, they get out of sync with each other. Maybe you made the font bold on this one but you forgot to do it on the other one. At the end of the day, the consequences aren't catastrophic, but you do have a subtle cost, which is inconsistency in your design system. And then you have, I think the more expensive cost is when I'm thinking, when I see this button in the code, I'm seeing 10 lines of HTML which is like lots of different things. I'm not seeing the smallest named thing that represents what this chunk of code is. And so, um, you know if I can see one line that just says button, and then it has two parameters the text and the link or whatever. Um, uh, like that is so much cheaper mentally than seeing, you know, 10 lines of code with, know, huge numbers of tailwind classes.

Speaker 2:

Often is the case. You know and like it's just like the mental cost that you can get from something that's duplicated a lot by actually saying let's just name that concept, let's let's hide away exactly what HTML implements a button for us, and let's hide away exactly what html implements a button for us, and let's just call it what it is and give it an interface. Um, you know, the minimal interface that's required to describe that thing, um, you know, and it might have a bit more than just text and link. It might have um variant or whatever. Um, like you can, you can do all of that. And if you put the work in early to extract that abstraction, then I think it just really pays off long-term, not only when you're reading the code, but the next time you need to insert a button, you don't need to think, okay, where can I go and find these 10 lines of of code to copy and paste from? You can just say, oh, I remember, it's the button component yeah, 100 agreed.

Speaker 1:

Um, and to, to talk even more shit about the duplication is cheaper than the wrong abstraction thing. Um, it also, man, there are so many things wrong with it it also implies that creating the wrong abstraction is something to be avoided yeah, yeah, um you know that's okay, yeah, if it's the right abstraction for today.

Speaker 1:

It's fine, and you can change it later no, maybe, maybe it's even the wrong abstraction for today. Okay, and I don't even. I wouldn't say that it's okay, like I wouldn't look at it in terms of okay or not okay, just like I would more say that being wrong is inevitable, like you're guaranteed to be wrong about some proportion of the stuff and the answer is not to try to avoid being wrong. Duplication is cheaper than the wrong abstraction.

Speaker 1:

The sentiment there is to avoid being wrong. We shouldn't avoid being wrong. What we should have is ways to detect when we're wrong and make it easy to correct those cases when we're wrong. Right, completely agree yeah, and yet another thing. Um, duplication is cheaper than the wrong abstraction. Uh, kind of implies that we don't trust ourselves to come up with a good abstraction. It's like oh no, don't deduplicate this code, you're probably going to fuck it up. And it's like why, why do we trust ourselves that little?

Speaker 2:

uh, that's yeah, that's not helpful. But it's also this idea that, um, if you avoid trying to tackle this problem, that it will get easier as time progresses, that you know that the more duplication we have, the the easier it will be to to see, uh, how it should have been abstracted, which is, in my opinion, just not true most of the time. Why not Trying to do the abstraction is your quickest path to figuring out that that abstraction is wrong and to eventually learning more about the problem, to the extent that you can find the abstraction that works much like, works better for that scenario like I think I partly agree and partly don't.

Speaker 2:

You have to get um, I think a lot of the time you have to just try something and figure out that it's wrong and throw it away and try again, and this time you've got that extra context. Um, rather than like what you can end up doing, is it just being like okay, I don't have enough context to do it right now, so I'm just going to avoid it. Like it it's not going to solve in the back of your head, like you have to actually dig into it and and like try something.

Speaker 1:

Right and, and often those cases where a better answer is unclear, that is a clue that something is wrong at a deep and fundamental level.

Speaker 2:

Yes, yeah, you might need to zoom out and reassess your existing obstructions Maybe they're wrong as well. Like you can't take for granted that. Actually, this is another thing about it, right? It's this idea that once you have an abstraction it's concrete. It's not like it is totally valid when you're working on a new feature, a new requirement to reassess, are these abstractions that already exist in the code base now the right abstraction for this new requirement? Do I need to change these? Um? And if you're willing to do that, then I think the fear of getting the wrong abstraction is lessened and you should be willing to do that. You absolutely need to be able to do that. In fact, like um, it's just often the case that you have to change abstractions.

Speaker 1:

That's absolutely fine um, I don't know if this example is gonna serve our purpose at all okay, but it's it's the least worst thing I can come up with, and I was working on it today, so it's fresh in my mind. Um, okay, so saturn ci has a cli, a command line interface, um, and as of this morning, the cli could only talk to production. Um, and that was a problem, because the main thing that I use the cli for is when I do a test suite run. Sometimes I want to conveniently SSH into the machine that's running the suite. But I made some changes and I broke my local environment. But it was a total mystery as to why, and I knew it would be easier to figure out what's wrong if I could SSH into the machine that was running my local test run, because my local environment still has runners in the cloud. Okay, so I wanted to be able to have my CLI connect either to production or to my local machine.

Speaker 1:

The problem is the production credentials are hard-coded, so it has my production URL, production API key and production uses SSL, whereas local host doesn't, and so I needed a way to conveniently switch back and forth between the two. The problem was that I have I have an object in my code base called API request and into the API request I pass what endpoint I want and I pass in something called a client. I have a client object and the reason that's needed is because the client knows what host we're connecting to and it has the user ID and user token, so that needs to be passed into the API request. But I was finding it very difficult to make it so I could swap out the credentials and the host and what I realized I wanted to do oh yeah, and this is another thing Like client would call API request and you would pass in the host and the user ID and the user token when you initialize the client. But then the client never used those things.

Speaker 2:

And it was really confusing.

Speaker 1:

It's like, okay, I'm passing in host and user ID and user token to client, but then client never uses them, and the reason that was like that is because client was passing itself to API request and then API request was using those things. So that's a little bit like hard to follow, you know, and I'm like this is dumb. There has to be a better way to do this. So what I decided to do was I created a new abstraction called credential.

Speaker 1:

And when you initialize a credential, you pass in the host and user ID and user token. You pass a credential into. You pass in the host and user ID and user token, you pass a credential into the client and then when the client initializes an API request, it doesn't pass in its whole self, it just passes in the credential. And so, whereas before I had host user ID, user token in the client constructor, now I only had one thing I had credential, and it's like okay, where's credential used?

Speaker 1:

you could just search for other instances much easier to see where is this one thing credential used and where are these three properties used yeah, exactly, and so that was the reason I used that example is that was an instance where I wanted to do something, but I found it difficult. And it turns out, the answer was that my existing abstractions were imperfect and they needed to be rethought.

Speaker 2:

Yeah, that makes sense.

Speaker 1:

Yeah, again, I don't know how related that is to that other stuff we were talking about, but it's at least related to abstraction.

Speaker 2:

Yeah, again, I don't know how that, how related that?

Speaker 1:

is to that other stuff we were talking about, but it's at least related to abstraction. Yeah, yeah, ok, yeah, and you know, going back to duplication in general as an industry, I feel like 20 years ago we knew that duplication was bad and now, like people, people know, know, in quotes, they know that it's not bad and it's really unfortunate, this shifting wind, because it's like it's, it's kind of wrong and also, again, it's not good or bad. It just like has a cost and you have to figure out the cost and what the alternative is. Yeah, you have to weigh it out.

Speaker 2:

There are scenarios where I choose duplication over abstraction intentionally for a specific reason. So in Flex, for example, there's a ton of duplication in Flex that would be very easy to be like oh look, there's a ton of duplication in Flex that would be very easy to be like ah look, there's some duplication. I'm just going to extract a method that's going to do all of that for you and we'll just call that method in all those places that do this thing. But, like, the cost of calling a method in Ruby is not completely free and if you're doing something that works at the level of this code runs for every HTML element, or even for every attribute of every HTML element of every view that every user of every one of my gems users loads into their browser, that's happening a lot and so just the benefit of I'm going to inline this code so that it's a bit faster and I'm going to pay the cost of it being much more difficult to maintain.

Speaker 2:

Now, like that can be a reasonable decision to make. But you, like you said, like duplication isn't necessarily good or bad, it just has costs. Um, yeah, and the cost is, I think, worth it in something that is so generic like used by lots of different people, where even that one percent improvement it's going to make a big difference. Uh, across all the times that it's going to be used, so that was for performance reasons.

Speaker 2:

Yes.

Speaker 1:

Yeah, interesting Another thing.

Speaker 2:

Yeah, go ahead, possibly, like in unideal, like code decisions for the sake of performance, like using an array to store an object rather than an object, because allocating them is faster, or using, instead of an array of arrays, just having a flat array, and you know that every three items in that array is a pair. So if you index into, if you want to get the third set of three items, you index three times three and then the next three items are your set, but you've only allocated one array. You can do some silly things for the sake of performance, but at the same time, you need to be aware, I think, of this is what I'm giving up for, this.

Speaker 1:

Yeah, it seems like you're trading abstraction for performance.

Speaker 2:

Yeah, a lot of the time you can end up in a scenario where you can do that and that's a decision you can make, and I think the point is you just have to know when it's worth it and when it's not worth it.

Speaker 1:

Right, Totally agree. We should probably start wrapping up pretty soon. Um, but something I want to talk about before we sign off um, and you can say as much or little as you want for your part, um, but I personally am looking for a job right now, as we speak. Um, it's possible that by the time this goes out, I will not be anymore, but I at least am right now. I wanted speak. It's possible that by the time this goes out, I will not be anymore, but I at least am right now. I wanted to say a thing or two about that.

Speaker 1:

If you're listening to this podcast, there's a good chance that you've listened to this podcast before. Maybe you've listened for several years. So this message is intended for people who kind of already know me a little bit. Uh, I don't want to like go into the whole history of who I am and stuff like that, Um, but you, um, you you probably know kind of what I've been up to my my consulting work that I've done over the last couple of years. Um, a lot of it has been helping um technical leaders um do their jobs more effectively and and helping to train teams and stuff like that. Uh, you know me and you, Joel, said the thing at the top of the show of uh how like people aren't really. Well, I don't know if we said this, but like people often are not really changeable.

Speaker 1:

Um, you just have to get rid of people and hire better ones and stuff like that. So, unfortunately, the vast majority of the time in organizations, um, very little improvement is possible because there's certain things that are just unlikely to change, like people probably, you know, despite my recommendations, they're probably not even going to fire like one or two people, let alone like half the engineers in the organization or something like that. So there are very tight constraints and you can only change very little. Having said that, it's often the case that more than zero improvement can be made, and that's another thing that I read in that Jerry Weinberg book.

Speaker 1:

It's like, in fact, there was this quote he like put it in bold, or something like that it's like, despite people's best efforts, most of the time nothing of substance ever really happens, something like that, which is true, um, I'm like doing a terrible job selling myself, um, but anyway, I I enjoy working with organizations to like try to help tweak things, to make things at least a little bit better, um, because the improvements are usually modest. But I was working with the team over the last six months or so and I kind of felt like we hadn't made that much progress, and I said so to the team and they're actually like no, like, now that we've been working with you for a while, we think more about like, when we're about to make a change, we don't just think about like how can we make this change as quickly as possible?

Speaker 1:

but like how can we actually make an investment so that we can not only make this change, but make it so that when we need to make a change for tomorrow, uh, it's not all a giant mess and and our and things grind to a halt and stuff like that? So you actually have had a big impact on our thinking. Anyway, I really enjoy being a force multiplier and helping a whole team get better and stuff like that. Anyway, I'll pause there in case there's anything you want to say, joel.

Speaker 2:

Nothing, I don't have a whole spiel like that, but I am also looking for a job, um, and uh, yeah, I'm not really sure what, um, what that's gonna look like um, I just know what it's not gonna look like, um, and yeah, I'm excited. I'm like you know what gets me excited and actually, if we have time, I want I kind of want to get into this uh, motivation. But like, um, I want to build something that is really high quality like, and that should be, uh, like the product. You know the actual product and the behind the scenes, the code for that product and also the team behind that product. That is what I really enjoy doing. It's just so often the case that you don't get to do that, yeah, and so that, like, that's kind of the thing that I'm really trying to select for when I'm interviewing is like, is this going to be a company that lets me do my best work, or is it going to be a company that where everyone has kind of accepted this is the way things are?

Speaker 1:

um, it's never going to be great, but it's like good enough, um, yeah, I don't really know how to put that into yeah, no, I get exactly what you're saying, and I feel the exact same way, like you mentioned the thing about like working on some side project that was like unencumbered by the baggage of a of the way things are in most production applications and stuff like that for me at saturn ci, it's.

Speaker 1:

It's not just that way, for like the technical aspects of it, but like the, the product itself. Like so few organizations are even trying to make something good um, it's depressing. But like not only are they not making something good, they're not even trying, um, and they're like lying about it. They're like we want to be best in class or whatever, we want to have the best people, but it's like they say those things and yet what they're actually shooting for is just barely good enough.

Speaker 2:

Like something that checks the box, something really mediocre.

Speaker 1:

Yeah, and that is so frustrating because it's more enjoyable and fulfilling to create something that's actually good and it's, it's like a better business decision yeah like apple is you know, I think apple is a great example of an organization that creates really good, uh, products, at least, while steve jobs was there, um, and like it's an insanely for a period of time as the most valuable company in the world, um, and so yeah because they sweat the details, like, yeah, they every single apple product.

Speaker 2:

Like you might not love it, uh, you might think it doesn't work for you, but like there is a, a level of um, just just detail, um oriented design, uh, that comes across from every apple product. Um, that gives it something that you don't really get from many other companies. I think I think there's a few really good examples of this um and I've been thinking about. I think Steve Jobs is famous for talking about hiring 10x developers, and I think that there's obviously like different levels of skill in the developers that you that you hire, but I really think that, um, actually it was apple's um. It was probably apple's um own like goals and aspirations that led to their developers being so successful in this, in some sense, because, um, I think that the the biggest motivation killer, uh, for for people like us who really care about our craft, is like imperfection. It's like this, is like it's making something that's good enough but not great.

Speaker 1:

I'd put it a slightly different way for myself, yeah um, something that bothers me is just like stupidity, laziness, um, and sloppiness, yeah, and I hate to say it, but like all three of those qualities are rampant in the software industry and just in the world. Like there's that saying that 90% of everything is crap. It's like one of those Wikipedia laws or whatever. Yeah, just most things suck.

Speaker 2:

Yeah.

Speaker 1:

And I don't want to be somebody who is making just this crappy stuff. I want to make something that's actually good.

Speaker 2:

And this is why, when you do open source like this is why people spend so much time building such high quality open source things because the motivation is there, when, when you get to do a really good job of something and no one's stopping you from doing that. And my point is like it doesn't necessarily make you slower, like you would think that you know it would be you'd have to spend so much more time to do, you know, to do it to this, this standard, compared to this other standard. But actually your developers are probably very unmotivated. They're probably operating at like a tenth of what they're capable of.

Speaker 1:

If they were really motivated, if they really cared and I'll add this um, you'll be ableuitive, but I think it's true, because the way I look at the products that I build is I'm always building from a stable base. Yeah, I'm always building from a stable base, yeah, um, and that stable base is often having like cruft added to the top of it.

Speaker 1:

But then I don't put cruft on top of cruft and jank on top of jank, like before I add more to it. I'll take stock of the whole thing and be like, okay, what needs to change so this whole thing can be a stable base. I'm not just talking about the code, I'm talking about, like the whole product, because sometimes you need to take the thing and like reconceptualize the the entire thing a little bit in order for the whole thing to be a solid foundation.

Speaker 1:

but if you're always doing that, then things can be very fast and smooth, whereas if you're just adding jank on top of jank, which is what most software products do like, it gets really like I've said before that, like a product's code base. The quality of a product's code base never exceeds the quality of its ui design, because the ui design is a reflection of the concepts that the product is made out of. If the conceptual framework of the product is corrupt, then that corruption is necessarily going to be reflected in the code base and no matter how good of developers you hire, they're never going to be able to overcome that corruption because it's baked into the conceptual model of the product. So the conceptual model of the product has to be kept on top of at all times so that it's always sound, and if you do that it's way faster than if you don't. Okay, well, that covers the topic of working on high quality things.

Speaker 1:

Yeah, that's definitely something I'm seeking. Sometimes people ask me, like what kind of job are you looking for?

Speaker 2:

It's a little frustrating because it's like I don't know, I think kind of like you.

Speaker 1:

I know what I don't want to do, but it's like at this point in time, like 20 years into my career, I can do almost anything and I don't really want to like arbitrarily choose something because that doesn't really like.

Speaker 1:

Why would I do that? But so far I've interviewed for a CTO role, a manager role and at least one just like IC developer role and I'm open to all that stuff. And, dear listener, if you're interested in talking with me about potentially working together, my email address is jasoncodewithjasoncom. If you just search me online, I'm pretty easy to find and contact. Anything else that you want to say before we go, joel.

Speaker 2:

No, I think we've covered a lot.

Speaker 1:

Yeah, we definitely have covered a lot and if you've made it with us this far, dear listener, I admire your. I always have a hard time saying this word Intrepidity. I admire your intrepidity and Joel thanks so much for coming on the show.

Speaker 2:

Thank you.