Debuggers considered harmful

In a recent article, Bob Martin talks about the interaction of Test Driven Development and debuggers.

In an old post to linux-kernel mailing list, Linus Torvalds opines on the use of debuggers in kernel development. But I believe that his arguments, if they are valid at all, may apply more generally. Kernel development is not qualitatively different to the development of any large, complicated piece of software, with strong stability, performance, and compability concerns and real-time constraints, though it is special in the way that it brings all of these issues together.

The arguments presented by the two essays have a lot in common: Essentially, debuggers encourage the bad habits that lead to bugs (which reminds me of the argument that more roads mean more traffic).

I've very rarely used any debugger. I find that most bugs are either very easy to resolve, or very hard to resolve. For the easy cases, there is no need for the helpthat a debugger provides. For the hard cases, the debugger doesn't actually help: bugs are usually difficult to resolve because they are timing dependent, involve race conditions, or relate to subtle conditions in large amounts of data, where the cause is very distant from the immediate problem ("how did it ever get into that state?"). Maybe in the future, more sophisticated debugging tools will help with these difficult bugs, but I'm not optimistic: It seems more profitable to pursue design and programming techniques to make these bugs less likely to occur in the first place.

I think that Test Driven Development probably serves to separate these classes of bugs even further. Once the implementation passes a reasonably comprehensive set of tests, the remaining bugs are either really really easy, or really really difficult.

I would expect that the situation where debuggers are most legitimate is the writing of exploratory and "throw away" programs, where it is assumed that the the programmer will always be there to sort things out if the program fails, and a debugger is the ideal tool for sorting things out. It's interesting that in the world of scripting languages, where such programs are most common, debuggers do not seem to be widespread. For instance. while there are debuggers for Perl (ActiveState has one), they do not seem to be a part of the standard Perl development toolkit, in the same way that they are part of almost any C/C++ development suite.

On the other hand, the dynamic languages crowd (especially Lispers) advertise their ability to examine programs and their data at run-time, and modify both of them without restarting. In this case, the development environment does not merely include a debugger, but subsumes it into the language.