This site will look much better in a browser that supports web standards, but is accessible to any browser or Internet device.
Back in February, I ran across the post robkinyon on Perl: How useful is a debugger, really? and was again reminded of the great debugging debate. I thought about commenting on it at the time, but I got distracted.
Well, Matt Trout reminded me of it again today with his post Simple Debugging. So, I decided it's time to throw my thoughts into the wind.
When I was a very new programmer (a long, long time ago) I only used print statements to debug. This was partially due to a lack of tools and partially due to a lack of experience. I was introduced to a couple of debuggers, but was not really convinced.
Then I was introduced to a really good interactive debugger. It completely changed the way I worked, I could inspect data structures interactively, chase down long chains of links, and basically do the same sort of stuff I did with print, just faster. I could also set a breakpoint near where I thought things would happen and kind of explore the area to see what was wrong.
It didn't take me long to decide that this was definitely the way to work. Unfortunately, I couldn't rally use this wonderful tool at work where I was working on a background program that could not comfortably be placed under the debugger's control. (This was an old TSR program running under MSDOS.)
I moved on to another job and was working in an environment without an interactive debugger. More importantly, it was the server-side of a client server system. Suddenly, the concept of pausing the whole server to track down some bugs did not seem like such a great idea. Our client-side programmers often used an interactive debugger for their work and I could easily compare their experiences with mine.
I started noticing something interesting. A few people were really amazing with the debugger. They could zero in on a problem with a small umber of breakpoints and a little judicious inspection. Others spent enormous amounts of time single-stepping through the code, eventually finding a problem.
Over of the host side, I noticed something equivalent. There were a few people that wielded their print statements like a scalpel. They would examine code, use a few well-placed prints to uncover surprising behavior. Iterate a few times, and solve the problem. Others would scatter-shot print statements all over the code, printing out reams of data in the hopes of seeing something of interest.
With either tool, the key insight appeared to be the method chosen for placing either a print statement or a breakpoint. The effective programmers strove to understand the code and form a hypothesis of what problem might cause the current symptom. That person would use this hypothesis to determine where a print statement or breakpoint could be used to prove or disprove the hypothesis.
Those people would usually make effective progress toward finding and squashing the bug. The ones that also had the most experience or understanding of the code were particularly effective in this technique. Their initial guesses tended to be much closer to the target.
The other group used either print statements or single-stepping to explore the code. They seemed to almost be on a voyage of discovery. This is admirable, and can be an effective way of learning the code. But, this approach does not lend itself to rapid bug fixing.
In watching several people over a period of years, I've noticed that people using print statements often discover this approach on their own. This is caused by the simple fact that adding and removing print statements is time-consuming and boring. Good programmers soon learn to reduce this cycle with better analysis.
On the other hand, I've seen many developers using the interactive debugger single-step technique continue because it feels like they are making progress. They don't notice the boring stuff as much, because they appear to be moving. It often takes input from a mentor to get them to understand that a better breakpoint choice would make all the difference.
I tend to prefer the print statement approach. This has fit well with the kinds of programming I've done during my career. However, I'm not a fanatic about it. A good interactive debugger can be a joy to use on a code-base that I'm really familiar with. But, as with most of the debates in programming, the most important and powerful debugging tool in your arsenal is the one between your ears.