Episode 43

Habits 2.0

00:00:00
/
00:51:29
Your Host

About this Episode

This podcast episode from The Acima Developer Podcast crew dives into the concept of developer habits, focusing on how habits are formed and their importance in software development. The discussion begins with a recap of the previous episode, emphasizing the "four laws" of habit formation—making it obvious, attractive, easy, and satisfying—as presented by Justin. These principles are highlighted as foundational to acquiring and maintaining good habits that can significantly impact one's personal and professional life.

The conversation shifts to personal experiences and practices that contribute to productivity and good habit formation in a software development context. Matt shares his perspective on taking ownership and how it has been pivotal in his career. He references the book "Extreme Ownership" by Jocko Willink, stressing the importance of accountability in software development. David expands on this, discussing how owning the success of a project often involves being open to feedback and adjustments, even if it means stepping back from one's own work.

The latter part of the discussion delves into Test-Driven Development (TDD) and its role in productive software engineering practices. Eddy brings up the challenge of spending too much time refining projects instead of coding, questioning the productivity of such tasks. This leads to a row on the efficacy of TDD, with several participants, including Matt and Justin, defending its importance not just in writing quality code but also in understanding problems more deeply and fostering productivity. They argue that TDD, when properly applied, not only helps in reducing bugs but also in enhancing the developer's understanding of the codebase, ultimately leading to more productive coding practices.

Transciption

DAVID: Hello and welcome to the Acima Developer podcast. We are doing a part two on developer habits. Justin, you kicked us off last week. I'm going to pick on you again. Give us a quick summary on, like, what are the elements of a habit so that we can kind of just jump straight in. Last week, we spent most of the time talking about, like, why and how of habits, and we didn't get into too many specific engineering habits.

JUSTIN: Right. One of the main things is, and here I'm just going off a table of contents here that perhaps is a good, quick summary, there were four laws that kind of make up a good habit or how you can acquire a habit. And the four laws were: make it obvious, make it attractive, make it easy, and make it satisfying. All of those require perhaps a little bit more work than just the desire to do something. If you actually go through and do what's needed to follow those four laws, you are much more likely to actually acquire that habit and have it make a change in your life. That's, like, the two-minute summary.

DAVID: It's awesome.

JUSTIN: [laughs]

EDDY: I kind of want to, like, punt this to individuals who weren't present in our last just to kind of get, like, a fresh perspective (if you're okay with that, Dave) just to see, like, what other people's opinions are on what makes them more productive.

MATT: I'm happy to talk about it. For those of you who do not know who I am out in GV land, my name is Matt. I'm one of the engineering leads over here at Acima. For me, one of the most important things that has helped me form really good habits over my career is taking ownership. I think it's extremely important in this industry and, you know, just in life in general.

There's a book, maybe some of you may or may not have read, called Extreme Ownership, written by Jocko Willink, and he was a Navy SEAL, I believe, platoon leader. And he's written a couple of books, but that one in particular really helped me. And the preface of it is that we just need to take accountability and ownership over all of the things that we're doing. And in software, part of that is not getting married to your code but having ownership of your code, have some pride in your code, take ownership of bugs, anything that arises with it. And I feel like that's going to help you write better software and think through your problems up front.

DAVID: I like to think of that by saying I want to take ownership of the success of the project. And sometimes, that means letting somebody rewrite my code or somebody push back on my design because cash flow doesn't care about your pretty, little design. Cash flow cares about whether or not a customer can get through the system. And so, when somebody pushes back on me, even if it chafes, I'm often very quick...and this might be an internalized habit, but I try to be very quick to say, "What do I really want here? Oh, this hurts, but it's getting me what I want." So yeah, I'm on board with this.

EDDY: So, I wanted to kind of throw something out there, especially for people who have more experience than I do. The past few weeks the project that I'm currently working on and one I'm involved in has required a bunch, a bunch, a bunch of requirements in order to finally get some work done and finally start writing some code.

Here's the thing, and here's kind of where my perspective lies is: refinement, at least for me at a high level, isn't productive. For me, I've always defined productivity as how much code you're pumping out, right? Because those are the metrics. Those are what really define you as you doing your work. So, if most of your time is consumed on refining a project, for example, can you really, at a high level, consider that a productivity effort, and does that really help? Can you constitute as that? Is it kind of, like, a gray area between you...it's a given. In order for you to be productive, you need to have something defined in order for you to work, right? So, I feel like I know the answer, but I want to get people's opinions when it comes to productivity.

JUSTIN: Like, a classic bad metric is lines of code. I could be super productive. I could just sit with my hands on my keyboard and just churn out code, but that doesn't necessarily mean anything, right? Like, it has to be quality code that meets demand or does something, right? Like, you can't just say lines of code or how much code I've written. I think if you measure that way, you're going to end up going the wrong direction.

DAVID: Goodhart's law says, "When a good measure becomes a goal, it ceases to be a good measure."

MATT: Yeah, I think refinements are every bit as important as the actual code you're writing. When we get requirements, one of the key things about refining this work with the engineers is making sure they have a good understanding of the problem. Without a good understanding of a problem, you can't solve a problem. And if you front-load your work with a good refinement, make sure that your requirements are defined, and clear, and concise, you're going to write good code.

