Use all the help available
printf
is not the only debugging tool. It's useful when you're testing a
hypothesis, and when you can repeatedly and rapidly reproduce the failure. An
automatic test runner, such as Karma helps
here. In JavaScript, console.trace
complements console.log
. Other languages
have equivalents.
Debuggers are great for exploration. They let you look up and down the
stack. They make it cheap to peek at all manner of variables without cluttering
the output. They allow you to Go to the source. They don't
swallow type information the way stringification for printf
does. It happened
twice in one week that I spent fifteen minutes trying to find a bug in my Ruby
code by running through it in my head. Each time I finally fired up
Pry with
pry-byebug and found the
problem within a minute in a place I hadn't expected.
The developer tools in the browser are known to everyone, I hope. I use the
console, the network tab and the debugger all the time. Sometimes using the
debugger appears to change the behaviour of the system. I haven't gotten to the
bottom of this. In these cases, I have to fall back to printf
and friends.
Verbosity is similar to printf
, but sometimes you can't get the
information you need by adding printf
to your own code. For example, there
were two cases when I needed to know which test case was causing a hang or a
certain warning. printf
or a breakpoint didn't help, because I didn't know
where to add them. The abovementioned Karma normally doesn't tell you which test
it is running at any moment, but in debug mode it does. Minitest only gives you
dots, but with
minitest-reporters
it, too, logs the test names as it runs.
Summary
There is a hurdle in front of everything but printf
. Setting up the tool,
learning the tool takes effort. But it's worth it. Once upon a time I tracked
down an intermittent failure that had been bugging the team for two years. I did
it by connecting Winpdb over SSH to a Python process running in a Docker
container during a Jenkins build. As if this is not enough, the failure was
occuring in Python code within a YAML file, where the debugger couldn't jump
directly. So I had to devise a way to gingerly step through the interpreter of
the YAML data without messing up the setup and having to restart. – Jump those
hurdles.