Giles Bowkett writes, in the context of Ruby, “debugger support is like nail-biting support, or farting-in-public support. Its absence is a feature.”
I strongly disagree. And while Giles’s stance is extreme, the perception is common. Most programmers think of the debugger as a tool they shouldn’t really need, if only they could write proper code. Even the name itself leans this way. The tool in question is one which inspects the state of a running program; to call it a “debugger” is an oddly opinionated and restrictive way of expressing its functionality.
By claiming that “debugger support is for languages that you can’t run tests against gracefully”, Giles himself falls into the trap of seeing the debugger as a mechanism for fixing code. It can certainly be used for that purpose, but it’s like seeing a web browser as a tool for reading the news.
In the simplest case, the debugger is a great way for getting a feel for the running state of a program; how it flows, and how its state varies. Using it to find bugs is a small subset of this class of uses. A more common case (for me, at least) is to use the debugger while reading code. With the debugger, you jump around the running state of the program in parallel with reading the source. You get to see the program on two axes—that on which the program is defined, and that on which the program runs.
All of the information that that can be gleaned from the debugger is of course contained within the code itself (except in disastrous cases!), but to claim that one should therefore not need the debugger is an argument which reductios very fast to absurdum—you might as well read the binary. Using the debugger makes understanding exactly how code works hugely easier and faster.
Personally, my most frequent use of the debugger is to get the program into some running state, and then start writing code in the debugger itself. (This idea will probably seem strange to some people, in the same way that not freeing your memory once did.) With the debugger, I can write code in chunks that are immediately compiled into the executing environment, and which are “tested” in the most direct manner possible—in the environment of the running code. Most of this code is part of a web application, and more often than not, it’s being written while a web request is pending. To claim that tests are an adequate replacement for this kind of use of the debugger is crazy.
To return for a moment to Giles’s claim—that debuggers are bad—I’m curious to know exactly how fully he holds this position. Would he argue that print statements and stack traces, the primordial debugging instruments that Ruby does provide, be disallowed for the same reasons that debuggers are bad? And if not, at what point do debugging tools reach the critical mass of “fart-in-public” proportions?
Lastly, and on a basic level, I think Giles is making a stronger claim than he thinks. His reasoning is apparently that “tests are a replacement for debuggers, and a superior replacement at that”. But his stated claim is that “having a debugger is a very bad thing”. Nowhere in his article does he actually argue for the stronger form. Consider two hypothetical languages, Foo and Bar. Foo is a superset of Bar, but also has feature X. Giles claims that Foo is worse than Bar. To do this, though, not only has to show that X is without any possible use, but also that it’s actively harmful.
On both of these counts, the post fails to present any kind of decent evidence.
Footnote:
The article tries to drive home the point by saying “it’s also like asking why Lisp doesn’t have design patterns.” This is (presumably) a corrupted version of Norvig’s 1998 claim that most (16 of 23) of the Gang of Four design patterns are invisible or simpler in Lisp. Given also that this was shown as part of a long presentation on design patterns in Lisp-like languages, which was created while Norvig worked at Harlequin (a major commercial user of Lisp), I don’t really know what Giles’s claim is based on.
If the statement was just referring to design patterns generally, Richard Gabriel put it well:
“Here’s another true statement about patterns: If there are no such things as patterns in the Lisp world, then there are no statements a master programmer can give as advice for junior programmers, and hence there is no difference at all between an beginning programmer and a master programmer in the Lisp world.”