It's just like test-driven development, right? If we're writing our tests first with a good understanding of the problem and a good understanding of the outcome, that almost writes our code for us. Versus if we're doing that after we're writing the code, then we're writing tests to pass against the code we just wrote, which is kind of contrary to what we really want to accomplish. Because we don't know if that code we just wrote is meeting the requirements exactly as defined, whereas a good written test will.

DAVID: Mm-hmm. You end up writing the test to follow the code, and if the code is sort of a sideways implementation of what you thought the card was going to do, the test will then become a sideways implementation of the following of it, right? But if you start with the TDD, you're like, no, this is what it needs to do. You also ran into the thing of like, oh, the code is hard to test, and that's because you wrote the code first. If you had started with the test, the code would be easy to test because it would have to follow the test.

EDDY: I have a caveat to that, Dave, and I think...I spoke with Tad about TDD a few weeks ago. And I told him, I'm like, "How is it possible for you to write a unit test for something, you know, that you don't even know how you're going to write the code for?" So, it makes it extremely difficult to, like, set up all the instance doubles and all of the mock data and all of the stub data that you need. You don't even know where you're reaching, where you're looking, right?

And so, to me, I feel like it's more like a skeleton TDD, where it's like, cool, I can probably get my get, or my it blocks and my context set up the way I think they should be, but that's as far as I've gotten, as far as TDD. I've never actually implemented anything and then wrote the code to pass it if that makes sense.

DAVID: You said one word at the start of that paragraph, and I knew...I'm like, yep, you're headed down the wrong trouser leg of these pants: unit test. A unit test is how you assert that this tiny, little piece satisfies what the whole should do. That's where TDD starts. You write a test to say, "Does the whole thing behave correctly?" Then you start breaking down into the pieces, and then you write unit tests against those. You don't write a unit test to say, "Does this have a callback on the database before save?" until you have something higher up that says, "Hey, when I do this, it updates this other thing." And so, you come out of...it's a multi-layer approach.

EDDY: Right. So, I had a misconception of what [inaudible 07:58] was, right? And so, like [laughs], when I spoke to Tad, I was like, "Oh, gotcha, gotcha. So, you're not writing all the branches," right?

DAVID: Right.

EDDY: Like, making those branches pass. You're essentially doing, like, this is the happy path.

DAVID: Eddy, I want to sidebar with you afterwards and bang out this idea because you just sparked an amazing thought in my head. And poor Justin is just waiting for us to talk about habits [laughter]. But you just sparked an amazing thought in my head, which is, I think a lot of people push back on TDD because they're like, well, I wrote the code, and then the testing was dumb and stupid, and hard, and after the fact. And they look at TDD as write the dumb, stupid, after-the-fact test before writing the code. It's not going to work.

It's like, you have to write something different first, and then you're like, oh, if we were just doing that, right? But yeah, I just realized that, yeah, if you see all this stuff, all the baggage that testing and awkward tests are, if you just move that ahead and try to do the awkward testing first, it's much harder to do that. Why would you do that?

ENRIQUE: Basically, TDD is it's like a good practice when you have a domain knowledge, what you're doing. Because sometimes, for example, here at Acima, it's been the first time where I work with mocks instead of intensively writing the database when you write specs and start with specs. For someone like me in this context, when I don't know anything about the domain, and I don't know anything about how things are mocked, it is really, really hard. I really need to go into the UI, understand what is going on, go into the controllers, and see that everything is working correctly then I write specs.

MATT: Yeah. Back to your refinement comment, Eddy, if you have a really good understanding of the problem and we're writing stories properly and breaking them down to a level at which I feel a story should be broken down, you don't have to have a whole lot of domain knowledge. You just need to know what's coming in and what you expect out, and if you have that understanding, you can write a test.

And you don't have to write the entire test for it to be TDD, right? You know what's going to happen first, so you write that piece of your test. And you should run it, and it should fail. So, you implement that piece, and then you go to the next step. Let's write the next step in the test for it. And you can just step through it that way. And that actually, in my opinion, makes it so you don't require as much domain knowledge to be able to write software in a big application.

DAVID: For me, the secret is to go up a level and identify the behavior that the system should follow. That you can test in a very generic way. It's like, oh, when these things go in, they need to come out sorted. Now you go write a unit test that says, "Oh, I need you to call the sort method," or "I need you to sort it in the database," or "I need to use a B-tree," right? But the behavior is: it should be sorted when we're done, that if I pass in A, C, B, I should get A, B, C out. And how we got from A, C, B to...right? Who knows? We could split the text and pass it through...who knows, right? That's the thing.

And I think if you start your TDD with, okay, I need to mock out the database SQL query with an expect an order clause so that it will sort, oof, that's not test first. That's [chuckles]...Tad will call me on this one. That's [inaudible 11:27], which is test after I thought up the implementation, but before I wrote it [laughter].

MATT: So, and I think that's a good habit to form, right? TDD is going to help us write better code and more accurate to the actual requirement.

TAD: I think when you start out, you're right. You get something, and you're like, I don't really know how to do this. I don't know what this code is going to be, right? And I know, for me, a lot of times, step one is kind of poke around and brainstorm and kind of look [laughs] at where I'm putting the code and what's going on there. But that could be tests, too, right? Like, if I'm exploring the code and I'm testing, I'm like, what does this gem do? What could this code look like? What's the environment that this feature is going to be written in? I could easily write a test that kind of sets that up for me to poke around in.

JUSTIN: One of the things I'm picking up here from TDD, and I've done limited TDD, I'm not as good at it as I would hope, but just if you generalize it to kind of, like, a habit, I think it's worth recognizing that any or most good habits that you think are good habits when you start out at them, you're going to suck.

