Live data from Hacker News

The unreasonable effectiveness of print debugging

buttondown.email

241–250 of 366 posts

Re: The unreasonable effectiveness of print debugging

#241
post #209

Print debugging is not that different from setting logging level to DEBUG and those logging calls should already be there in code and give meaningful insight so I don't get printing being often ridiculed. For over ten years of commercial work I used a debugger only a couple of times and in most cases it was against someone else's code, usually when things were completely broken and I needed to get backtraces from mul…

I pretty much all of these. One thing I wanted to add is decorators. There is code you might have easy access to edit to add print statements. I don’t love the spring boot docs and reading the code isn’t as useful as stepping through your specific autowired code tree. There’s definitely use cases but 95% of the time prints will get you there. Imo you should learn it because it will save you a bunch of time and headache when you need it.

Re: The unreasonable effectiveness of print debugging

#242
Whenever this comes up, I think of this quote from The Practice of Programming by Brian W. Kernighan and Rob Pike [0]:

> As personal choice, we tend not to use debuggers beyond getting a stack trace or the value of a variable or two. One reason is that it is easy to get lost in details of complicated data structures and control flow; we find stepping through a program less productive than thinking harder and adding output statements and self-checking code at critical places. Clicking over statements takes longer than scanning the output of judiciously-placed displays. It takes less time to decide where to put print statements than to single-step to the critical section of code, even assuming we know where that is. More important, debugging statements stay with the program; debugging sessions are transient.

I found this lines up with my personal experience. I used to lean on interactive debuggers a lot, and still enjoy using them. They're fun and make for good exploring. But the act of figuring out where you want to print really makes you think in ways that interactive debugging cannot. I find the two forms really complement each other.

[0] https://logging.apache.org/log4j/2.x/manual/index.html

Re: The unreasonable effectiveness of print debugging

#243
post #222

With the Jetbrains products breakpoint debugging is so easy that i use it for development all the time. Evaluating expressions inside a breakpoint while developing provides many answers in a mich tighter feedback loop, even with go or something equally fast. If i don't have the jetbrains tools i default to print debugging because everything else is too much of a hassle.

I wish that evaluating expressions in a C++ debugger worked more often. It fails half the time (due to "optimized out") in Visual Studio C++, and 80+% of the time (for various reasons) in Qt Creator, even in debug builds.

Maybe it works better in non-C++ languages.

Re: The unreasonable effectiveness of print debugging

#244
post #179

Earlier quoted context omitted.

You can also do print debugging with a debugger. Just have a breakpoint that doesn't halt, but instead simply prints the values of interest to the debugger console. This is particularly nice for things like debugging interrupt handlers where the time taken to print output normally is too much to accept.

Watched variables they were called once upon a time. Also, I think what you suggest to do here is way harder to learn than printing.

Perhaps, but that lends credence to the theory that people using print debugging may just not have learned how to effectively use a debugger yet.

Re: The unreasonable effectiveness of print debugging

#245
post #203

Earlier quoted context omitted.

> typically not as general-purpose as print In my domain which doesn't usually cover distributed systems printf can be worse because it introduces synchronization primitives that have caused race conditions to disappear(and that race condition causes second order heap corruption or the like). On one platform system memory was so small(8mb total) that each output to stdout went over the serial link slowing performance…

> Like I said, different tools for different uses, and really depends on the context We totally agree, and I'm not sure what we're arguing about--perhaps you can fill me in. I'm arguing that print is almost always worse than any specialized tool. (After all, who would use a specialized tool worse than print?) There is not a one-size-fits-all tool, and print is not a one-size-fits-all tool. Indeed almost every seasone…

I think we're mostly arguing about how useful the various approaches are. At least for me print debugging is a measure of last resort unless I want to extract some historical data out and I know it won't influence the timing of the issue I'm trying to chase down.

With print debugging your inserting the whole build + deploy + repro setup loop into your debugging, if that's a long time(say 20 minutes in one job I had with production hardware) you're in for a world of pain. I find that just about any other tool usually is an order of magnitude more efficient.

