Live data from Hacker News

The unreasonable effectiveness of print debugging

buttondown.email

251–260 of 366 posts

Re: The unreasonable effectiveness of print debugging

#253

I can just write print(whatever) and get the job done, I don't want to put breakpoints and search for a data structure I need. Why can't I write something like this: breakpoint { debug(var) } ?

Assuming you mean something like "leverage the debugger to print, so I don't have to do it in code": you can, in most debuggers. This is effectively a "log breakpoint", or a "conditional breakpoint" where your condition is "print(thing)".

I use debuggers even for print-debugging for this kind of reason. No need to re-compile between changing prints, just re-run - the debugger session will hold them from previous runs, you can temporarily disable them with a single click, etc. It's FAR faster and more flexible.

Re: The unreasonable effectiveness of print debugging

#254
post #208

Earlier quoted context omitted.

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 d…

(most) debuggers can print - I often use conditional breakpoints with the "condition" "print(thing)". It works great, doesn't require re-compiling, can be enabled/disabled with a single click, etc. It's handy when you want to see a lengthy sequence all at once.

Re: The unreasonable effectiveness of print debugging

#255
Almost all the reasons people use print debugging can be overcome by improving debuggers --- and to some extent already have been (in the words of William Gibson, the future is already here, it's just not evenly distributed yet). I think it's important for people to understand that the superiority of print debugging is contingent and, for many developers, will not persist.

Record-and-replay debuggers like rr [0] (disclaimer: I started and help maintain it), Undo, TTD, replay.io, etc address one set of problems. You don't have to stop the program; you can examine history without rerunning the program.

Pernosco [1] (disclaimer: also my baby) goes much further. Complaints about step debuggers (even record-and-replay debuggers) only showing you one point in time are absolutely right, so Pernosco implements omniscient debugging: we precompute all program states and implement some novel visualizations of how program state changes over time. One of our primary goals (mostly achieved, I think) is that developers should never feel the need to "step" to build up a mental picture of state evolution. One way we do this is by supporting a form of "interactive print debugging" [2].

Once you buy into omniscient debugging a world of riches opens to you. For example omniscient debuggers like Pernosco let you track dataflow backwards in time [3], a debugging superpower print debugging can't touch.

rr, Pernosco and similar tools can't be used by everyone yet. A lot of engineering work is required to support more languages and operating systems, lower overhead, etc. But it's important to keep in mind that the level of investment in these tools to date has been incredibly low, basically just a handful of startups and destitute open source projects. If the software industry took debugging seriously --- instead of just grumbling about the tools and reverting to print debugging (or, at best, building a polished implementation of the features debuggers have had since the 1980s) --- and invested accordingly we could make enormous strides.

[0] https://rr-project.org

[1] https://pernos.co/about/overview

[2] https://pernos.co/about/expressions

[3] https://pernos.co/about/dataflow

Re: The unreasonable effectiveness of print debugging

#256
post #203

Earlier quoted context omitted.

> 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 w…

> I think we're mostly arguing about how useful the various approaches are.

Ah, that's fair.

> At least for me print debugging is a measure of last resort

Right, and I think this depends on the domain. For lots of mature environments, this makes sense -- there's been years for tooling to catch up to the kinds of bugs people run into, possibly corporate money being put into developing debugging tools, etc.

> IMO you should relentlessly optimize your iteration times, that's the inner loop of development speed and[...]

Agreed, though the effect on print debugging on iteration time is very environment-dependent.

> [...]print debugging fares pretty poorly in that area for all the reasons above

Adding console.log to a web app can be a trivial change (though of course reproducing app state is another issue) -- again very environment-dependent.

Re: The unreasonable effectiveness of print debugging

#257

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 o…

There's a part of me that wants to say that that opinion has to be taken with a grain of salt and a lump of paying attention to who is offering it.

Circa 1999, one would assume that Brian Kernighan and Rob Pike are largely drawing experience from working with C, which is a relatively verbose language. Single stepping through C code in a debugger is indeed a laborious process.

If you read accounts from Smalltalk developers, on the other hand, it's clear that they very nearly live their entire lives inside the debugger, and consider it to be an enormous productivity booster.

I would guess that there are several effects going on there. One would be that, in terms of how much effective work it accomplishes, a line of Smalltalk code is generally not equivalent to a line of C code. That has a big impact on just how many steps are involved in single-stepping your way through a region. The other is the nature of the debugger itself. Gdb and Smalltalk debuggers are wildly different pieces of software.

Re: The unreasonable effectiveness of print debugging

#258
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.

I have. What information exactly can you get from a debugger with watchable variables and immediate mode code execution, that you can't get from print?

I'm not making the argument that people shouldn't use debuggers -- obviously if there's a good one that does what you need, it'd be silly not to use it. And good debuggers are great.

But what happens when you're working on a distributed system? Or multiple processes on a single system? Or...etc. etc. -- debuggers are almost always built to support a particular set of use cases for a particular set of domains. Step outside, and they're not usually as useful.

print always works. It's almost never the best. It's more flexible because it can almost always be used.

Re: The unreasonable effectiveness of print debugging

#259

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 o…

There's a part of me that wants to say that that opinion has to be taken with a grain of salt and a lump of paying attention to who is offering it. Circa 1999, one would assume that Brian Kernighan and Rob Pike are largely drawing experience from working with C, which is a relatively verbose language. Single stepping through C code in a debugger is indeed a laborious process. If you read accounts from Smalltalk devel…

Perhaps it has to do with dynamism? I find myself "debugging" way more in dynamic languages that emphasize interactive development. At that point, the line between running code and debugging gets pretty blurry, since "stopping" execution at some arbitrary place is not very different from normal development anyway.

Re: The unreasonable effectiveness of print debugging

#260

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 o…

There's a part of me that wants to say that that opinion has to be taken with a grain of salt and a lump of paying attention to who is offering it. Circa 1999, one would assume that Brian Kernighan and Rob Pike are largely drawing experience from working with C, which is a relatively verbose language. Single stepping through C code in a debugger is indeed a laborious process. If you read accounts from Smalltalk devel…

Linus used to be against kernel debugging for the longest time.

The core of his position (as I understand it) was that regularly needing a debugger is a sign that your software has "gotten away from you". You've let the software get to a state where it cannot easily be understood from the architecture and program text alone.

I do think debuggers can be useful when building up comprehension - particularly of other people's software.

It's very time consuming though, and at each "trace" you're only seeing one path through the program. Good architecture and documentation lets you understand all the possible paths at once.

Post reply on HN