Ask HN: Why are we not using debuggers more?

13 points by pentab 2 years ago

I noticed that I rarely use debuggers. I asked around, and most of my co-workers are the same. We rely on debuggers only as a last resort, instead opting for prints, asserts, or the "method of the long stare". We are developing in Python/Java/C++ and use other convenience tools like IDEs.

Are you also avoiding debuggers? If so, why? What makes debugging so tedious?

PaulHoule 2 years ago

For me debuggers are the first resort. I learned a long time ago that if you get in the habit of hacking the code to debug it (say adding print statements) you will eventually check in debug-related changes that you shouldn't. Using the debugger means you don't have to hack the source code.

I use Jetbrains tools and have an easy time debugging in Java, Python and Javascript. In Java I'd say that you can use unit tests to interactively experiment the same way people do with the CLI in Python with the difference that you get unit tests out of the deal as opposed to having lines scroll away in the console.

I use WebStorm to debug Javascript programs that run in npm but if it is running in the browser I just use the "developer tools" from Firefox, Chrome, Edge or Safari. I think there is some way to attach WebStorm to a running web browser but I've never figured it completely out.

I think the Unix culture is allergic to debugging. It's not that hard to use gdb from the command line and in fact you can do some pretty awesome things with it such as embedded system debugging or debugging the C++ and Java sides of an application at the same time, but for a long time I kept trying graphical front ends for gdb such as ddd that "just don't work".

  • vr46 2 years ago

    I started out using debuggers because it made sense to step through the execution, then stopped for years as a junior- and mid-level because nobody else did, least of all the toxic lead engineers that were liberally sprinkled over every London agency I worked in, and then eventually turned 40, at which point I instantly stopped giving a shit about what anyone thought of me, and went back to being a totally-non-rock-stroke-ninja coder again. Debugging.

    It’s not just Unix culture that’s allergic to debugging, it’s every chancer and charlatan the world over.

alfonmga 2 years ago

I use a debugger every day. Delve[0] Go's debugger made me love the process of debugging my code – either attaching the debugger to an existing running process or the feedback loop of debugging the test code until make it passes the test case.

Back in the days when I didn't use one, it was a miserable developer experience. Thanks to Go and his great decision of having unit testing built into their standard now writing tests and debugging them is a joy.

Far are the days of not using a debugger because the programing language of choice didn't treat debuggers/unit testing as a first-class citizen. I could say that now I sleep a lot better thanks to coding my backends on Go and having the confidence that I can go as much depth as I want to fix any bug.

Debugging for me is an automatic action like drinking water when you're thirsty; two clicks (set breakpoint and click the debug button) and I'm back into the debugger, again.

[0]: https://github.com/go-delve/delve

sdevonoes 2 years ago

I use debuggers, but only if "prints" don't help me figure out the issue at hand first. Debugging via "prints" works out of the box.

You put a "print" statement dumping whatever data structure you want, you run the program again, and voila you got something. Now, the "where to put the print" is an art on itself of course. If you don't know where to put it, then either you start writing multiple "print"s here and there (following an approach similar to binary search) or you use a debugger and go step by step until you find right place to inspect.

The problem with debuggers is that they do not work out of the box. If you use the terminal, then you have use an external program and read its manual to understand how to debug, how to put breaks. Depending on the platform you are using, you may require even an executable to run the debugger on. Sometimes you don't have an executable. Sometimes you don't know where the "entry" point of your program is, but you know where the bug relies. Some debuggers require you to point the debugger to the entry point.

If you use an IDE like Jetbrains', then for debugging you need as well to do some (minimal) setup as well (the last week I had to debug a Node.js program: it was simple, but it didn't work out of the box. Also, when I open my IDE on a different Node.js repository, my debugging setup was gone).

themodelplumber 2 years ago

Some ideas:

First, if you can fix most issues with a glance or a brief stare, using a debugger never really feels necessary. It may also feel less like using your own brain and solving a puzzle, and puzzle-solving is a huge part of human psychology (see post title).

Also, the story of the last N years has been the text editor, not the IDE. The IDE and its world is really where the integrated debugging story is a big deal.

But if you are using a text editor--or text editors--integrating debugging is less of a thing. Your time may be better spent with various productivity-focused changes for ergonomics, like studying or changing keyboard shortcuts, installing or writing plugins, setting up your own scaffolding using system tools integration, and so on.

Plus once you know the various shortcuts, it's maybe more fun to use them and zip around adding prints than it is to debug. You also gain practice this way, after all.

