Sunday, November 14, 2010

Software is remarkable stuff. Sometimes, perhaps because we work with it all the time, we forget just how remarkable it is. Very little else in human experience is as malleable, allowing us free rein to exercise our ingenuity and inventiveness almost without limits. Also, with a very few exceptions, software is deterministic—the next state is completely determined by the current state, and (crucially) we have complete access to all of that state whenever we want it.

Compared to traditional engineering, we are spoiled. What do you think a Formula One engineer would give to be able to instantaneously stop an engine when it’s rotating at 19,000 revolutions per minute and examine every aspect of it in minute detail? To see the precise state of each component while under pressure and stress, for example, or to dynamically record the shape and position of the flame front within the combustion chambers during ignition?

It is exactly this kind of trick that we are able to perform with our software, which is why the empirical approach is particularly powerful when debugging.

Empirical Approach. Construct experiments, and observe the results. Empiricism relies upon observation or experience, rather than theory or pure logic. In the context of debugging, this means directly observing the behavior of the software. Yes, you could read the entire source code and use pure reason to work out what’s going on (and on occasion you may have no other choice), but doing so is usually inefficient and dangerous. You can track the problem down much more effectively by carefully constructing experiments and observing how the software behaves. Not only is this faster, but these observations force you to reexamine flawed assumptions in your mental model about how the software behaves. The software itself is the most powerful tool in your toolbox—allow it to show you what’s going on.