Also even the "step debugger" tools do the same thing you'd do with a print. LLVM for instance uses the IR JIT API to generate watch/eval values: https://releases.llvm.org/9.0.0/docs/ORCv2.html#use-cases

IMO you should relentlessly optimize your iteration times, that's the inner loop of development speed and print debugging fares pretty poorly in that area for all the reasons above.

Re: The unreasonable effectiveness of print debugging

#246

Personally, I think my biggest reason for using print debugging is.. it works. In C++ I often find the debugger doesn't find symbols on projects built with configure/Make. If I have a Java Gradle project I have no idea how to get it into a debugger. Python debuggers always seem fragile. Rust requires I install and use a "rust-gdb" script -- except on my current machine that doesn't work and I don't know why. I'm sure…

Especially when you need to run your code on a remote server as part of a bigger platform like some Cloud or Serverless system.

These systems likely already have a way to get logs, but good luck getting a debugger to work there.

Re: The unreasonable effectiveness of print debugging

#247

I agree about being able to see the whole program execution. This is particularly useful for multithreaded code since it provides a linear view into how the program actually executed. How are you supposed to figure out that A happened before B in a multithreaded program using only a debugger? With adequate logging, even if you don't log the precise times for A and B, you can often infer the ordering of these events b…

> How are you supposed to figure out that A happened before B in a multithreaded program using only a debugger? Setting printpoints, letting them be hit and continuing... this whole thread seems to arise from the fact people have not learned to use debuggers.

Re: The unreasonable effectiveness of print debugging

#248
post #166

Personally, I think my biggest reason for using print debugging is.. it works. In C++ I often find the debugger doesn't find symbols on projects built with configure/Make. If I have a Java Gradle project I have no idea how to get it into a debugger. Python debuggers always seem fragile. Rust requires I install and use a "rust-gdb" script -- except on my current machine that doesn't work and I don't know why. I'm sure…

Print debugging always works, but also: it lets the programmer customize their view of the program’s (very, very large) hidden state in any way imaginable. Step debuggers are the “no-code” equivalent: extremely useful for the purposes for which they were designed—and often the better choice there—but inherently limited. Geoff’s not wrong in invoking Bret Victor’s Learnable Programming argument that being able to trac…

> it lets the programmer customize their view of the program’s (very, very large) hidden state in any way imaginable.

I’ve been trying to articulate this to myself for a long time. Thank you.

Re: The unreasonable effectiveness of print debugging

#249
post #208
post #166

Earlier quoted context omitted.

Print debugging always works, but also: it lets the programmer customize their view of the program’s (very, very large) hidden state in any way imaginable. Step debuggers are the “no-code” equivalent: extremely useful for the purposes for which they were designed—and often the better choice there—but inherently limited. Geoff’s not wrong in invoking Bret Victor’s Learnable Programming argument that being able to trac…

This is a lot of words but I wonder if you've ever worked with a debugger with watchable variables or immediate mode code execution. I find it odd you say print debugging is more flexible.

Using a debugger is largely passive - it shows you what is actually happening.

Debugging via print allows you to step outside and peer in ie it is active.

Print debugging can be prone to bugs within itself which may cause additional ignorance about the potential bugs being diagnosed. How meta can you get? 8) There's also the effect of the effort of actually looking - that may or may not have an effect.

Anyway, the discussion here is largely ignorant of language and function. At the moment I spend time fiddling up Python and OpenSCAD scripts if I dig out a programming language. For me, print is really handy. For a Linux low level latency sensitive driver in highly optimised ASM n C I suspect this matter is moot.

Re: The unreasonable effectiveness of print debugging

#250
post #209

Print debugging is not that different from setting logging level to DEBUG and those logging calls should already be there in code and give meaningful insight so I don't get printing being often ridiculed. For over ten years of commercial work I used a debugger only a couple of times and in most cases it was against someone else's code, usually when things were completely broken and I needed to get backtraces from mul…

When I start to use a new server framework, I like to step thru the main loop, just to see how it works with system calls/listens/accepts/reads and how it dispatches up the stack. But for debugging, I like to a) make it reproducible, b) read the code, c) add logging to help with any deductions that b yields. (Sometimes will just go to b if it's a simple bug).
Post reply on HN