And it is something that you have to realize you may need to push yourself, or do other incentives, or try a different strategy to do the thing to be able to actually make that habit stick. If one thing isn't working for you, recognize that, and then try another thing, or try a different strategy, or talk to people, all of those things. You know, seek out help that helps you, you know, get you closer to where you're going to try to get to the habit.

MATT: Yeah, good habits are hard to form, right? There's a reason that millions of people make a New Year's resolution that they're going to exercise this year. And then, the gyms are totally packed for about three weeks or so. And then they just fall off because good habits are hard to form. And they're worth it though. The effort is worth it.

EDDY: Since we've been talking a little about TDD, and I kind of want to stay on track a little bit, would you go as far as to say that TDD will make you more productive? Assuming you've honed the skill, and it's just, like, second nature. And you're just like, cool, I'm going to do TDD, and that's it. Like, would you compare someone who is more senior, who's already acclimated doing TDD, and categorize that essentially as, yeah, that makes me more productive than just running the...or banging out of the code first?

JUSTIN: TDD itself is like a combination of a bunch of different things, like breaking down problems, knowing what your target is, you know, all those things kind of add into like, hey, I'm good at TDD now.

MATT: Yeah, so look at it from this perspective: if I'm writing accurate tests on a problem that I understand, the likelihood of me introducing a bug into the codebase is much, much lower. So, from a productivity perspective, I would say if I'm introducing bugs into the code because I'm not testing and I don't understand the problems that I'm trying to solve, that is significantly dropping my productivity because I'm going to have to go back to it or someone is and fix it, which is going to take even more time. It's going to take debug time, tracking things down, and then, on top of that, coding time. So, if you can avoid all of those things by writing good tests upfront and solving that problem, I would 100% say that yes, it is going to increase your productivity.

DAVID: I think a lot of people push back on TDD because they're like, I'm not sure how I'm going to solve this problem, so how am I going to test it? This is really percolating; this idea of TDD is not test after but backwards in time. If you go up a level and figure out what is it that I'm trying to solve, that's the thing that you test and that you can do in advance, and then you go down slow. And then, when you go down a level, you have to write a unit test that say, "Does this code do the...?" Yeah.

You guys have fried my brain here. I'm, like, smoking neurons as well as we speak and, like, trying to get my head wrapped around this idea. What I will say is, if I don't know how to solve something, TDD lets me come at it from above and sketch in and say, "You must satisfy this to make this happen." Where, if you are expecting to come up from underneath of, like, well, I'm going to build a thing that combines this, and then recurses into that, and then calls this query over here, and then; eventually, I have a thing that does the thing in the end, TDD sucks when you're trying to do that. That much more suits the write it, test it, write it, test it, write it, test it.

And there your unit tests are, like, regression specs. They make sure that the next three things that you do don't break the first thing that you did, where, for me, TDD gets out in front. I was talking with Tad about this earlier in the week. I wrote a spec, and then I wrote the code. And the spec was just there to help me keep my thinking straight and make sure that it would do the thing. And when I was done, I had a spec that did not explain what the code was trying to do. And it duplicated a lot of the, like, external stuff that really wasn't useful, and it forced a database hit, which made the thing very, very slow.

And after we had the whole thing written out, the spec was superfluous. It was useless. It was not a really good regression test. It was just going to be a maintenance nightmare. So, I wrote the test. I got the code working, and then I deleted the test and I pushed up the PR. And Tad called me on it because I did it on two PRs. And the second one, he's like, "Where's the test for this?" And I'm like, "Oh, that actually was a good test. I shouldn't have gotten rid..."

The first one was just a database scope, and, like, to test that in Rails, you're going to duplicate Rails, and it was kind of useless. And there's not really a clean way to just say, "This scope should exist." So, anything outside of that was just duplicating. Oh, I kind of start to receive a message chain, but yeah, the arguments could be all over the map.

MATT: To be able to do this, right, you need to know what is your expected input, and what's your expected output. It doesn't need to dictate your implementation. So, it's not going to write good code for you, but it is going to solve your problem, and it's going to prevent you from breaking things when you make choices.

DAVID: Yeah. You just touched on a really key distinction there, Matt. You have to know what your inputs and your outputs are. When we come at these tests, and we're like, "This testing is hard," it's because we're coming at from the other side, and we're saying, okay, I should expect this model to receive the message chain of dot where, dot order, dot...you try constructing the ActiveRecord query, which is all implementation, right? It's all pure implementation, and we're trying to mock and stub that out. And you're standing at the wrong end of the code for TDD when you do that. Man, I feel a blog post coming on. Remember blogs? Three people on the call are like, "No," [laughter].

EDDY: Dave, [inaudible 18:27] might actually have something that's really interesting. And you said test-driven development allows you to come at it from a different perspective, right?

DAVID: Mm-hmm.

EDDY: Like, at a higher level, then we're acclimated [inaudible 18:36]. I want to say something about that. And there's a concept, you know, that is pretty notorious around the tech industry, especially for programmers, and it's called rubber ducking debugging. And I've associated writing tests...I used to not like it, especially doing RSpec because the DSL is crazy, right? But, like, once you, like, really narrow it down, it actually caught...I've caught myself actually approaching the problem differently. For me, it's sort of like a rubber duck, where I'm able to express it in a different way that I wasn't looking at it before, so a new perspective.

