The old Jasik debuggerfor the classic Mac OS had this cool quote in the help somewhere. Forgive me for paraphrasing:
Any halfway decent programmer can debug the problem if they can display the relevant variables in an understandable way.
Of course for most programmers these days this means an interactive debugger. Which is fine, but tends to be misused to do step-step=step boredom debugging.
Functional and logic languages win here. The SWI-Prolog debugger includes ‘r’, retry, which restarts the execution at the enclosing predicate, so you don’t have the common step-step-over-over-oh crap… phenomenon. If you do, you just hit r, step over down to the problem, and this time step in.
Advantages of state free systems.
Other people favor print statements. There’s definitely a time for print statements. They can focus attention on what’s relevant. But they can often be like sightseeing in a submarine, and it’s perishingly easy to end up sticking debugging statements everywhere. This becomes logging.
Logging as debugging tends to be most useful for figuring out who to blame after production goes down. Needing lots of logging is often a smell that your system has grown beyond your control.
But often Jasik’s right. I’ve frequently found it useful to build a little GUI tool into my program that lets me browse the important data structures. A dynamic, animated tool to display data is often only an hour or two’s work, and gets repaid many times over.
Debuggers single step. You should ask yourself if you actually need to be doing that.
I used to have a collection of short sound clips. I’d insert calls to play these as the program ran in debug mode. This was vastly nifty – you soon learned what the happy sound was, and could step over big hunks of code fairly safely as long as they made the right hooting and burping sound. Also handy for improving performance.
You can also make a little interface that displays a pixmap. Shift the image left one, then draw in pixels with values for colors each frame. Make a rollover that tells you variable names based on rows.
Or any other way of displaying data in a way that’s well connected to the underlying model.
Yes, you probably do have a view as part of the final product. But it’s designed to hide abstractions. Your debug UI is designed to help you understand them.
If you can read the stack depth, a moving graph of that can be informative. So can graphs of CPU time by thread. SWI-Prolog provides such graphs as a built-in thing. Query
Back in Burroughs Cobol days we used to be able to tell what pass the compiler was in by leaning on the cabinet of the hard drive – the motion was characteristic.
Some intelligence and imagination is often a better solution for debugging than a death march with the interactive debugger.