Debuggers aren't bad. But neither is printing. Knowing when to reach for them is probably a bit more key.
Debuggers aren't bad. But neither is printing. Knowing when to reach for them is probably a bit more key.
The problem is that the two print statements will only catch the bug if they are the right two, based on a correct hypothesis of what the bug is. Which, with a debugger, won’t require stepping, but setting two breakpoints, doing a run-to-breakpoint, and inspecting values.
Stepping is required when you are exploring behavior because you don’t have an easily testable hypothesis about the source of the bug.
As you note, debugger breakpoints aren't magically better than print statements when I'm investigating a hypothesis – I'm no more likely to put them the right place than I would have put print statements.
And then there's a class of problems that neither debugger nor print statements will help: many years ago a very junior co-worker was wondering why his C code was giving the wrong answer for some math. It took me pointing out that one of the numeric types he was using in his code was different from the rest (I think it was #defined elsewhere, in some library, as an integer type). When the compiler did the math it had to do some type coercing.
A debugger and watches on the values of concern absolutely will help with that (so will properly placed print statements), so its a really bad example. (Of course, strong typing helps even more with that particular case.)
Can't I also bisect with breakpoints?
The worst developers I've ever known always have their "this is the best way to do everything" hill they die on.
Same applies to other debuggers.
It is not only the debuggers, but also OS and language runtime tracing facilities like DTrace, eBPF, ETW, JFR, ....
Many devs aren't 10x because of QI, rather because they learn and make use of the tools available to increase knowledge about the platform.
So we get generations that use vim and Emacs like notepad, create Makefiles by copy-paste and barely know gdb beyond set breakpoint, run, step and continue.
Using C as example, but feel free to extrapolate to another language.
And no I am not exaggerating, this was the kind of students I would get into my lab when I spent a year as TA in 1999/2000, and naturally would have to get them up to speed into good programming practices.