A common task in the working world is dealing with existing, but buggy code. What are some tips to improve your skills as a debugger?
13 Answers
Don't Assume Anything
It's often tempting to just say "oh, I know what this bit of code is doing, it's fine". Don't do that. Test every assumption and step through everything carefully.

- 31,939
- 8
- 101
- 125
-
2+1. Absolutely. Be prepared to be amazed by how some of the stuff, you thought you knew, is going to play tricks on you. – aufather Oct 13 '10 at 16:04
-
-
3Debugging other's code is a huge time waster, productivity killer, but that is how it is. The only time when it really makes sense to fix other's bugs is when they have left. What I HATE HATE HATE is going through some objectively crappy code by a senior coder, then having to ask a question in order to make timely progress, and getting a lecture on improving my skills at learning the existing code base. Unlike studying the mother nature, solving human-caused screw-ups is hardly fun. At least I get my answer. The reverse situation will not happen, because I am just better and leave fewer bugs. – Job Nov 28 '10 at 00:56
-
1@Job: ... okay? Did you mean to leave this comment on the post, perhaps? :) – Adam Lear Nov 28 '10 at 06:10
-
This! It's silly to blindly trust any small bit of your code if you're debugging a weird issue and the code seems fine. – Dan Feb 13 '13 at 13:21
-
-
+1 `Assume as much as you can but at the same time don't forget to prove your assumption` – Sampat Badhe Jan 13 '18 at 14:48
Testing incrementally.
Go depth first in your code and test it from smallest module moving up gradually.In this way, you are not under too much stress trying to figure out where the problem exactly might be.
It also means that it affects less code at a time since you are moving incrementally..as at times I have had issues where I fixed something and that lead to breaking lots of other stuff. I give credit to my boss for this as he taught me this when I messed around.
Divide and conquer is a good approach. Try to identify some visible input (user input/network event ...) and output (log, output to user, outbound network message ...) between which the issue exists. Try putting prints at sizable chunks or significant points between them and try to narrow down where the bug is in the code.
Divide and conquer can also work very well in case of regressions over version controlled code. Find two builds - one where it works as expected, other with the regression. Narrow the gap down till you are left with a bunch of checkins as potential suspects.

- 4,449
- 2
- 26
- 24
Rather than the binary bug chop, write tests in the form
- Given...
- When...
- Expect...
To verify what you actually know to be true about the functioning of the app versus what you assume to be true.
Most IDEs make it easy to extract methods and to generate xUnit testing stubs. Make use of that.
Why not sprinkle debugs? Because after you are done, you will likely have to undo much of that work and delete a fair amount of those debugs. When you write tests, your debugging will aid in the prevention and detection of future bugs.

- 2,078
- 1
- 15
- 19
Keep debugging. If you debug a lot, you'll improve.

- 1,339
- 1
- 8
- 8
-
Absolutely debugging is in art in itself, especially debugging other peoples code. – Gratzy Oct 13 '10 at 20:59
As others have said - do not assume anything. This is especially true if its code you've written. When debugging others code you are more likely to slow down because the code is new to you or you don't trust the coder. When debugging your own code its too easy to assume you wrote it correctly, slow down!
For the actual process of debugging:
- Write unit tests if they don't already exists.
- Add appropriate logging if doesn't already exist.
- Then use the debugging.
Adding the unit tests and logging first more efficient that using the debugger first up. You also get the added advantage of having the unit tests to help not introducing future bugs and the logging will help debugging sessions in the future.

- 578
- 3
- 9
Before stepping over a small chunk of code, see if you can accurately determine the outcome. This does tend to fly in the face of don't assume anything (which I up voted BTW) but as you gain experience, it can help narrow down where to look.
This may sound trivial, but learn the nuances of your debugger and learn the hot-keys. Sometimes debuggers can be slow enough that your mind wonders when your stepping through. If you can keep up with the machine and aren't mousing around, that can help.
If you can modify code while debugging:
- consider asserting pre AND post conditions. Sometimes you can then step over, instead of into code.
- for if statements with complicated expressions, consider something (some may frown at this but it works for me)
like:
bool isLessThan5 = a < 5;
bool isGreaterThan10 = a > 10;
if ( isLessThan5 || isGreaterThan10 )
{
// more code here
}
instead of:
if ( a < 5 || a > 10 )
{
// more code here
}
For the cases you can't debug everything, for whatever reason, learn to "rubber-duck" with a co-worker. Sometimes the act of explaining sheds light. (ok, maybe this isn't exactly in the questions theme, but I think it's close enough to warrant mention)