Now, we're talking about productivity. That is a prime example. Now, I need to test my code, but my code isn't working. How am I going to set it up? And then, suddenly, the setup is like, oh, that's why it's not working [laughs], right? And you're able to go through it line by line in a different angle, right? So, when we're talking about productivity, I think TDD, in a sense, at least I have some experience with it getting me unstuck, right? Because it's able to provide a different perspective.

So, I do kind of want to go on record and say hey, I don't hate TDD. I've seen the benefits on why we do it, right? And it's keeping ourselves in check. And it's also a way to solidify the code that we wrote is on purpose [laughs] and that we truly understand it.

MATT: Well, right. And it's up to the engineers to figure out the middle, right? And, again, it can't dictate good implementation, but it prevents you from breaking your inputs and outputs. And as long as you know those things, test-driven development is absolutely relevant.

DAVID: Yeah. Matt, you're feeding my brain hamster. It is not an input or an output to assert that ActiveRecord receives this convoluted message chain, right? That's implementation support to make your test go a certain way. And this is the kind of spec that we don't do in our code a lot because we have a very large test base, and we're always trying to speed it up, and we've had productivity hits from trying to talk to the database.

But, like, when you have a thing that says, "Hey, I'm going to write this kind of contract and this other kind of contract. And I'm going to assert that when I call this thing, I get the first contract and not the other one," and that's all handled by database stuff. That's stuff that we would be tempted to stub out the ActiveRecord query and da da da. And that's very implementation-specific. And those are not inputs and outputs, right? The inputs were I had these two contracts, one was even, and one was odd, or one was red and one was blue. And when I ask it, "Give me blue contracts," I need to make sure I got the blue one, and not the red one. And that's input-output. And now it doesn't matter.

Eddy is frantically waving, "Mike's on the call. Mike's on the call."

MATT: [laughs]

DAVID: Welcome, Mike. We were just talking about...well, today on the Acima Developers podcast; we are baiting and switching Justin on his habits stuff. We let him give a two-minute introduction on habits, and then we went down the rabbit hole of TDD and testing. Next week, we'll talk about ADHD and bicycles, which reminds me of a story about bicycles.

EDDY: To be fair, Mike, we also have circled back, and we were able to kind of deduce that TDD really does help with productivity.

MATT: I think it would be hard to argue that it isn't a good habit if you're doing it properly.

MIKE: You touched on something there: if you're doing it properly. There is actually some debate in the community about how religiously you should follow TDD. I think there are circumstances, particularly when I'm doing more exploration and generally within existing code, where I might not write TDD first. But then, again, sometimes it's for sure great to have a test, right? And you can use the test to see if something works. You can actually use the test to, you know, test that interface to see if it works. There may be some personal application there, but in general, TDD, while it may take a little overhead up front, leads to a reasonably performant process and generally leads to stability, right? Predictably, which is always a good thing.

EDDY: Can I just go ahead and also go on record in saying having TDD, specifically in RSpec where you have a context, and it block, it dumbs it down for me to better understand what that method is doing. So, when we're talking about productivity, like, my biggest complaint really is if this method is really complicated, I hate that it doesn't have comments. If you think it's complicated, either leave comments on there or have some gnarly, gnarly test that really breaks it down and tells you this is the context. This is the it block. This is the behavior. This is the [inaudible 23:30].

And having really good tests has actually helped me better understand what the purpose of that method really was and the intention behind it. So, again, circling back [laughs] to productivity, I was better able to have, like, a better-defined picture that attuned on, like, the changes. And I felt safer doing it as a result.

MATT: And writing good, clean code is much more productive than writing code that introduces bugs that you have to go back and fix.

DAVID: Ooh, but in the first five minutes, it's slower, right?

MATT: Oh, 100%

DAVID: It's so much quicker, right? I can jam in a fix that solves the thing that, you know, it's like, oh, hey, look, even-numbered contracts are the ones that are violating the TCPA standard. So, I'm going to reject texting messages for even-numbered contracts. Fixed it! It took me 10 seconds.

MIKE: [laughs]

DAVID: There might be some maintenance later. Future me will hate me.

MATT: Never [laughs].

EDDY: Justin, circling back [laughs] to the topic at hand, do you want to continue?

JUSTIN: Well --

DAVID: Actually, the reason we went...sorry. Sorry to jump on this again. I am actually steering towards you, Justin. The reason I brought up testing, in my particular bit, is that somebody reminded me on Twitter this week if they haven't seen the test fail, they assume that the test is wrong or hasn't worked. And so, this person has a habit that when they write a test, they make it fail every time. If they haven't seen it fail, they assume that the test is either not executing or not touching the code that's being exercised.

And I don't always follow that habit, and I will get bitten by a test that seems to be passing, and then I will break the code. And the test continues passing, and I get very alarmed. And then, I get very good about following that habit for a while.

MATT: Yeah. When I first learned how to do test-driven development, that was a requirement of the team.

DAVID: It's a [inaudible 25:30]

MATT: You know, we were programming, and we said, "Okay, it's passing. Now let's make it fail."

EDDY: If you make it fail, suddenly you have your unhappy path, right?

DAVID: The old Red-Green-Refactor mantra was, you get to red first, then you get to green fast, then you refactor until the code is, you know, not a maintenance nightmare.