But if you moved from text editors to IDEs, IMO you probably brought that same set of practices along.

Anyway, good q, I've thought about this recently as well.

AH4oFVbPT4f8 2 years ago

I use debuggers all the time. Don’t repeat yourself and keep it simple stupid goes a long way. I’d much have something readable and easy to follow than something clever.

mdcds 2 years ago

I program in Scala and didn't know what IntelliJ debugger could do until someone taught me how to use it (including the nifty trick of setting break points inside 3rd party libs).

Sometimes you don't know what you don't know.

But yeah, these days I rely on the debugger heavily. Even for Python :)

suprjami 2 years ago

I make an effort to use a debugger first.

Right now I'm writing some stuff which takes over the terminal and works in recursive loops (ncurses roguelike map generator) so print debugging is a hassle. It's actually quicker to use a debugger.

I find that attaching gdb and running "bt" and "info locals" or inspecting variables with "p" is much cleaner than printing, and helps me visualise what the code is doing much better.

This use of a debugger for "little things" is immensely helpful for when I need to use a debugger at work to solve "big things", which are usually remotely and after-the-fact with a core file, so printing isn't even an option there.

bobajeff 2 years ago

I'm getting more into using debuggers lately. They can really help they just take time to learn.

As to why they are a last resort. For me it was just having to learn the debugger and also setting up the debugging environment. For every binary needs to be built with debugging symbols and any libraries you're wanting to step through you have to find the symbols for those too.

Also I think it depends on how low level the language and what kind of program it is.

Some languages/environment don't have debuggers or they aren't very good. I wouldn't say most debuggers that are mature are super great to use either.

  • pentab 2 years ago

    Yes, it is sad that setting up debugging is so tedious.

    Could you give some examples or languages/environments with "bad" debuggers?

    • bobajeff 2 years ago

      Off the top of my head: Multi-threaded C++ is one. Odin lang has poor support for many debugger features.

      The Chromium Project can be way too slow to run in a debugger. Even just debugging the Content Shell can be very slow.

bluefirebrand 2 years ago

When build times are short, spinning up a debugger is overkill compared to adding a couple of debug statements.

The code I write is also a lot more asynchronous nowadays, and debuggers are fairly worthless for async code imo. Pausing on a breakpoint conceals issues with asynchronous timing that good logging will show immediately.

I still believe debuggers should be a part of every developers toolkit, but like anything else, pick the tool for the job and sometimes print statements are just the easiest and fastest. Actually in a lot of cases.

  • Delk 2 years ago

    > When build times are short, spinning up a debugger is overkill compared to adding a couple of debug statements.

    I often find it a lot faster to set up breakpoints and fire up the debugger than to write debug statements. At least in some IDEs, breakpoints are a single click each, and if you have to restart the application/module/whatever anyway, doing that in a debugger instead of a non-debug run is also just a click. I can then inspect any variable values at the breakpoint instead of having to explicitly include all potentially interesting ones in the debug output.

    When I'm trying to figure out a problem in code I'm writing rather than one in production, the debugger is often my first resort.

    I'm mostly writing plain old backend code without asynchronicity, though.

    Debug output (at a reasonable level) is still useful even outside of asynchronous program flow, of course, because it might give immediate clues for problems encountered in testing or production. If you don't have a good idea of where to look, debug output from several places might also be nicer than having the program stop at lots of breakpoints that turn out to not be useful.

    • bluefirebrand 2 years ago

      > If you don't have a good idea of where to look, debug output from several places might also be nicer than having the program stop at lots of breakpoints that turn out to not be useful.

      I have the exact opposite opinion. Firing up the debugger is what you do when you no longer know where to look, because you need it to examine the whole program state and have the ability to step through. Writing a console log with output from a variable is the precise "I already know what the problem is, all I'm doing is verifying it" approach.

      > if you have to restart the application/module/whatever anyway, doing that in a debugger instead of a non-debug run is also just a click

      A click that spawns a process that takes 10x longer to spin up. Debuggers are slow and heavy.

mindcrime 2 years ago

Not me. I love debuggers. One of my favorite features of Java has long been the JDWP support for remote debugging. Being able to fire up Eclipse (or whatever) and attach to a running process on another machine and step through the code... amazing. Not sure if other platforms have caught up in that regard or not, but to me for the longest time that single feature was one thing that made Java very cool in my book, compared to a lot of other environments.

DecoPerson 2 years ago

