It turns out using the debugger is somewhat controversial, who would have thought it?! Let's explore why

Why is Using the Debugger so Controversial?


It turns out using the debugger is somewhat controversial, who would have thought it?!

Let’s explore why.

Over the past few months I have been working on The Ultimate Guide to Debugging in Go (which is now released!) When I came across this meme which made me laugh so I tweeted about it:

I was really surprised to see some really experienced engineers state that they never use the debugger, have not for years and don’t recommend it to others. Myself and all my colleagues use it regularly. I wanted to understand this a little more, so I made a poll:

787 people voted, and although the majority did use the debugger, a large proportion (37%) did not. A not insignificant portion said they didn’t know how to, but my course will help them ;)

The discussion on this tweet is where things got a little more interesting, with some indicating that if they need to reach for the debugger it’s a sign of a code smell:

Where as others shared my view:

My Case for using the Debugger

My case is a simple one and twofold; if you don’t know how to use the debugger, you should learn how. If you then decide you don’t want to use it as it doesn’t suit your workflow, then that’s a great outcome as you learned a new skill and opinion.

For those that already know how to use it, here is why I think you should use it more often.

Some Code is just complex

Even if you implement all the correct patterns, some code can just have a lot going on. After all, our code is meant to represent our business domain, and some domains are complicated! Being able to set conditional breakpoints as you “play” with a codebase is an incredibly powerful way to up-skill.

Evaluate more expressions than you can fit in your head

Follows on from the previous point, computers are really really good at keeping track of things, and we should let them do it for us. If you are interested in a value at a point in time, the debugger can help you here.

Tests are just code; you can make mistakes in tests too

A lot of arguments resolved around the fact that if you are using the debugger, you should just write a test. Tests are code too and can be complex to follow too. I particularly find this in Go where people write some pretty confusing tests with a goal of keeping them in the Table Driven model. Also, sometimes I just straight up make mistakes in my assertions, and using the debugger helps me figure this out.

Not all code bases are perfect

Follows on from the previous point; “just write a test” is not applicable to every code base I have ever worked on without a refactor. That should be the goal, but just understanding how everything works is always the starting point, and the debugger helps here.

(At least for Go) Starting the debugger is fast with little overheard

This isn’t true for all languages, but for Go, starting the debugger is very easy and fast. Most IDEs allow you to get setup with little to no overhead.

Slow things down

Slowing down the pace of code execution using a debugger is a powerful technique that grants you the opportunity to analyze the behavior of their applications in real-time. This deliberate slowdown is not about hindering progress but rather about ensuring a thorough understanding of the code’s flow and logic. By stepping through code line by line, you can observe the state of variables, the execution of conditional statements, and the interaction between different components at a granular level. This approach allows for the identification of subtle bugs and logic errors that might be overlooked during faster, more automated testing processes.

Slowing things down not only enhances the quality of the software but also enriches your comprehension.

Conditional Breakpoints

This functionality is incredibly useful for isolating and diagnosing issues that occur under specific circumstances without having to manually pause the program at every step or sift through irrelevant parts of the code.

This targeted approach makes debugging more efficient, especially in complex systems where issues may only show up under certain conditions or during interactions between various components.

The Debugger is great for local development; but it’s not a replacement for logs, metrics and traces

The debugger is as an invaluable tool for local development, providing developers with the means to interactively step through their code, inspect variables, and understand the flow of execution in real-time. However, it’s crucial to recognize that the debugger’s usefulness is primarily within the confines of local development. When it comes to monitoring and diagnosing issues in production environments, logs, metrics, and traces become invaluable.

Wrapping Up

After the discussion, I did re-consider some of the points raised, and wonder if I am just a worst/slower engineer than those who do not need to use it. However, I was reassured that having to use the debugger is not a metric for skill when I discovered this interview with Lex Friedman and John Carmack, who is considered to be one of the greatest programmers of all time, and he talks about how much he uses the debugger.

If its good enough for Jon Carmack, its good enough for me!