MIKE: And I think that there's something there. I think that a lot of times we think, I need to test the thing, and so we're not very systematic about it. We say, okay, we'll start with a happy path, and then I'll start doing edge cases. And after that test passes, we think, okay, I've got pretty good coverage. Now, let me start covering the other things. And I think that that way of testing in this way that I've done it in the past, that I've changed over time, has some flaws. It really isn't structured in order to document your code. And we've talked about this in other podcasts. It's structured in order to help you maximize your efficiency in that moment to cover that specific part in the flaws.

And instead, I like to approach my code and say, well, what are all the branches? And I usually like to test all the broken branches first. And if you do that, you have verified that, you know, all of your validation failures are actually failing out, and then your happy path is kind of the last piece you get to. It takes a little bit longer, but then you get full coverage. You get better documentation out of it and avoid a lot of that risk of like, oh yeah, the happy path test works when maybe that wasn't even testing anything.

MATT: You're preventing downtime in the future.

EDDY: I don't know if it's crazy. For me, I like to see green dots first. Like, it super, super, makes me a lot more enthused to write code. I joked about this on a previous podcast, like, green dots have become my favorite-colored dot.

MATT: On that note, if you are doing test-driven development, it's going to fail first because your failure is what's driving your development.

DAVID: And I don't think those are incompatible statements, by the way, or even what Mike was saying. Like, I still see it. In my head, it's all green dots, right? That green dot means that this is exercising the code and that it's passing. So, we get to red first so that I know it's executing the code then I make it pass. Now I get my green dot, and I get cookie. It's satisfy. It make it work. And testing the unhappy paths, those aren't red dots, right? Like, the unhappy path is you tried to save a username that was, you know, 4K long, and the database only holds 50 characters.

There must be a validation error that says, "Name must be less than 50 characters." And if I save a 4k thing and it writes it and it doesn't raise a validation error, but it throws away [chuckles] 3.9k of the name because it only said, "That's a fail," because it failed to validate, so you make the validation pass. And you get the green dot, and so it is; it's all green dots. At least in my head, it's all green dots.

MIKE: Yeah. It's all green dots all the way, but you're testing all the edge cases either way.

DAVID: Yes.

MIKE: So, you don't have to write a test that doesn't cover that case and then have to go through the pain of seeing the red dot. What you do instead is you write a test that captures all the bad cases and make sure that those all show green. Like, make sure those failure cases actually happen.

MATT: Let's take an integration test with MVC. First thing we may do is load up a model, right? But because we're doing test-driven development, that model doesn't exist. So, first run it's going to fail. Then, we go create our model. Next line, hey, we hit this endpoint in this controller. It then loads the model. We run it. It fails on that endpoint because it doesn't exist. It drives you step through step. And that's what I was trying to say, Eddy, is, sometimes, when we don't understand a domain, going about it in this manner helps us understand the domain but also makes it so we can work inside of that code without that full understanding.

DAVID: The other thing that gets me thinking is, like, when we get a ticket that we have to work in the code, it doesn't say, "Use a red-green or a red-black tree to sort the data in the database." You get tickets that say things like, "Stop sending text messages to customers who have opted out via TCPA because that's against the law." There's nothing in the database that says, "Don't break the law," right? And yet we will pull up code and, like, ultimately, the fix is going to be to add a where clause in the thing. When we do this, we need to join on the TCPA, you know, opt-ins or whatever, or however you can implement it.

And we might be tempted to write a test to say, "Are we checking the database for this one thing?" But if you're starting with TDD, you start with a customer who has opted out and another customer who's opted in. And you try to send them both messages, and one of them should receive the message and one of them should not. And that's pure io. Now, it doesn't matter how it gets developed, right? It literally could be, "Hey, there's this queue that we send to human operators who punch things in on a phone to call people, and that queue should not get the customer that opted out," or it could be a database query, or it could be there's a million ways to select data, right?

MATT: Yeah, because you know your inputs and your outputs.

DAVID: Right. When you get this thing, don't try to write a TDD of changing the way we filter from a list. You know, it's like, how am I going to reject on the MapReduce? No [laughs]. Start with your input. Start higher. Go up a level.

EDDY: I kind of want to punt this to, like, individuals who weren't here in the last podcast. And I kind of want to get their perspectives so more tailored towards Matt, Tad, and Enrique. What are some of the habits that you typically gravitate to when you're stuck on something, and you're trying to get more productivity? Like, what are some of the things that you do, like, instinctively that get you more productive?

TAD: Talk to someone else. A lot of times, if I just talk through it...like, you were talking about rubber duck earlier, Eddy, right? If I stop, talk through it, then, usually, I'll get some clues. I'm like oh, there's some variables I need to check, or, oh, there is where I might have gone wrong, right? Just talking it out, talking it through, even if they don't give me any feedback, is often helpful.

MATT: For myself, I would say my first steps usually aren't reaching out unless I know someone has a context on the problem I'm trying to solve. But I do have things that I almost always do; one would be Prys. I love Pry, you know, ruby-specific, but debuggers, breakpoints. And then, I step through because, ultimately, if you're trying to solve a problem, you need to know where that problem is happening, and I will always time-box a problem, always.

One of the mistakes people make early on in their career is they don't want people to think they don't know something or they're inadequate, so it's a pride thing. Overcoming that and being able to reach out and ask questions will significantly help your process. Every day, I'm reaching out to people. It doesn't matter who it is. It doesn't matter what level someone is. Everyone has something to offer that we don't know. So, I think a good habit is asking questions and just being able to communicate those questions to your peers.

