12 ms·
I’ve never understood why anyone would choose to debug by printing and logging if they have a good debugger available to them. My day job is mostly PHP (yeah y
by deergomoo 3y ago
I’ve never understood why anyone would choose to debug by printing and logging if they have a good debugger available to them.
My day job is mostly PHP (yeah yeah, I know) and the general attitude towards Xdebug in the community seems to lie somewhere between apathy and active avoidance.
To me, a debugger is such an invaluable tool not only for identification of bugs but also for familiarising oneself with new code. The value of being able to not only trace execution from start to finish but also to modify state in a running program is immense, and gives me a small taste of what Lisp folks rave about.
Littering print statements everywhere feels like banging rocks together when there’s a perfectly good lighter in your pocket.
- Topgamer7 3y agoHaving good log statements about what is being called with what value is invaluable when running a server and using log output to investigate issues.
- accoil 3y agoThey also let you troubleshoot a problem after it has happened. Logs can give information about the trigger, which the debugger can't do as it requires you to known what inputs caused the issue.
- deleted 3y ago[deleted]
- Hermitian909 3y agoOne of the great UX features of printing is that it is a quick way to have an auditable form of state over time. I look at states 1-n, compare and contrast, which my debuggers don't make as easy. I'd add many people don't work in languages with good debuggers. I work in TS and the debugging async node code is an absolutely garbage experience in many cases.
- smusamashah 3y agoCan you please explain how does debugger can help in cases where you can't wait too long on a breakpoint because some thread or service waiting on it will fail? I do this many times at work in Java with intellij. I do fine with breakpoints most of the times but sometimes print statements is the only way to trace the thing. From your comment I feel like I am missing better ways to debug.
- Gibbon1 3y agoThing that annoys me is I know that debuggers could do a quick grab and dash. Either stop the program snag the state of a variable and go. Or set a sample point where when it gets hit the debugger takes a sample of local state and continues. It aught to be able to do that within a few hundred clock cycles. Myself I use error/debug printf, a command line interface, debugger, and sometimes an oscilloscope. With error/debug printf I leave them in and just turn them on/off with a compiler switch. Over time they tend to evolve into something that provides good info on what's going on. The command line interface allows me to inspect the program state on the fly and run tests on the fly. The debugger allows me to do random look sees of what the program state is and follow the call tree. Oscilloscope allows me to inspect/debug/verify timing issues. My suggestion to you is implement a command line interface to you program so you can interact and inspect your program while it's running. It's really not hard at all. Implement commands as a table. { "command", handler, extra_data}
- smusamashah 3y agoI don't know how this can be used in a very old and large codebase where no single person knows everything. There is too much state and unknowns at any given time. IDE with breakpoints does help explore the state through stack.
- Groxx 3y agoUse a log breakpoint? No need to recompile then, just add the breakpoint and do the thing again.
- 3y ago
- bluefirebrand 3y agoMore and more software, especially on the web, is asynchronous microservices. Debuggers are basically useless for both of those imo. Debugger break points introduce synchronous behavior into your async application, which basically forces race conditions to fail when debugging. And I'll admit to not being a debugger expert but I don't know of any that can watch multiple executibles at once.
- sanderjd 3y agoIMO, this is one of the reasons that architectural style is not actually very good...
- randomdata 3y agoThere shouldn't be a need to connect to another service during debugging except maybe to validate that an external service stands by its published contract. A debugger (nor printf) does not seem like the right tool for that job, though.
- bluefirebrand 3y agoIf you're not sure which service is causing the error, combing a log output from the two services is much easier than debugging each service separately, is my point.
- randomdata 3y ago1. How does this really differ from debugging both services at the same time and attaching logpoints? 2. Microservices is a team separation technique, allowing different team to live in isolation, sharing only API documentation. It's the same as regular web services, except within a single organization instead of across organizations. If you happen to have access to the code (not a guarantee!), are you really going to be able to jump into a codebase you're not familiar with to start adding print lines with more expediency than other possible approaches?
- 3y ago
- whynotmaybe 3y agoIt's because both are great for specific tasks. If I want to check that the dependency injection engine creates & disposes correctly while navigating the app, I only need printing. If I want to intercept some process and check value on the fly, or even change it, debugger is the way to go. It's kinda ironic that you're discarding the matches because you have a good lighter.
- Supermancho 3y agoA jr programmer once asked how I know that N lines do what I expect without writing a test every 10 minutes. Logging is a form of unit testing. Logging can be thought of as unit tests for your specific context, decoupled from the logic (almost) entirely. I have an expectation of state, the execution can be checked against that expectation via observation of the output (which usually has serialized state). It's not a fancy True False or checkmark, but it's an assertion (which constitutes a test of an expected state) nonetheless.
- catiopatio 3y agoThere are two junior developers in your anecdote. That’s not a test. It’s not even comparable to unit tests, much less a replacement for them.
- Supermancho 3y agoIf you want to define tests as something other than observed state, go ahead. The ad hominem looks like you took it personally.
- ludston 3y agoA log statement isn't a unit test in the same way that apples aren't trees. A unit test is a discrete, runnable program that asserts some state about your program to be true, whereas a log is just some subsystem of your overall program that prints some output with no pass/fail condition. You may have a unit test that makes assertions about logs though? I would definitely expect somebody that isn't a junior programmer to understand this.
- Supermancho 3y ago> A log statement isn't a unit test in the same way that apples aren't trees I don't think your explanation is compelling. > a log is just some subsystem of your overall program that prints some output with no pass/fail condition. The pass fail is interpreted. A unit test result is interpreted, be it with a big green/red or an exception or any other way you wish to express it. Running something manually and checking the logs in an environment, when there is a reported issue, is modus operandi of every developer today. Did A happen and B happen and what did C say before exit? A looks good (because it has an expected state), etc. > I would definitely expect somebody that isn't a junior programmer to understand this. I didn't say logs were a replacement for unit tests (that's a previous poster's strawman). Regardless, they are a form of testing, because we use them to observe state after execution. Manual testing is testing, manual testing and observation of logs, is testing.
- etler 3y agoIt depends on what you're doing. I find console statements helpful when testing out a new function that you don't necessarily expect to misbehave so I check the internal state is correct without having to stop the code. Debuggers provide much more information, but stopping and stepping through the code is much more time intensive than printing out variables at various points and running the function and doing a quick double check that they're correct. It also allows you to check the state of the program earlier for problems that may only emerge after the fact. Instead of having to stop what I'm doing and retry and step through with the debugger, I can just look back at the log and see what went wrong where. I think both debug logs and debuggers have valuable use cases.
- tincholio 3y agoTracing debuggers give you the best of both worlds. I've recently started using Flow-storm [0], by @jpmonettas), and it's been quite transformative. You can still easily see the values flowing through your system (better than just "prints"), and it can handle multi-threaded / async scenarios quite nicely. You don't need to manually step through code, you can just "see" your data flow, and when you have loops or some other form of iteration, you can see the data for each pass. Coupling this with a good data visualization tool (such as Portal [1]) really feels like magic. I've been doing Clojure for quite a few years now, and was very happy with my plain REPL-driven workflow, but this is way better. [0] https://github.com/jpmonettas/flow-storm-debugger https://github.com/jpmonettas/flow-storm-debugger [1] https://github.com/djblue/portal https://github.com/djblue/portal
- etler 3y agoThat sounds like a really cool idea! Thanks for letting me know it exists
- jabradoodle 3y agoAwesome tools. Personally I can't imagine coding in clojure without scope capture https://github.com/vvvvalvalval/scope-capture https://github.com/vvvvalvalval/scope-capture
- bakugo 3y ago> My day job is mostly PHP (yeah yeah, I know) and the general attitude towards Xdebug in the community seems to lie somewhere between apathy and active avoidance. From my experience, simply having xdebug enabled comes with a significant performance hit, which is why I generally avoid it unless I really need it.
- deergomoo 3y agoI believe that’s mostly solved with Xdebug 3. The performance hit of having it enabled but not actively debugging was greatly reduced compared to 2.
- theshrike79 3y agoYou don't need to litter print statements, you can litter log statements :D I can't even remember when was the last time I was on a project where debugging would've been even a bit doable. Maybe, just maybe, during development when it's running on my computer. But it worked on my computer, that's why it ended up in production =) With proper logging (or just print statements) I can go in after the fact and narrow down what happened when it didn't work in a specific situation.
- pkolaczk 3y ago> I've never understood why anyone would choose to debug by printing and logging if they have a good debugger available to them. Because logging provides a different experience and can be sometimes much faster. I can run the code once and then analyze all the collected information later. The log allows me to go back and forth very fast, or very quickly see that e.g. a 150th iteration went sideways even if I don't exactly know what to expect. Another area where logging is tremendously helpful is debugging concurrency related bugs.
- josephg 3y agoYep. Most debuggers also make it very hard to go backwards in time. Logs can be read in any order. There’s a neat trick I like to do when I’m trying to triage a bug that only shows up with some input data. I’ll run the passing test and the failing test with detailed logging, then diff the logs to understand how the code is behaving differently in each case.
- knubie 3y agoPrint debugging can be much faster than using a debugger if you can figure out the problem and fix it on the first try. For more complex issues it makes sense to switch to a debugger.
- boxed 3y agoI don't understand how that is possible. I would say the exact reverse. With print debugging you have to write the prints. With a debugger you just run the code. Especially with conditional breakpoints...
- ben-schaaf 3y agoTakes me considerably less time to dump a bunch of prints than write (multiple) working conditional breakpoints. That said it's very problem dependent whether I use a debugger or logging (often a mix of both) and rr has considerably reduced some uses of logging for me.
- flohofwoe 3y agoYou really shouldn't have to "switch to a debugger" as if it were a separate tool, but instead have it integrated into your development environment (e.g. "run" or "step into" should both be just key presses, and every "run" automatically runs inside the debugger so that you can pause and inspect program state at any time).
- dpkirchner 3y agoSure, you shouldn't have to, but sometimes you're developing in an environment where adding a print statement + restarting + reproducing is faster than waiting for your IDE debugger to download whatever state information it needs (or whatever it's doing) l to render a prompt. For example, Xcode takes an eon to show a lldb prompt when you hit a breakpoint. Printing is instant every time. Further, there are cases where variables are optimized out of builds so you have to add code to ensure they stick around (in which case you may as well print). Again, this applies to iOS development. Maybe others.
- beagle3 3y agoFor many nontrivial debugging tasks. You need to record a lot of past context - e.g. you can put a breakpoint when a bad decision gets made, but the data causing this decision likely accumulated over a few tens/hundreds of previous iterations - and in particular one bad iteration that you don't (yet) know how to characterize. In such a case, setting up watches and pressing F5 a hundred times to get to bad iteration is inferior to adding a print/log and scrolling back to it.
- flohofwoe 3y agoIt's not one or the other, most debug sessions will also include some sort of adhoc logging. Also "modern" debuggers ("modern" as in "this century") offer a lot more than just simple on/off breakpoints: conditional breakpoints, data read/write breakpoints (e.g. who wrote this broken piece of data), "tracepoints" which don't stop execution but instead log out a message or run some scripted action, etc etc... A good debugger is essentially an interactive program state explorer and visualizer, ideally it would be fully integrated with the actual development process (e.g. edit, compile, run, break somewhere to inspect program state, tweak some code while program is suspended, rewind a program state a bit and continue running with the modified code, rinse, repeat...).
- archagon 3y agoThe problem is that the debugger conditional logic has to be written outside the local context of the code, and probably in a different language to boot. For example, in Xcode, you’re entering commands into a tiny box in the breakpoint popup that won’t actually tell you if you got the syntax wrong or not.
- anthonypasq 3y agoguess im lucky to be a java dev then lol
- beagle3 3y agoWhich python debugger with these qualities? Which Javascript debugger? Which Go debugger? Seriously asking; I am well versed in everything gdb, but I often revert to logging and "import pdb; pdb.breakpoint()" when I have to debug Python.
- sebstefan 3y ago>the general attitude towards Xdebug in the community seems to lie somewhere between apathy and active avoidance. Every year more good engineers start refusing to interview for most php gigs if it's not FAANG. You're with what's left of the rest
- jandrewrogers 3y agoI use both, they have different purposes. I find printf-style debugging to be much faster for bisecting the control flow, and the vast majority of bugs I see are of this type. Debuggers tend to be more useful in cases of corrupted state that isn't the result of broken control flow logic. These are much rarer, usually the product of something like broken bit-twiddling logic. And these days that kind of code is rarely written manually. When I write a non-trivial data container, I usually provide a standard public method that does a deep inspection of the integrity and consistency of the internal state. These are much too expensive to use as a typical assertion, but turning this on usually isolates the problem so well that a debugger isn't required to figure out what went wrong. I used to use debuggers a lot more than I do now because the nature of the typical bug has changed. The types of bugs are also much less diverse than they used to be.