One doesn’t often reach for a tool that isn’t convenient to reach for, even though that tool may be the best available for the task at hand.

If you force yourself to use the debugger more, you will in the process both familiarise yourself with it and iron out any configuration kinks. Learn those keyboard shortcuts, figure out how to make it autoconnect and break on exceptions, find out how to evaluate expressions on the fly, …

You + That tool = maybe goodness. Maybe not.

m4xm4n 2 years ago

I like debuggers, but I don't always use debuggers. Typically because I can find the problem quicker w/ a puts/print/etc. than the time it takes me to run the debugger.

I also do a lot of web stuff, and if you're running some server process and you're not running the server process through a debugger directly, then you need to find and attach to the server PID, etc., then maybe deal with threads, and it's just a lot of upfront effort when I could just find the issue by throwing a puts/print somewhere or writing a test.

I'm not anti-debugger, I'm just busy and it's easier to put something in my code (which is how I frequently jump into debuggers too, e.g. binding.irb, binding.pry, debugger, byebug, etc.)

the CLI debuggers (gdb, lldb, etc.) are great when I really need them, but they're a pain in the ass to setup with things that are not C or C++, editor integrations sometimes need setup, and using them without setting breakpoints visually is tedious.

brailsafe 2 years ago

The people I've met who don't use debuggers either write very uninteresting code day to day or just get by enough with their old ways of print statements, enough to not feel compelled to learn to set a debugger up. But I think that's dumb, and it's almost always worth understanding how to set up, especially in a large codebase.

  • eurasiantiger 2 years ago

    And now you have to set up debugging for a Scala backend, a Node application running a GraphQL server, and a React Native frontend running in an iOS simulator.

    • brailsafe 2 years ago

      Anytime something new comes along there'll be a period of time where debugging tools aren't adequate or substantially more difficult to set up. But for a piece of tech to be a competitive choice, it's just just such a productivity waste to not make that a pretty high priority. JS frameworks themselves are classically terrible at this, even React itself is pretty meh, but usually you can fall back to just standard devtool breakpoints.

      I'd have a really hard time respecting someone's choice to bet on a tool that is very difficult to troubleshoot, if there's an alternative that isn't, unless that tool is extremely better at something else.

jamisonbryant 2 years ago

I am sadly not using a debugger because the last two or three times I've tried to set up XDebug for PHP, it just hasn't worked. I have 15 years experience with the language. Have tried multiple IDEs, multiple plugins, multiple browser extensions. Have tried multiple ways of running PHP (docker vs. native). I think the last time I might've had XDebug running properly such that I could do debugging in an IDE was probably 2018 or so. It wasn't too long ago that I found the `dd()` command, which is really quite handy and has gotten me by since then.

I'll give it another crack because I have just started a new job (new machine, new PHP, new everything) but I have my doubts it will work this time, either.

Setting up debugging for PHP has got to get a whole lot easier and user-friendly, IMO.

porcoda 2 years ago

My team regularly uses debuggers developing our C/C++ codebase. Often they are just one part of the workflow, combined with logging and visualization tools (to look at complex data structures as graphs). Debuggers often help track down where something bad happened to narrow down the search through logs and traces, and to figure out what part of a giant data structure to focus on. Most people I interact with work similarly : a combination of debugger, printing, logging/tracing, and viz. We tend to use debuggers less in other languages for various reasons (either poor debugging tools, or failure modes that are easier to understand via other methods).

bjourne 2 years ago

My preferred debug method is to have a program that I run to verify that it misbehaves. Then I remove some part of the source code, rerun it and verify that it still misbehaves. If it doesn't misbehave, I reinstate the removed code and I remove a part of the reinstated code that I suspect is misbehaving and then I rerun the program. This continues until I have found the offending line, at which point fixing the bug usually becomes trivial. Debuggers are nigh useless in this workflow.

I do use a lot of analysis tools like Valgrind which imho are way more useful than debuggers. Linters and static analysis tools can also be really useful for early bug detection.

ok_dad 2 years ago

I love using the debugger but now I want one where I can rewind the program a few steps if I want to. The use case I have is to go back and forth trying out different combinations of variables on a section of code. Even if I could manually set a flag to store the program state at certain portions so I can return there, that would work great.