JUSTIN: One other thing that I think is helpful is to...it's been mentioned several times before, but breaking down the problem such that if you are stuck on one particular thing or kind of a general thing, you're like, oh, okay, how do I break this down? And keep on breaking it down until you get to something you can solve.

And then, by the time that you have perhaps identified, you know, okay, I can solve these five sub-steps, but I can't solve six, you've identified enough to bring it to somebody else who may have context. Because they'll probably ask you, "Oh, did you try A, B, and C? "And if you were able to break it down, you'll be able to go to them and say, "Okay, here's my work so far. You know, I don't have any idea how to do this," But rather is, "Oh, okay, here's the original problem. Here's what I've tried to solve it. Here's the progress I've made, but I'm stuck on this particular one," and just explain to them everything that you've done.

And then, they'll be able to answer, "Hey, did you try this?" Or they might be able to answer, "Hey, you're barking up a wrong tree." But it's also, you know, you combine that with all the other suggestions of time boxing and things like...you don't want to go too far down the wrong rabbit hole. So, there's a balance to be had there. But, you know, do your work and do your homework and try something.

EDDY: Oh my gosh, I've never thought about timeboxing a problem [laughs]. That's so cool. Just to bring everyone kind of up to speed, Tad and I were pairing earlier today, right? And we were trying to figure something out. And he said, and it's kind of stuck with me even now, he's like, "Okay, let's try to figure out this problem. But if we can't figure it out, we'll timebox it. We know how to fix it another way, but we don't like this other way. We're going to try to fix it this way instead, but we'll timebox it for, like, 10 minutes." If we can't figure it out in 10 minutes, suddenly, your productivity kind of starts spiraling down because you're still stuck on the same problem.

So, just saying, "Okay, if in 10 minutes we can't figure this out, we still know the solution. We'll do the other solution as a fallback." But you're still moving forward on your problem, right? Oh my gosh, you know, timeboxing is so cool. I didn't think of that.

MATT: [laughs]

TAD: Because I was like, there's an elegant solution here if I could just find it, right? And there's a way that works, but it's kind of ugly. I'm like, "Eddy, if I can't find the elegant solution, we're just going to...in five minutes, we'll stop and do the ugly thing instead."

MATT: That's kind of a good segue into what else I was going to say, and that is stepping away. Oftentimes, just stepping away from a problem is a good idea. So, if you have an elegant solution in your head and you think this other one's sloppy and you implement it, step away. The elegant solution may come to you. You know, sometimes just kind of walking away from something, giving yourself a breather because we tend to get tunnel vision. And I think getting outside of that tunnel is extremely helpful.

DAVID: I used to rock a standing desk, and I legit believe that the number one value of the standing desk...nothing to do with health or with any of that. The number one value of the standing desk was that I was much more likely to step away from the computer once every 30 to 60 minutes just to think about the problem. And it stopped me from fixating and tunnel visioning on a problem for two hours, three hours, five hours so many times.

MATT: We want to solve problems. That's why we do what we do, right? And I think all of us tend to get tunnel vision and get stuck in these problems because we're so stubborn that we just want to solve them. And a lot of times, walking away for a few minutes can help do that.

DAVID: I just realized that dovetails perfectly into Justin's habit thing that if you're standing up at a standing desk, it makes stepping away to switch from fast thinking to slow thinking, to tight focused to, like, spreading out to wider thinking, it makes it so that that's easy. It's attractive [laughs]. There's no start-up cost. You just take a step back, stretch your arm, and then just walk over to the window, right? Because there's no pushback, change state, stand up, deep breath. There's none of that big state change. You're already standing up. Just walk over the window and breathe.

ENRIQUE: I'm trying to Google what time box a problem means.

DAVID: Oh. It means to decide in advance how much time you're going to spend on this. You draw a box on it on the calendar and basically say, "We're going to work on this for half an hour." The value of this is you can say that, "We've got a bad way to do it. We don't want to do it this way. But it's not worth spending 10 hours on to avoid this problem. If we can't solve this in 30 minutes, it's not worth solving."

So, you just draw a box around it on the calendar and say, "We're going to work on this for 30 minutes. And if we're done, we're done, and if we're not, we're not." Or at the end of 30 minutes, you can say, "We're really close. It's worth another 30 minutes." You can extend your time box. But, again, you stay boxed. You don't let your time become open.

MATT: If I have a problem I don't know how to solve, because a lot of us are self-learners and we like to just figure things out ourselves, we say, "Okay, I'm going to spend an hour trying to figure this out on my own. And if I don't have a solution, then I'm going to go talk to somebody else and reach out."

EDDY: I love the fulfillment, though, that I get if I resolve the problem myself. Like, there is some sort of joy in myself, like, self-pleasure, where I'm just like, oh, I did it, right? Like, I was able to overcome that, and I found the solution that I was looking for. However, there's times where, like, I've been stuck in a problem for, like, an hour, reach out to someone who I know will have the answer and be like, "Hey, I have this failing spec, and I can't figure this out, you know" And they're like, "Oh yeah, it's because you need to do this." And suddenly, I'm like, oh man, why didn't I see that before? But there's value to that because, like, that solution gets cemented in your brain much better because you struggled to find the solution much longer.

