The unreasonable effectiveness of print debugging
151–160 of 366 posts
Re: The unreasonable effectiveness of print debugging
#152Earlier quoted context omitted.
Also, in almost all languages debuggers are an afterthought. Take e.g. the situation with Golang, Haskell or Python. Either there is no useful debugger or there is one, but it came late and still cannot debug everything the language does.
Print debugging not (really) working is haskell is... Non-idea, and a bad pairing for bad real debugging. But test cases are usually easier to figure out. Presumably there's a balance discovered by people in big projects but it never seemed as good as normal approaches to me.
Re: The unreasonable effectiveness of print debugging
#153At Google, we have time-traveling debuggers neatly integrated into our cloud IDE: You can step forwards and backwards, you can inspect variables for all the values they've had or will have until program termination, and you can also see all invocations of methods (along with their parameters) that have happened or will happen.
I still use logging for debugging. Cool tech aside, I think what you really need, above everything else, is the fastest possible iteration cycles.
Re: The unreasonable effectiveness of print debugging
#154Probably the most interesting thing about development as a discipline is the near radio silence on how to debug. There is a decided lack of academic success in engaging with debugging as an object that can be studied. There are channels to learn about debugging as a stand-alone topic. Programmers don't often talk about debugging techniques in my experience. For something that takes up the overwhelming bulk of a devel…
Debugging is impossibly difficult to teach. It's much closer to "how to solve an escape room" than it is to "how to build X". Debugging requires deep understanding what you are doing and your system. It's different every time. And while there's a general algorithm you can follow: 1. Guess what's wrong 2. Ask "How would I prove that's wrong?" 3. Try it 4. If bug found, fix, if not go back to 1 How would you teach that…
Do a bisect instead. The complexity is O(log n). It's probably slower than if you guess right on the very first time, but that's less important. Debugging time is dominated by the worst cases.
1. Do something you're 90% sure will work that's on the path towards your actual goal.
2. If it works, move forward in complexity towards your actual goal. Else, move halfway back to the last working thing.
3. When you've trapped the bug between working and non-working to the point that you understand it, stop.
"The weather data isn't getting logged to the text files. Can I ping the weather servers? Yes. Can I do a get on the report endpoint? Yes. Can I append to a text file? Yes. Can I append a line to the weather log file? No. Ok, that narrows it a lot."
The real point of this is that you should spend most of your time with working code, not non-working code. You methodically increment the difficulty of tasks. This is a much more pleasant experience than fucking around with code that just won't work and you don't know why. Most importantly, it completely avoids all those times you wasted hours chasing a bug because of a tiny assumption. It's sorta like TDD but without the massive test writing overhead.
A modification for the disciplined: give yourself one (1) free pass at just taking a stab at the answer. This saves time on easy fixes. "Oh, it must have been that the country setting in the config file is off." Give it a single check. And if it's not that, go back to the slow and steady mode. Cause you don't understand the system as well as you thought.
Re: The unreasonable effectiveness of print debugging
#155Pernosco's tool is described pretty well on their website, but basically it allows you to view a program inside and out, forwards /and/ backwards, with zero replay lag. Everything from stack traces to variable displays (at any point in time in your code execution) is extremely easy to view and understand. The best part is the lightning fast search functionality (again: zero lag).
On top of this: extraordinary customer service if anything breaks (in my experience, they fix bugs within 24 hours and are highly communicative).
If you value your time I highly recommend you check out this tool.
Re: The unreasonable effectiveness of print debugging
#156Personally, 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…
As a counter-point, I think there’s an argument that folks don’t spend enough time in the debugger. But there’s a lot of value there and in fact one could use a debugger environment to unit test as even native debuggers have scripting environments. Personally, I think folks should master the debugger _first_ and during all steps learning a programming language. But similar to test-driven-development it’s a different…
Having said that, it is absolutely a requirement when working on a project for any length of time (especially professionally) to set up and figure out a debugging environment, because it is significantly more productive than printing. But the startup cost is certainly there.
Re: The unreasonable effectiveness of print debugging
#157Another aspect, where printf debugging can be better than debuggers are use-cases where timing is relevant. Some bugs don't occur when break points stop the program at certain points in time. For completeness is should be added, that there are also cases where the printf can change the performance and make it impossible to find a bug. I think the two methods are complementary and should be use in combination. However…
That said, most people don't know this is possible (the learning curve issue you mentioned), even though it's an important part of how to use debuggers!
Re: The unreasonable effectiveness of print debugging
#158More languages should have that.
Re: The unreasonable effectiveness of print debugging
#159I'm still waiting for the feature where you can conditionally stop at some breakpoint -only- if some other breakpoint/watchpoint was crossed over. It's not a conditional breakpoint, because conditional breakpoints can only watch variables, not other breakpoints. You could of course set some variable depending on whether some section was entered and then conditionally break based on that variable. But then you're back to print debugging land, having to manually insert code in order debug the program.
Debuggers are superior when it comes to interrogating the exact state of some variables, as well as the decision paths the program takes. For anything simpler, print debugging simply offers the better developer experience.
Re: The unreasonable effectiveness of print debugging
#160Earlier quoted context omitted.
As a counter-point, I think there’s an argument that folks don’t spend enough time in the debugger. But there’s a lot of value there and in fact one could use a debugger environment to unit test as even native debuggers have scripting environments. Personally, I think folks should master the debugger _first_ and during all steps learning a programming language. But similar to test-driven-development it’s a different…
In a world with perfect optimizing compilers that never introduce bugs, we should never "need" print debugging. But that's not where I live, so I'll keep using print debugging. On the other hand... adding print statements can also invalidate certain optimizations (an excellent source of heisenbugs), so I'll never stop using debuggers either