- 2,814
- 20
- 23
-
1The naming of subconditions needs a step more, namely the refactoring of the names when you find out what the condition is for. It might turn out to be `if (tooCloseToHydrant || overTheBrink) { ` when you learn more later. – Nov 28 '10 at 10:36
Two things, based on spending most of the last 22 years maintaining code other people wrote.
Understand the kinds of bugs you tend to write.
For instance, I'm a very meticulous coder, so once my code compiles, it's usually free of trivial bugs. So my bugs tend to be weird complicated things like thread deadlocks. On the flip side, I have friend who mostly writes trivial bugs - semicolons at the end of C++ for loops, so the next line only gets executed once, that kind of thing.
Don't assume other people write the same kinds of bugs you do.
I don't know how many times I've wasted time pulling out the big debugging guns, assuming a bug was my kind of really subtle weird thing, only to have my friend look over my shoulder and go, "Did you notice that extra semicolon?" After years of that, I first go for the trivial, low-hanging fruit when looking at other peoples' code.

- 16,028
- 3
- 51
- 77
-
-
@Thorbjørn: If I've taken ownership of the code, I sometimes do it to improve readability, but not to find typos. Interesting idea! – Bob Murphy Nov 28 '10 at 20:25
-
you do not have to commit it, just see what happens. I can strongly recommend enforcing a polity that requires code to be reformatted - preferably automatically - when checked in. – Nov 28 '10 at 20:47
-
@Thorbjørn: I'd love to do that. What do you recommend as a code "prettifier"? I mostly work on Linux and Mac. – Bob Murphy Nov 28 '10 at 22:01
-
I use Eclipse available both places, and the Java editor has a socalled Save action where you can specify what should happen each time the file is saved. Here one of the options is formatting the source. We are a small team so I have not investigated more in it. More experienced teams allow for pre-commit hooks in the source control systems, allowing a source commit to be rejected if it is incorrectly formatted. Very efficient. – Nov 28 '10 at 22:28
Know your tools. For example, Visual Studio's debugger has an awesome feature called TracePoints that are like breakpoints but instead of stopping your code instead inserts a trace statement into the debug output.
Reading books or taking a class on how to use your debugger is highly recommended. I took a couple of classes and read a few books by John Robbins that made a big difference in my effectiveness as a debugger.

- 2,321
- 2
- 18
- 17
Understand functionally what the code is trying to do. If you don't know the complete picture (all test cases this code must pass) it's hard to debug properly without introducing new bugs

- 2,037
- 1
- 17
- 15
Write automated unit test and other types of integration and functional tests.
The more automated tests you have, the less time you need to spend in a debugger.
Also, good design - SOLID principles. If you're writing small, focused classes and favoring composition over inheritance, eliminating duplication, etc., then your code will always be easier to debug.
I find that well designed code produces a different set of bugs that code that is not designed well. Generally speaking, well-designed code produces bugs that are easier to find, reproduce, and fix.
The exception (and there always is one) is multithreading code :-)

- 2,244
- 14
- 14
If you've narrowed it down to a small region, but can't still can't spot the error, try the 'view code + assembly' option of your debugger. Knowing enough ASM to say "there should be a branch here" or "why is it only copying the low word?" will often pinpoint the coding error.

- 5,793
- 31
- 51
Check out the very valuable book Why Programs Fail: A Guide to Systematic Debugging, by Andreas Zeller. It will introduce you to many techniques, theories, and tools, some of which are on the cutting edge of research.
The slides for the book are available online, but I find the book itself is easier to read.
The book will help get you started and make you think more scientifically about debugging, but it's no substitute for practice. You may need to be writing and debugging for 10 years before you see an order of magnitude improvement in your performance. I still remember having my jaw drop at Sun seeing senior developers, who have been programming for Unix for 30 years, find obscure multithreading or parallel bugs in minutes. Experience matters!

- 8,223
- 4
- 34
- 68