7 Steps to Debug Efficiently and Effectively
I’ve been writing code for well over 15 years now and I have still yet to write a bug-free application. Every new project is an opportunity for me to achieve perfection, but at some point someone will find that one value or that set of clicks brings my day crashing down. I’m used to it now. It’s all part of the process of being a developer. But when that ticket comes in from a QA person, I want to be able to kill that bug as quickly as I can. So here’s some tips I’ve picked up that help me close up bugs quickly and easily!
1) Always Reproduce the Bug Before You Start Changing Code
So many times I have seen the description of a problem, immediately made some random assumptions, proceeded to make changes, checked in the code, closed the ticket and sat there pleased with myself, only to find out that the next day someone re-opened the ticket and said it’s not fixed.
Chances are I fixed something, but without having reproduced the original bug, I have no idea what have I actually done. So, always find the exact steps to reproduce the bug. If you can’t reproduce it, find someone who can! Your time is precious- don’t let people “assure” you they saw it. Have them prove it to you and then reproduce it for yourself. There’s nothing worse than spending hours on a wild goose chase!
2) Understand Stack Traces
Not every bug will have a stack trace, but most of them do. The ability to read and understand them in seconds is an incredible skill. The key to remember is that the root cause, the filthy culprit that broke your perfect day, is usually wrapped up several layers deep. So work from the bottom of the scary long stack trace upwards to find the root cause!
I’ve picked out a few stack traces I found scattered across the internet. Here’s a relatively easy one to start with- see if you can spot the root cause.
The root cause is the last “Caused by” line, so here it’s “java.lang.ClassNotFoundException: com.badlogic.gdx.graphics.g2d.Batch”. It looks like someone didn’t setup the class path for this Java app correctly and hence the developer needs to add the missing class to it.
Let’s try another one I found on Google. This time, can you figure out which file, method and line of code the bug is triggered on?
Just as before, we look for the last “Caused by”. This time, when we look at the very next line it will tell us exactly where the error occurred in the code.
Now, here’s great piece of advice for reading stack traces:
Look for the last time in the stack trace that it touched YOUR code.
It sucks to say it, but 99% of time the stack trace will come from a bad assumption in your OWN code. So, in the above screenshot, someone did something wrong in com.example.myapp.NameUtil.toFullName (line 6 in fact!). Now it may not be that exact line which has the bug, but you’ll need to work backwards up through the code to find where a bad argument was perhaps passed in. Which brings me to the next piece of advice:
Always wrap exceptions thrown to you.
You know that NullPointerException you discarded because you think it'll be obvious that it was a NullPointerException? Ask your future self who in 6 months time will be cursing at the screen saying "but what's the cause?". Always wrap an exception you caught! Being able to track that root cause when something goes wrong will save you hours of pain!
3) Write a Test Case that Reproduces the Bug
I hear you… ***“Aww man! You had throw the T word out there!”***. I’m not a TDD purist, but I know that the times I’ve written a test case in Jasmine, JUnit or XCUnit to help me diagnose and close out a bug have felt incredible. For one, it keeps you focused on just that one bug. It also speeds up your fix time because you no longer need to launch a full app and click around 6 or 7 times just reach the screen which crashes. Finally it’ll help ensure your bug never returns!
4) Know Your Error Codes
This is a bit of strange one to hear, but given how fundamental HTTP is to pretty much every app these days, knowing what the HTTP error code means can be a huge help in diagnosing bugs!
- 404 - You might have the wrong url in your app
- 401 - Your credentials are likely wrong
- 418 - You’re talking to a teapot! (seriously https://tools.ietf.org/html/rfc2324)
- 429 - You’re making too many requests
If you get an HTTP error code, always Google it to make sure you understand it. Again, it’ll save you a lot of time! The same goes for Database drivers and other protocols. If you see an error code, Google it with the name of the database and look for the official docs.
5) Google! Bing! Duck! Duck! Go!
Whatever your search engine of choice is, you're sure to find a helpful answer somewhere in the internet. Just gather up as much information as possible before you hit "search" in the search engine.
6) Pair Program Your Way Out of It
If you find yourself spending more than 30 minutes hacking away and not making any progress, stop right there! Bring in a colleague, a friend (or a CodeMentor) and talk them through it. Show them the bug and the code, tell them everything that you’ve tried and explain to them what you think the problem is. You would be shocked to find out how often just the simple fact that you’re talking it through and having to explain it to someone else can suddenly help you see what the issue really is. Other times, it might actually be a complex issue (like a race condition) and having a second set of eyes can help pick up edge cases and scenario’s you have not even considered.
7) Celebrate Your Fix
Whether you turned a test from red to green or closed out a ticket on your queue, give yourself a solid high-five. You've just saved the day and deserve all the credit coming your way on this one.