But perhaps it's a lack of knowing what a debugger can deliver.
A debugger gives you the ability to immediately dive in and instantly inspect the complete stack trace, all the values on the stack, all the values of local variables, etc. Without restarting the program or calling out specifically what you're going to want to inspect ahead of time.
A debugger will "pause the world" and let you see all the parallel stacks.
A debugger will let you set conditional breakpoints. If you need to debug the conditions for when a variable gets set to a particular value, a conditional breakpoint on the variable set to break when it's set to that particular value makes that a doddle.
A debugger will let you enumerate collections and re-write values on the fly.
A debugger will let you break on exceptions, even ones normally caught and handled.
A debugger can launch and attach itself.
All of that is a massive force-multiplier and time-saver, which print debugging doesn't deliver.
I use my debugger often, but sometimes you need to track the value of something over time (say, over 1000 iterations) and a debugger can't show you that.
So prints are still relevant. Debugger are more for "needle-in-haystack" stuff I think.
A debugger that could record the execution over time (and query that execution), that would be great. I know there are some, but are there for python for example ?
Do you mind providing examples? I’m not sure what I would search to find that and I’m interested in the idea.
Admittedly, I mostly develop with sbcl and slime, so the judiciously place 'break' statement brings you to a stack trace.
Also with sbcl/slime, you can do ESC-. on a function and go to the actual source, even deep within the core of sbcl itself.
Nonetheless, I mostly depend on logging statements and print statements. When I need to go to python, print statements give most of what I need.
Linus Torvalds:
> I don't like debuggers. Never have, probably never will. I use gdb all the time, but I tend to use it not as a debugger, but as a disassembler on steroids that you can program.
> I don't think kernel development should be "easy". I do not condone single-stepping through code to find the bug. I do not think that extra visibility into the system is necessarily a good thing.
> Oh. And sure, when things crash and you fsck and you didn't even get a clue about what went wrong, you get frustrated. Tough. There are two kinds of reactions to that: you start being careful, or you start whining about a kernel debugger.
> I happen to believe that not having a kernel debugger forces people to think about their problem on a different level than with a debugger. I think that without a debugger, you don't get into that mindset where you know how it behaves, and then you fix it from there. Without a debugger, you tend to think about problems another way. You want to understand things on a different _level_.
https://lkml.org/lkml/2000/9/6/65
And I agree. At least for me, print debugging goes a long way, and I'm already invested in building mental models about code. I think using a proper debugger has to be the last resort, because nothing else works and it's time to get into the ugly details. Two valuable avenues for producing good code are formal verification (and its ilk, such as specification) and horse sense/common sense, which combine to say that we should have rigorous mental models that impose on our code. That's the primary objective, to me. The use of tools such as debuggers is secondary, and in my experience, largely neutral or harmful. There's the classic caveat of "if your goal is to ship code fast, then this isn't practical", which is fair, but I have some things to say about shucking off that culture.
That's not to say I don't also use debuggers when necessary, I just reserve those for very hairy problems that can't be solved any other way, e.g. stepping into dependencies. Let's not forget that debuggers have their limitations too, e.g. release build GC optimization (or indeed any release-only bug), and any init process where you have to attach the debugger after the startup, fundamentally cannot be debugged using debuggers.
You can design a house on paper, but you need e.g. mallets and wheelbarrows to build it; you can design software with "tools for thought", more or less computerized, but you need the automation offered by CI, version control etc. to handle the more concrete aspects properly.