We are living in an age of unprecedented language creation. Between the explosion of languages on the JVM and the new native languages, we find ourselves with a happy surfeit of very interesting choices. These options are not just the toy creations of comp-sci undergraduates, but sophisticated products with extensive libraries and active communities. Where they tend to be weak, however, is in tooling. And unfortunately, for many language developers, tooling is a metaphor for the coding front end: They strive to create editor plugins to provide basic syntax assistance. The more important support for debugging is often consigned to the use of
printf-like statements to dump
trace statements and variables' contents to the console.
- One Phish, Two Phish, Three Phish, Fraud Phish
- Threat Intelligence Spotlight: The Shifting Framework of Modern Malware
I have always found this substitution of
printf for debugging to be a profoundly wrong conflation of two concepts. Yet, because we've all had the experience of using
printf or its equivalents to help chase down bugs, we tend to go along with the proposal. Some well-known developers even proclaim their preference for
There are multiple aspects of
printf statements that make them very poor substitutes and, in fact, at times dangerous tools.
Location. Martin advises "judiciously placed print statements." Well, if you're in a serious debugging mode, judiciously placing
printf is a very difficult thing to do. It implies some strong knowledge of the nature of the cause of the defect you're chasing. My experience is that, frequently, you get the first attempt at
printf wrong, and then must start to guess where else to place the statements. Sometimes, it's not even guessing: You need to put them at several upstream points to coarsely locate where a variable unexpectedly changes values. Finally, when you get the right location, you must then add new statements to track down why the variable is changing. It's a mess that brings me to the second point.
Time cost. Every
Complexity. While conceptually nothing is simpler than dumping a variable to the console, in fact, it's no trivial matter. This is particularly true of data structures, especially those containing pointers. Now, the
dump statement is useful. Debuggers handle this transparently and allow you to walk lists and arrays with no difficulty.
Clean up. Congratulations, you found the bug! Now, it's time to clean up your
In almost every dimension, the dumping of variables to the console is an inferior alternative to using the debugger. It takes just as long, if not longer, to find defects, and the practice inserts detrimental artifacts into the codebase.
When I hear developers say that they're happy debugging with