A visual debugger is a like an addictive mental drug. It’s fascinating to look at, very helpful at times, and it can become a crutch. Just as with alcohol or other drugs, a little bit can be fun and help get you to where you want to be, but too much can derail you. Allow me to explain.
I do most of my development on Linux (OK, I actually do ALL of my development on Linux or something similar like Solaris or BSD–I don’t do Windows) in C, C++, or Python. When the need arises to be able to peer into the code and see what, exactly, is causing an annoying fault I use gdb or DDD (a GUI front-end for gdb) for C and C++. For Python I use tools like winpdb or Eclipse with the Python IDE plug-in.
Generally, however, I don’t use a debugger. I’ve found that many errors are obvious after carefully reading through the code (as in, OMG I’m glad I caught that one before the code review!). The judicious use of printf, cout, or print statements can illuminate the location where a fault is occurring, and a good stack trace can be immensely useful when trying to locate a problem. I’m a rather impatient person by nature, so I don’t want to spend the time firing up the debugger, setting the breakpoints, and defining the watches, when I can just toss in a few output statements and run it again. I save the debugger for those times when I’m really stumped, and no amount of pondering the problem produces any answers (or even clues). So, for me, the debugger is a tool of last resort.
But for some developers the debugger has become a problem. I once worked with a fellow who did all of his development in a Python IDE with integrated debugger (Wing IDE, if you must know). It was a gorgeous tool, with more knobs and dials than the cockpit of a 747, and he would cobble up a function or a module, push it through the debugger, and then pronounce it done. No formal functional requirements, no test cases, and no integration testing. The debugger said it worked and therefor it worked. Except when it didn’t, which was a lot of the time, actually.
Over-reliance on a debugger can lead to unstable code that’s only tested in targeted sections, and then only from a very limited perspective. All the debugger will really tell you is that the code is syntactically correct and doesn’t contain egregious errors like array boundary overruns or null pointers. It won’t, and can’t, tell you if the code will play nice with the rest of the software in the system, if it will handle the necessary inputs and outputs, or if it will handle faults in a predictable and graceful fashion. That’s not what debuggers are designed to do.
So save the debugger for when you really need it. Just as you wouldn’t want to use a sledgehammer to set a screw, you don’t want to hit the software with more than is really needed just to uncover a simple problem. It is also a good idea to always keep the big picture in mind. For all but the most trivial programs there are integration issues–will the new module work in the context of a larger system? A debugger won’t tell you anything about this, but a good set of test cases based on formal requirements will.
Here are some pithy witticisms about debuggers I’ve collected over the years. I’m not clear on where these came from; they might be original, or they might be from someone else. If any of these offend you, well, sorry, but the sad truth is that I have seen all of them put into practice at one time or another.
- Software debuggers are the crutch of the incompetent, the tool of the impatient, and the last resort of the professional.
- The debugger is the best tool ever invented to allow a programmer to look incredibly busy for an extended period of time while doing almost nothing of any substance.
- Failure to comprehensively test and verify software is the sign of someone who lacks a proper appreciation of the word “disgrace”.