Thoughts on debugging
Last year I published Humane Guide to Debugging Web Apps which lead me to do a few talks and small workshops about the topic. All of them further lead to me having great discussions with developers of all levels of experience. (That's my second favorite benefit of doing talks and writing – the best one being meeting amazing people.)
What fascinates me in debugging is the way it's a combination of process/mindset and technical tools. That means there are so many things you can learn and improve to make your development process much better and cause much less headache.
Like my colleague Jan (I highly recommend following him in Twitter!) well said it in Twitter:
Different problems also require different ways of debugging. Sometimes the problems are in the domain logic abstraction level and then rubber ducks, pen and paper and long walks on the beach are my favorites. Distancing yourself from the code and the technical aspects of software development helps to think about the problem.
Simple steps for technical debugging for beginners
Sometimes the problems are more tangible and concrete however. Sometimes you know exactly what you want to do but the computer is not cooperating with you. I wanted to expand a bit on what I wrote in the guide.
Read the errors
For people new to software development, error messages can be cryptic and even intimidating. There's often a lot of information, especially if the stack trace is long and if you don't have understanding of what those things mean, it can feel easier to just skip them and try to reason with the code.
Never try to reason with the code.
What I mean by that is to not go from this code didn't work (errors/does wrong things/does nothing) to let me read the code to see what's wrong. It's not easy to find the mistakes by reading the code.
Pretty much regardless of your language of choice, one thing you will find from the error message is the line number for where the error happened. If you don't know what the error message means, you should copy paste the error into Google and try to see if someone has had similar problems.
Explore the current state around the misbehaving code
Whether you're receiving an error, getting wrong results or nothing happening, exploring the current state is a good next step. State refers to all the variables and their values that are currently available in the code.
Let's say you're trying to run a map function to an array/list of values and the outcome is wrong. Printing out the original array before and after the map function call can give you insights into where the problem lies. If the original array looks good but the result not, you know the culprit is inside the map function. In that case, you can go into that function and either use debugging statements or printing out values to see step by step where the problem is.
And if the original array is already wrong, you can then go backwards in the code to see where that array came from or was last modified to find the culprit. There's no need to purely guess anything when debugging. Following logical steps, experimenting and attempting different things can lead you to the result.
That's not to say that debugging something, especially more complex modern web applications would be easy. I once spent days trying to figure out why our application showed wrong data on the web when viewed from New Zealand at a specific time of day. It felt like a lot of dead ends and discussions with colleagues.
Shrink down the problem area
Identifying the right spot where the wrong code lives is crucial. No matter how many changes you make to your code, you're not gonna make good progress if you are making them in the wrong place. Hence, you should be spending all of your time identifying the correct spot before doing anything else.
After you think you've found the right place, it's good to then do some testing (if your project has automated testing set up, this would be a great spot to write unit or e2e tests for this part but if you don't you can just test manually).
Run your code first with it still being in incorrect state. Change something in that code to make sure that the outcome changes (even if not to the correct result yet). This part is important because it validates that you are making changes in the correct spot.
Now you can work towards making the code correct. Sometimes finding the right spot makes the mistake easy to spot but quite often it doesn't. The smaller you can make the area of suspicious code, the easier it is gonna make sure that your fixes produce a correct outcome.
Once you've managed to make the fixes, make sure to test with other possible correct and incorrect inputs as well to make sure you didn't accidentally introduce other bugs into your application.
Learn debugging tools
A good investment of any developer's time and effort is time spent on learning the tools of software development. When it comes to debugging, there are many.
For frontend web developers, learning Developer Tools (see for Chrome and Firefox) are a good place to start. There's a lot to learn there (I'll publish more in-depth look into those later this year, join my newsletter to know when that happens) and you don't have to know every single function before they can become useful.
More advanced your tooling and skill of using them is, more complex issues you'll be able to solve. But none of those tools will be helpful if you're not approaching the problem correctly and are just making random guesses. I've noticed recently when helping junior developers that I'm able to help people debug applications written in languages I've never written or read myself simply by following the basic steps and asking questions.
What did I miss?
What are your favorite methods for debugging? Let me know in Twitter and let's have a discussion about them.
Sign up for Syntax Error, a monthly newsletter that helps developers turn a stressful debugging situation into a joyful exploration.
If you found this post interesting, consider sharing it with your community or following me on Mastodon.