Excerpts from Coders at Work: Joe Armstrong Interview (2013)
ivory.idyll.org
ivory.idyll.org
Interesting. I came of age before debuggers were a 'thing' available to common kids at home (80s BASIC, etc). As I've worked in various environments over the years, debuggers are nice when available, but they're not always available. Code is only running in production, you don't have full access to a debuggable environment, company won't pay for tool X, etc. print/log statements always work, regardless of what tool/language you're working with. Or... 'always work' enough of the time that it's not surprising it's a common theme.
I jump between client projects relatively often (consulting) and while I do use debuggers, I don't use them exclusively (perhaps no one does?). The longer I'm in a codebase, the more likely it will be that I'll end up with a full debugger setup and get comfortable stepping through all the bits.
Using debuggers makes a lot of sense in this case. If I had to switch context that frequently between relatively stable applications, it would be helpful to have a debugger framework for doing work.
`printf` statements are helpful when the error exists beneath the debugger: in the application framework itself.
> they're not always available
100% agreed. `printf` is "one tool" I can use to follow the control flow of a function call across frameworks, programming languages, and even operating systems. It's also something I can reliably assume my coworkers have in their tool belt, and thus provides a common language that even multiple different organizations can use to cross-collaborate a specific debugging session.
The only time I normally used a debugger is for post-mortem debugging - looking at a production core file for a multi-threaded process to see where it was in the code (and maybe inspect a few variables) when it crashed. If the core isn't sufficient to isolate the problem, then I'll add more logging to isolate it next time it happens.
During development, printf is just so much more convenient. I'll always put print/log statements in my code as a combination of tracing execution flow and to validate assertions / check that variables have the types of value that I'm expecting. Often this sort of pre-emptive debugging is all you need, and if not it should point to exactly where you need to sprinkle a few more print statements to isolate an issue.
The convenience of print statements is that once you've put them there, at critical points in your code, and printing critical values, they are always there (can conditional them out once code is working, if wanted), as opposed to having to go into a debugger, navigate to points in code, setup breakpoints, monitor variables etc ...
Of course coding discipline / experience plays into writing bug-free or easy-to-debug code too.
Modern development, scripting languages and web development, I rarely use a debugger, setting it up for each of the various languages we jump to is too much bother.
This is where Go's superfast compiles shine. Debuggers-B-Gone.
I had noticed the disdain for debuggers and it used to make me feel a bit inferior for relying on them but then found that John Carmack loves them so I feel better now. Ha!
This is why we have logs, metrics, and traces. They attach at least some of the same instrumentation you'd get out of a debugger but all the time. You lose the flexibility to stop, step, and modify program behavior at runtime, but also gain data that is representative of what happens at full speed, which may be the only time certain bugs manifest anyway.
Also most of them (at least) are known to have a focus on the practice of programming itself. They are literally authors/stewards of established algorithms, programming languages, operating systems and browser engines. What else would would you expect?
For example, if you watch any talks by Joe Armstrong you'll immediately perceive it as a kind, funny and down-to-earth guy.