MATT: I think a good habit, too, since we're talking about habits, is when you do finally reach out for answers and information, make it a point to understand why. Instead of just getting the solution, understand why it is the solution and how it is a solution. That way, the next time you run into a similar problem, you have the tools you need to be able to solve that problem.

EDDY: Yeah, for me, I found that I need to struggle on that problem for a little bit longer so that I can better understand the issue so that when I do get the answer, I understand it more in-depth.

MATT: Yeah, and --

DAVID: I think it's useful to know in advance, do I want to use this solution to solve this thing in the world, or do I want to work on creating the solution? Sometimes I don't want to carve wood. Sometimes I want to build wood carving tools. And sometimes I would rather work on my software tooling than build software with my tooling. And so, knowing in advance, what do I want to do?

Like, if I want to build the tooling, I don't want somebody else's help. I want to discover it myself. I'm in it for that joy. And if I go ask someone for the answer, I give up that joy. But if I just want to solve the problem so I can do another thing, every second I spend trying to find the solution is time not spent using the solution to get what I want. And knowing to switch hands and say, "Oh, just give me the thing," right? "Google, give me the answer. ChatGPT, give me the answer," because I just want to get on down the road to solving the thing.

MATT: Yeah, I think sometimes, I mean, and we're in a business environment, so we do have to limit the time we spend on these problems. But if we're getting the answer, getting the solution, if we also get an understanding of how that solution was created and why that is the solution, then the next time we come around, that tool is in our toolbox.

DAVID: We're not just in the business of producing software. We're in the business of producing programmers. That is one of the outputs of our system. And so, yeah, investing in figuring out the solution, definitely worth it.

MATT: Yep, and everyone benefits from that: we as engineers, the company from the ability we create to be able to develop software and mentor others as they come on board and make them more efficient. It's a win-win.

EDDY: I actually want to say something, and you all might laugh, but I stumbled upon this solution that helps me become more productive, and that is eating [laughs].

DAVID: No joke. Yes. How's your blood sugar?

EDDY: I'm not kidding. I'm not kidding. Like, there's times where I'm just like, I've gotten up. I've gotten to my kitchen, gotten a snack, sit down for a little bit, come back up fed, you know, and I'm like, oh, yeah, that's the problem [laughs]. Eating, eating has helped me tremendously on my productivity.

MATT: There's a reason they call it hangry. I'm the same way. If I go without eating, I can get snappy and --

DAVID: I worked with a guy years ago. The question "Have you eaten?" is on my list of questions to ask when nothing else is working. I actually have a list of things to ask when you're out of questions, and "Have you eaten?" is on there. I had a co-worker who was just grumbling, and he's wicked smart. He got a PhD in geophysics, and he's trying to solve a seismology vibrational problem in software. And I can hear him muttering and cursing, and he'd been doing this all afternoon. So, I was just like, "Don, have you eaten?" And he pauses, and his eyes get real big, and he's like, "No," and I'm like, "Get your stuff. We're going to get a cheeseburger."

And part of it might have been the walk, part of it might have been stepping away from the computer, but by the time he had come back and his blood sugar was back up, he knew where to start the next piece of the software. So, you are bang on. Keep that question, Eddy. It will save your career.

[chuckles]

MATT: Rest is right there with it, too.

DAVID: Rest. Yeah.

MATT: You know, yesterday, Travis, one of our other engineers...you all know him, but our listeners may or may not. We were working on a problem together, and I was running on...I think it had approached about 36 hours of no sleep, and, you know, I started my day at about 5:00 a.m. yesterday, and it was going on the 13th hour of work for the day and 36 hours of no sleep. The simplest of problems become difficult. If you aren't rested, then that's a real thing.

DAVID: Sometimes, the most productive thing you can do is get your head down for six hours. Yeah.

MATT: Yeah, and I just finally I was talking to him, and I said, "Travis, how about I hand this over to you? You drive because I just am not functioning at the moment."

TAD: You've reminded me, you know, like a few weeks ago when we decided we're going to go for periodic walks around the office, and we fell out of that habit.

EDDY: It's a great habit to have, I think, right? Like, it takes your mind away from, like, just being stuck at your computer for so long. And I hope, like, higher people don't hear this, but that is part of why I like going into the office. It's much easier to reach out to someone to the side and be like, "Hey, Dave, question for you. I'm stuck in this problem. What would be your approach?" And kind of, like, bang off ideas out of each other. Like, when you can do that, there is solutions to that. Or sometimes just going on a walk for a little bit, like we said earlier, right? So yeah, just like what Tad said.

DAVID: I think the answer might be written on the mountain. Let's go look. Let's go out to the parking lot and look.

MATT: Yeah, that encompasses the stepping away. And, obviously, exercise is healthy. It gets endorphins going that may not be present just from sitting at your desk. I don't think anyone can argue against taking the occasional break and doing that. It makes us perform better.

EDDY: Enrique actually wrote something, and I kind of want to say it on record. He said going to the bathroom really helps getting yourself unstuck and being productive [laughs], take that as you will.

MATT: And being tracked down by your CTO.

EDDY: [laughs]

DAVID: A little burst of adrenaline. Whoa, what? Getting up and going to the bathroom...I read a neurology study. They found that when you walk through a doorway, there is something neurologically that happens that causes, like, a refresh stripe to go through your brain. Like, it just passes through the neurons.

