Senior Director, Orchestration And Automation
Debugging is a skill you must employ when writing software and yet requires a uniquely different type of mindset. Software engineering (for most code) is largely process oriented, debugging is often non-linear and looks like it’s intuition oriented. But there is process.
My #1 Rule in debugging is: Believe No One.
It’s so easy to follow a wrong assumption when you are listening to another developer who has been debugging something to no avail who is sure the
“error is in how we do foobar so we just need to change it to encode correctly” or “it’s a race condition in these two things” or “this is the code causing the problem, I just haven’t pinpointed it yet”. How many times have I been bitten spending time down the wrong path because I believed the other person and adopted their assumptions about how code worked or the root cause of the bug?
Now, the only question I ask is: “How does this bug present itself?”
Give me the root stack trace, the steps to reproduce it, the screenshots of the bug, the logs — however it presents itself. That’s all I want.
Then I start with a clean slate, no assumptions.
Don’t ignore stack traces. A stack trace is one of the best things you can have when debugging. It literally tells you which places in the code the error is presenting itself. Yet, it’s surprising to me how many developers ignore the details of the stack trace.
Start first from the most recent frame and dissect that line of code carefully. Many lines of code are doing more than 1 thing and dealing with more than 1 piece of data. Confirm your assumptions about the code and the data state at that point with a debugger (or printf statements ;)), and compare that against how you believe it should work.
Eliminate the possibility the error is in the logic or data in that stack frame (or confirm it), then move up a frame and repeat the process until you are at the root cause of the data or logic causing error.
Start with data, not big theories. This is where things often go awry with novice debuggers. If you don’t have a clean crash or a stack trace, it’s very tempting to start formulating big theories as to why things are going wrong. This can happen when you are debugging things like performance issues, race conditions, etc.
Examples: “The code is a mess in the CardProcessor module, and because I know it’s used at some point during when I click the button it must be there.” “The reason it’s slow is because writing to disk is slow so it must be where we write the files in the FileWriter package”.
The danger here is wasting time going down an incorrect path. How do you know what theories are right and what is wrong?
Know your tools. For problems like this, often people ignore valuable tools. You need the tools to give you the data to form good theories. If you are debugging C/C++, you must know how to attach gdb to a core file. If you are debugging a query performance problem, ask someone how the database query analyzer works. If the browser rendering is slow or you think you are leaking memory, use the chrome dev tools to profile.
If it’s obvious you don’t have a lot of good data about the cause of the problem, you should be first thinking about how to get that data before you formulate theories about root cause. Sometimes instrumentation tools can help, sometimes you must add logging. Again, the first place to start adding logging and instrumentation is where the error is presenting itself, (e.g. if the slowness is when you browse to the /foo page, profile that first).
Be prepared to throw away a theory. Often times developers get so hung up on what they think is a problem — they’ve invested hours and hours in going down a path for debugging, they must be getting close. To avoid this, keep your theories as narrow and testable as possible. Start with the most likely first, and test the theory methodically, and eliminate along the way. After spending more than 30 minutes on a problem, asking yourself: am I sure this is really where the bug is?
It can help to bring fresh eyes to a problem — having a well documented bug (and again, your documentation should be focused on how the problem presents itself and how to reproduce it, not your theories on its root cause) makes it easy to socialize it with other developers.
Hacker Noon is how hackers start their afternoons. We’re a part of the @AMIfamily. We are now accepting submissions and happy to discuss advertising & sponsorship opportunities.
To learn more, read our about page, like/message us on Facebook, or simply, tweet/DM @HackerNoon.
If you enjoyed this story, we recommend reading our latest tech stories and trending tech stories. Until next time, don’t take the realities of the world for granted!
Create your free account to unlock your custom reading experience.