The Joy of Debugging (or: Finding Out How Things Don’t Work)
Writing, whether it’s natural language or a programming language, is hard. Typos, misused and misspelled words, mangled syntax, a lack of clarity: debugging computer code, like proofreading and editing a natural language narrative, is the art of removing– or at least smoothing– these issues. But as your programs become more complex and start talking to other programs over a network, debugging evolves into a journey of discovery through a system of interconnected programs and resources.
A relentless, plodding mediocrity1 has a significant advantage over a lazy “genius” when it comes to debugging. Tenacity, curiosity, a comfort in knowing that things happen for a reason in the computer world, and a willingness to methodically follow the bug through a system are the virtues that make one good at debugging.
It’s the plodding and following that make debugging a daunting though transparent endeavor. The bug is hiding somewhere, and if you follow its trail you will find it and crush it.
It can appear at runtime, but it can’t hide.
Let’s retrace the steps of a debugging journey I enjoyed recently at work. The bug appeared in a popular web app.
To illustrate the bug and the debugging process, I created a simple, contrived example. You can reproduce the bug and debug the system yourself with the code here.
On a simple web page we have a gray box with a greeting (“Hello, World”, of course).
This is what we should see:
But this is what we’re getting:
No greeting– how rude.
Since we’re using javascript, let’s look at the developer console in the browser (shown here in Firefox) and check for error messages:
Everything seems fine in the console; let’s look at the code. The greeting is taken from a JSON file that we request after the page loads:
$(document).ready(function(){
$.getJSON('json/bug.json', function(data) {
$('#greeting').html(data.greeting);
});
});
Perhaps something is going wrong during the getJSON
call. Let’s put a console.log
statement in the callback:
$(document).ready(function(){
$.getJSON('json/bug.json', function(data) {
console.log('Success!');
$('#greeting').html(data.greeting);
});
});
Now let’s reload the page and see if the ‘Success!’ message is logged to the console:
Still nothing in the console. This means the success
callback from the getJSON
call is not executing, so something is going on with the request for the JSON resource.
Let’s reload the page and check the Network tab in the web console to see the request for the JSON resource:
The status code for the GET request for bug.json is 200:
So the bug isn’t likely to be a network issue. Let’s take a closer look at the response from the bug.json request:
Boom. There’s a SyntaxError
coming from JSON.parse
, so bug.json has something in it that isn’t valid JSON. But what is it? At first glance everything looks OK: no obvious issues with the commas separating the fields, the double-quotes are closed correctly– so what’s going on?
Take a look at this diagram from the JSON website (it’s like a flow-chart for valid states during the process of parsing a string):
A single-quote is not on that list of things that can follow a \
, so "\'Hello, World\'"
is not a valid string in a JSON file. Escaped single-quotes in a string caused a SyntaxError
when JSON.parse
tried to make sense of the stuff in the bug.json file. We found the bug.
You may take a look at the getJSON
call in the code and say, “let’s just inspect the JSON file it’s trying to access”. The thing is, in the web app I debugged at work, the resource we wanted was not a simple static file that we had in version control. And the offending text in the JSON response (the analog to the bad
field in bug.json in the example) came from user input that we didn’t validate or process in any way. Inspecting the request at runtime was the best way to find out exactly what was happening.
In the battle against that bug some knowledge of javascript and JSON are certainly necessary. But the most important thing you need to find this bug, or any bug, is an irrepressible desire to follow the bug until it is crushed. If you follow the bug relentlessly you will find it and kill it. In debugging, as in life, you only fail when you give up.
1
“In truth, I am nothing but a plodding mediocrity — please observe, a plodding mediocrity — for a mere mediocrity does not go very far, but a plodding one gets quite a distance. There is joy in that success, and a distinction can come from courage, fidelity and industry.” Benjamin Cardozo, “The Game of the Law” in Law and Literature and Other Essays and Addresses (1931), p. 163.