The Case Against "Try This" Debugging
- 4 minutes read - 735 wordsIn many group debugging sessions I’ve joined, a major technique being deployed is something I call “Try This” debugging. In this post, I’d like to talk about this anti-pattern, and consider a better way.
“Try This” Debugging Defined
What is “try this” debugging?
Imagine we’re debugging as a pair and we’re stuck. The easy answers aren’t working.
Suddenly, I produce an idea. It might be a:
- Stack Overflow answer
- GitHub Gist
- Popular comment on a GitHub issue
- Slack post from a colleague
I share this with you and say the magic words: “try this.”
Why should we try it? Because it might work. Just try it! What do we have to lose? We’ve all known this desperation. We’ve all “tried this.”
But what is this idea? It’s a Hail Mary pass. And I want us to throw it much later than many programmers do. I want to hear the words “try this” as a signal that we’re not debugging, but rather just throwing things at the wall.
What do I mean? What’s the cost of “trying this?”
The Cost of “Trying This”
“Trying this” is expensive: it’s slow, it robs us of learning, and it produces bugs and bad code.
First, “trying this” is slow. Instead of reasoning from first principles, we’re Googling, reading questions, bad answers, outdated answers, pasting code that ends up being just an example of the bug, etc. It’s like trying to find the name of a song when you also don’t know any of the lyrics. You might find the answer, but slowly.
Second, “trying this” invites hacky code because it blocks us from learning what fixed the bug. Unless you try to understand the solution you found, there’s magic in these solutions. We all know how stuck we were, and nobody’s going to question progress. But sometimes, we should, because we missed a learning opportunity. The next time we encounter that bug, we’re back at zero. Often the solution was a mix of things that didn’t matter and one thing that did, and accepting all the changes adds inscrutable, hacky code to the codebase.
Finally, “trying this” solutions are a gold mine for bugs. There’s a high correlation between the code that broke everything, uncovered via painstaking means, and a commit message like “:P Trying something else!!!”
In pair programming, “try this” often derails good lines of questioning. When shared in the middle of an active debugging session, it has the potential to distract from an insight or even a solution right around the corner. I appreciate that you want to help, but disrupting the flow of a team that’s an hour into a tough problem is not helping.
The Solution: Make a Prediction
The solution I’ve found is to shift to proactive by making a prediction. My previous post covers this technique. To add an additional example, imagine a test is failing and we’re stuck trying to understand why. What should we do?
Make a prediction! “The test is failing” is not a prediction. Maybe we read the error message and notice that our test runner can’t find some copy on the page.
expect(getByText("Welcome, Eleanor!")).toBeInTheDocument();
// ❌ FAIL: Unable to find an element with the text:
// Welcome, Eleanor!
Eleanor is unwelcomed! What are some predictions we could make? Here are a few:
“I think I’m importing the wrong test helper.” This is testable! We can consult other similar tests that are passing.
“It’s a race condition.” Testable! We can make the test wait, or assert about something else we know should be on the page simultaneous to our message.
“I have a typo on my assertion.” Very testable! We can change our assertion to something we know will fail, like “Welcome, Impossible!”, or print out the entire page in HTML or screenshot form.
“There’s a bug in the test library.” Not quite as testable, but okay! We can verify this with Googling or source diving.
All of these are step toward knowing something. They are much more useful than the pure fact that the test is failing.
Conclusion
Sometimes, you gotta try things. We’ve all been there. Resilience is important. Solutions matter.
But throwing things at a wall isn’t engineering. It’s slow, it robs us of learning, and it produces bugs and bad code. I want “try this” to be the very last thing we try. We’ve lost the plot. Let’s take a break or go home.