Skip to content

Herman J. Radtke III

Writing debuggable code

Coding standards are religious in nature, ranking high on the list near vim vs emacs.  Paul Reinheimer woke up many in the twitterverse with a simple post:

Paul Reinheimer handling errors early tweet

Debug-ability is simply writing code in such a way that it makes it easy to step through the code in a debugger.  I built my career using a debugger.  My first programming job out of college was at a C shop that started in the late 1980's.  My college professors instructed me using C++, so I was somewhat familiar with the C/C++ variety of languages.  After looking at the C code on my first day of work, I quickly realized I had a lot to learn.  Luckily I was well versed in gdb.  For those not familiar with gdb, gdb is the GNU C debugger.  It is probably the most important tool for anyone working with the C code.  There was no way I could grok some of the logic, such as pointer arithmetic, in the code without stepping through it with gdb and poking at it.  This invaluable experience has made me a debugger zealot.  Not only that, but I find that fixing bugs is usually a therapeutic exercise for me.

I am constantly surprised at the number of web developers who still do not use a debugger. Before Xdebug and Firebug were created, web development drove me nuts.  Finding bugs always felt like game of cat and mouse as I riddled the source code with calls to die('here') (or alert('here') for the Javascript code) until I found the bug.  Yet, I still find many developers using a combination of y() and die() to solve problems.  Xdebug has been out for years, is easy to setup and makes finding that bug in your code so much easier.

So, what do I consider debuggable code to look like?  Code that has one statement per line.  I don't care about braces, naming conventions, line endings, tabs/spaces or anything else that has little effect on how the code runs.  One statement per line makes it much easier to determine exactly what the code is doing when stepping through the debugger.  This may seem like a pain since it will cause files to have more lines, but I don't care.  The time it takes to write the code is only 20% of that codes lifecycle.  The other 80% is maintenance where it is being extended, bug fixed and maybe even refactored.  Taking a little bit of extra time to wrote easy to debug code in beginning is an investment that will quickly pay off.

Here are some examples of code that were not written with debug-ability in mind:

if (!$foo) doSomething();

This makes it hard to tell if doSomething() was actually called.  Sure I can print the value of $foo in the debugger, but letting the debugger step through the code leaves all guess work out.  There are still a lot of developers who think doSomething() will be executed if the previous line of code was: $foo = array().  No amount of var_dump is going to show that an empty array is falsy in php.  Putting the call to doSomething() on a second line makes it very clear if that line of code was executed when stepping through it on the debugger.

if (firstFunc() && secondFunc()) {
    // do something ...

How do we know if both functions were called?  We might add breakpoints to both functions so we can track it, but it is much easier to assign the results of each function to a variable and put the two variables in an if statement.

if ($a && ($b || $c) && !someOtherCheck()) {
    // do some stuffs ...

Similar to the last line of code, but it is important to note.  Complex if statements are very hard to debug.  I prefer to break this statement apart into separate if statements and use a variable or two to track the results of each section.  This might not always be possible, but it works a great deal of the time.

$r = $data[isset($a) ? $a : 'default'];

Logic inside to create an array key is fine, but assigning it to a variable makes it a lot more clear as to what is being looked up.  I chose to highlight a ternary operator here as I see a lot of younger developers using it for the sole reason that it is less typing and takes up less space than writing out a proper if statement.

All of the above statements can be inspected using a debugger with a little extra work, but when you are stepping through hundreds of lines of code searching for a bug all of these little bits of extra work add up.  The debugger does not lie and the simplest little bits of code can hide the most glaring bugs.  Start writing code with debug-ability in mind and, if you have not already, start using your debugger.