/*---[ Thesis and Antithesis ]---*/
Not long ago, there was a posting on slashdot from a self-proclaimed hacker (in the good sense) asking for advice on how to become a professional software engineer to target jobs in the corporate IS world.
"Learn to use a debugger" was one piece of advice he got. Sounds good to me, I thought, although I'm not sure hackers don't know how to use debuggers - gdb, the emacs Grand Unified Debugger and the DDD debugger were all arguably written by hackers. But the "learn to use a debugger" guy went on to ridicule a co-worker of his that had never grokked how to become one with his debugger and preferred print statements. This was such a deep lapse in his skillset and mentality that in their view he couldn't keep up with the awesomeness of the debugger crew and they were glad when he finally left the company.
At my job, I overhead a bathroom conversation (a great place to eavesdrop) where a similar view was taken: "I don't think he knows what he's doing - he put println statements everywhere".
I was recently rereading parts of The Practice of Programming by Brian W. Kernighan and Rob Pike. To provide a little counterpoint, I will quote something they had to say about this debate:
As personal choice, we tend not to use debuggers beyond getting a stack trace or the value of a variable or two. One reason is that it is easy to get lost in details of complicated data structures and control flow; we find stepping through a program less productive than thinking harder and adding output statements and self-checking code at critical places. Clicking over statements takes longer than scanning the output of judiciously-placed displays. It takes less time to decide where to put print statements than to single-step to the critical section of code, even assuming we know where that is. More important, debugging statements stay with the program; debugging sessions are transient.
Perhaps Kernighan and Pike are just hackers.
And just as I was writing this blog, Uncle Bob Martin (re)tweeted this note: Using a debugger is a code smell.
/*---[ Synthesis? ]---*/
The InfoQ article points to two companies that offer recording debuggers for the JVM:
- Chronon: http://www.chrononsystems.com/video-exceptions/
- Replay Solutions: http://www.replaysolutions.com/products/demo-video
I did a little investigation into Chronon's debugger. It does instrumentation of the Java bytecode instruction set of your code to record everything that happens in the JVM occur over the life of an application in all threads. No source code changes are required. They use an analogy of a “flight data recorder” for a Java program.
They claim the instrumentation is lightweight enough to be able to run it in production and certainly during formal QA testing. It basically creates a dump file of application state that can be opened in the recording debugger and played backwards and forwards. For example, you can pick a variable and see all state changes it ever had during the life of the program and then jump to any of those timepoints. The stack traces will show you all current threads and you can jump between them to see what state was there.
No breakpoints are required (or even possible), since you are just moving around in a program that has already run and looking at snapshots of time. You can do things like “show me all times which method X was called and from where” and then jump to any of those to see program state and execution at that point.
The other big selling point is that you do not have to recreate the full environment in which the bug occurred – you are just watching the state changes in the JVM so you don’t need to hook up to the database, the network, the message queues or whatever else to reproduce the issue.
This could be especially powerful for debugging multi-threaded apps, which is quite difficult using traditional debuggers.
Perhaps this is the synthesis of the divide expressed in the opening section of this essay. I haven't tried one yet, but it is definitely on my todo list for the future. I'd love to hear from anyone who has tried using a recording debugger.