Twitter GitHub Facebook Instagram

Daniel Irvine on building software

Beyond the IDE: Debugging is the last resort

24 September 2014

The great unspoken advantage of test-driven development is that it obviates the need for debugging.

Debugging is a terrible flagellation we inflict upon ourselves subsequent to finding a bug in our programs. Techniques like stepping-through code and setting breakpoints were cemented into the modern-day programmer’s psyche when commercial IDEs concocted the “edit-compile-run-debug” cycle. Debugging, we were told, was a necessary part of a developer’s existence.

Unlike writing a feature, which is precise and methodical, debugging involves sleuthing around the codebase setting traps in a valiant crusade to catch a bug. There is no way to estimate the time involved in this crusade, since there’s no formula that can be followed. Some debugging sessions go on for days and end up in total failure, with the programmer at the point of mental breakdown. Stepping through line after line of obtuse code is no one’s idea of fun.

The commercial IDEs invented vast systems of tools to help us: watch lists, per-thread call stacks, immediate windows, breakpoints with conditional support, memory inspectors, tracers, edit-and-continue. And we learnt to use them because they are absolutely necessary.

Except that they aren’t. Test-driven development proves the correctness of a program just by having clear specifications. Every bug reported can be specified precisely as a failing test, and that test pinpoints exactly where the error is.

Back in the real world...

In the real world we don’t specify our programs well enough--there are never enough tests--and our users will invariably run their programs in ways the developers imagined. They’ll hit edge cases which we’d never considered.

But when this happens, the answer is never to crack open the debugger. The answer is to write a failing test. That should be simple, given a) a bug report and b) a system already covered by tests. The new automated test should pinpoint the error just as well as a debugger would. Plus, it’s there forever more, to protect you “for free” from future bugs.

Writing a test involves nothing more than your code editor and the compiler, just as with your production code.

My point is this: Test-driven development is both a design and a debugging technique. With the rise of TDD, all those fancy debugging tools have become worthless. Vendors like Microsoft don’t want you to know this, of course, because you’d begin to question why you’re paying so much money for such unnecessary bloat.

Here’s my advice. Instead of investing time in learning an IDE and its debugging paraphernalia, invest your time in learning TDD and in learning a decent text editor, like Vim.

About the author

Daniel Irvine is a software craftsman at 8th Light, based in London. These days he prefers to code in Clojure and Ruby, despite having been a C++ and C# developer for the majority of his career.

For a longer bio please see To contact Daniel, send a tweet to @d_ir or use the comments section below.

Twitter GitHub Facebook Instagram