And they think this is why you can stand up and walk into the room to get a thing, and when you get there, you can't remember what you were going to get. And it's because the part of your brain that's holding on to that attention, go get the thing, gets reset by that refresh wipe as you go through. So, yeah, weaponizing that for good is get up and go to the restroom room, you know, go down the hall. Go talk to a coworker. I need to wipe all of the wrong solutions that I'm holding on to in my head. I need to just power off.

EDDY: Dave, I thought that was always a me problem. I thought, for me, I was just like, man, I think this is, like, early symptoms of, like, Alzheimer's or something. Like, how am I forgetting something so simple? And then, like, as other people, like, affirmed that it happens to them, too, suddenly, I'm like, oh, thank God I'm not the only one [laughs]. Like, other people have short attention spans also.

MATT: We've been talking about all these habits. Just another quick one just for record is, taking notes and recording meetings. Giving yourself something that you can reference, I think is a good habit as well. Historically, I was never a note-taker. Just because of the things I'm responsible for and have to keep track of, I have become a very consistent note-taker, and it's been a really good habit and helped me out a lot in my day-to-day duties.

EDDY: Matt, actually, this is really interesting because, like, I spoke with someone the other day, and they told me, "Oh yeah, I'm a huge note-taker." And they're like, "I can be on my computer, but I find myself getting a notebook and writing, like, with a physical piece of paper and a pen on my hand." And I'm like, "Really?" I'm like, "Doesn't that take longer to jot stuff down? Because I'm sure you can type faster than you do write stuff down, right?" And they're like, "Oh, no, no, it's just, like, I've been groomed, you know, it's instilled in my childhood to take notes with a notebook. So, like, it's ingrained in my head, and so I'll do that, like, natively." And I'm like, "That's interesting."

MATT: I think for a lot of people, just on top of that, is, when you write something down, while you're writing it, you're also recalling that information, right? So, right there, you've heard the thing. You've written the thing and recalled the thing, and you're ingraining it into your memory.

EDDY: Yeah, but that also happens when you're typing. I'd argue that it's –

MATT: Yeah, yeah, sure, sure, but I just mean note-taking in general. I'm of the age where when I went to college, you took notes by hand. And I got really good at it for a while, but I don't write by hand often these days. Just having something to remind you and to recall and go back and reference is a really good habit because we all get so much information thrown at us so often that we can forget and lose things over time.

DAVID: I took a speed writing class in high school back when typewriters existed. You'd take dictation very, very quickly, and your notes are sketchy. And it's trying to, like, what the heck did I write there? And I skipped words. But the very first thing you do after the dictation is you sit down and you transcribe your own notes to better notes. And then, you take your transcribed notes and you type them up, and that process of reviewing your own notes twice is hugely beneficial for memorizing.

MATT: Yeah, and there you go. Just by the time you get to the end of that process, you have recalled that information, like, four times. You start to remember it all.

EDDY: I was surprised when I first started, right? Like, my late high school years going into college, I'm like, how the heck are people able to write all this in a piece of paper and, like, recall everything that was said? And then, one of my teachers sat me down. He's like, "Well, because they're not writing everything. They're just doing highlights of what was said," and highlight. I was like, holy cow, that just opened up, like [laughs], another realm. I'm like, yeah, you don't necessarily need to write the does, the ifs, and whens. You just do only the highlights of what the conversation was had but enough where you can recall. And suddenly, you become super efficient.

DAVID: You start thinking about what is the objective of this? The biggest superpower for me in school was somebody said, "When you're taking notes, if you were writing the test for this class, what questions would you write from what was given?" And I turned in the sheet of my...I had the thing, and I had the questions that I wrote them down next to my notes. And the teacher actually pulled me aside and asked if I had...like, he didn't quite accuse me of cheating, but he wanted to know if I had been going through his desk because I had picked, like, 80% of the questions off of the test as a result.

EDDY: [laughs] But suddenly, that's a good thing when you do TDD, right?

DAVID: Mm-Hmm. Yeah.

EDDY: [laughs]

DAVID: Test-driven class note-taking. I like it. I like it.

EDDY: Suddenly, your coverage is much higher because you practiced.

DAVID: Yes. Oh, this has been a good round table chat. Thank you, guys, for coming. The one advantage of going so far afield when we invited Justin back for a part two is that now we can invite him back next week for a part three. Well, for a redo of part two.

EDDY: [laughs]

MATT: They always get a little off-topic, but I think that's the beauty of it, right? We segue, and we end up talking about useful information that I think everybody should have.

EDDY: I've actually made a habit on going half to what we were initially talking about. Like, I don't mind going on tangents, you know, every once in a while because that's how our brain works, right? But, like, being cognitive, right? Or conscious and, like, going back to what the original topic of the conversation is. Because otherwise, you'll spiral out, and you'll talk about --

MATT: I would argue today we did never really get away from the topic.

DAVID: No, No. You can't predict what you're going to discover when you start synthesizing new ideas. And, like, Matt, you kept just, like, lightning striking my brain. And I'm like, I did not expect that to fall out of my head and in the podcast. And I'm like --

MATT: [inaudible 50:56] [laughs]

DAVID: Well, no. It's like you were saying things, and it was causing just things to just precipitate like I'd had all the pieces of an idea in my head for weeks. And then, you said that thing, and I'm like, oh, man. Or, like, Eddy, when you said unit tests, and I'm like, aha, it's behavioral, not implementation. Yeah, right on.

EDDY: Well, David, this has been awesome, guys. Thank you so much.

DAVID: This has been great.