Other than that, debuggers are very superior to print statements and such. You can’t pause a print statement and inspect the objects you didn’t print!

  • pentab 2 years ago

    There is actually a surprising amount of reverse debugging products out there, some are listed here: http://jakob.engbloms.se/archives/1564

    Would you be willing to use one of those?

    • ok_dad 2 years ago

      Hey, thanks for all the references!

      I looked through there; I code in Python for work (Lua at home a lot), so I didn't see anything that seemed to be targeted towards that use case. I've also seen tools like rr that record a session, but I specifically want to be able to step back and forth while executing code. I would use anything that, at minimum, would allow me to set a "save point" like a breakpoint and then return to that save point from any breakpoint, or from paused execution if I am stepping through the code.

      I think it would be easier for Python, Lua, or other dynamic, interpreted languages to do this because you could store the program state via storing the interpreter's internal state more easily.

      Also, I understand side-effects would complicate this and I am willing to ignore those issues if I had a bare-bones reversible debugger for Python.

rgavuliak 2 years ago

I am a Data Scientist turned manager so I don't consider myself a super senior dev focusing on other areas. Having said that debugger is amazing, especially for data intensive applications where it's the data that breaks the flow usually. I know there are cases where defaulting to prints is easier, but I use debugging whenever I can (if I still get to write/debug code)

Taikonerd 2 years ago

In my case, it's a technical limitation: the code that I write runs on a remote computer, not my laptop.

I know that "remote debugging" is a thing, but I would need to talk with our network guys about firewall exceptions to allow me to connect to the Kubernetes pod over port XYZ. That sounds like a hassle, and I'm not sure they'd allow it.

  • pentab 2 years ago

    Can you SSH into the remote machine? Visual Studio Code offers quite solid remote development tools through ssh (maybe other means too): https://code.visualstudio.com/docs/remote/remote-overview

    I would guess that it also supports debugging.

    • Taikonerd 2 years ago

      That's a really interesting idea! I'm going to try that out later.

      (Thanks also to matthias247, who also suggested this.)

  • Matthias247 2 years ago

    you could check if the debugger somehow can run over SSH. That would alleviate the need for opening more ports.

jollyllama 2 years ago

I got in the habit of using logs when it was faster than reproing bugs or more reliable (couldn't repro the bug). There's niche cases where the debugger is better, but logging has generally helped me more.

Ancalagon 2 years ago

I try not to debug code with print statements but the build time w/ vs. w/o the debugger is so much longer that it makes sense for small issues to debug with print statements on occasion.

altruios 2 years ago

Using a debugger for async codes introduces timing bugs.

  • Gibbon1 2 years ago

    exposes timing bugs.

anamax 2 years ago

I avoid debuggers because if I can't debug something without them, said something is too complicated for me to understand now, let alone in the future. Moreover, if said something is that complicated, it is almost certainly wrong in several subtle ways.

One nice property of asserts is that they keep working even when your attention is elsewhere.

  • roflyear 2 years ago

    How do you step through your code to understand what EXACTLY is happening to the data without a debugger?

    • anamax 2 years ago

      I haven't used a debugger in 20+ years.

      If I don't understand what is happening to data without stepping, the code is too complicated.

      If it's too complicated, I don't understand it now, won't understand it later, and it's probably wrong.

      If I was working (again) in embedded systems, I might use a debugger as a substitute for print.

salawat 2 years ago

Because developers are deathly allergic to understanding/reading other people's code, and/or do not write them for <insert language here>

t. Grumpy maintainer

  • pentab 2 years ago

    I don't think I understand. Are you saying that debuggers have no use on your own code, and people avoid looking at other people's code? Also, are you saying that there exists no debugger for <insert language here>?

vlod 2 years ago

John Carmack's view [0] on debuggers (from Lex Fridman Podcast podcast video)

TLDR: He doesn't understand why a lot of SV big-tech companies are hostile to debuggers.

[0] https://youtu.be/I845O57ZSy4?t=3410

blacksqr 2 years ago

Debuggers don't give you enough information when you want more, and too much information when you want less.

Learning and effectively using a debugger can require as much cognitive load as programming itself.

Given that, using a debugger takes you out of your programming mindset and into debugger mindset. Using prints, asserts, etc. keeps you in programming mindset, so you can find and fix the problem and get back to coding without the need for cognitive gearshifting.

  • pentab 2 years ago

    What kind of information would help you to debug? And what kind of information is "too much"?

    Personally, I think "too much" is when you get a large table of all variables and their values; it is quite hard to locate the one you care about...

    • suprjami 2 years ago

      Inspect all global variables in gdb. You get every variable defined in a linked library, pages and pages and pages of output with your own program's global's stuffed somewhere in the middle. Useless.