Debug early, debug often.
Hey there! We're a few days into talking about how to write better code faster. You might want to catch up here, here, and here.
Today we're tackling Step 3: Debugging.
If it's not already clear from the previous emails, I want to disabuse of the notion that debugging is the thing that happens after you write your whole feature. Debugging should be happening as early and often as possible. Debugging is the act of course correcting, and the whole purpose of our tight, virtuous loop is to make lots of little course corrections as you go, rather than a few really big course corrections at the end.
Everything we've done leading up to this point has been with the goal of providing a small, clearly defined surface area to work within when debugging. If you're trying to get a single test to pass, then your surface area is whatever code gets executed as part of that test.
If you're composing a larger feature out of already tested components, then your surface area is probably the interactions between those components.
"What does that mean, Ben?"
I'm glad you asked, dear reader. Your tests give you confidence that the functions you've already written are performing as they are designed to. That means you can now treat them like Lego blocks that fit together to create more complex functions. When two Legos won't fit together, you're going to inspect the area where they meet to figure out why.
For a practical example, suppose you have an endpoint that accepts a POST body, persists that object to your database and returns the object, now populated with an ID, in the response. You are confident that this performs correctly, because you've written a test for it. If when you implement your feature you get a 500 response, then the first place you should look is the payload that you're sending in your POST request. Why? Because it is almost certainly different in some way from the payload that you provided in your test. That means that either your request is bad, or you haven't accounted for something in your test. Either way, inspecting the difference between what you're providing in your test and what you're providing in practice will give you valuable info for where to look next.
I've written in depth about a process for debugging, and even created an entire course on the topic, but the short takeaway for today's email is that by building up your software from small, modular, well-tested components, it becomes easier to debug. This is because you can focus on the interaction between predictable pieces to find where things are going awry, rather than digging through the proverbial hay stack.
Tomorrow I'll send out a video of me coding up a non-trivial feature using the method I've outlined this week. Stay tuned!
Next Up:
Live Coding Video: Write, Test, Debug
Previously:
Testing That One Thing