DEV Community

John Au-Yeung
John Au-Yeung

Posted on

Strategies for Debugging Code

Subscribe to my email list now at http://jauyeung.net/subscribe/

Follow me on Twitter at https://twitter.com/AuMayeung

Many more articles at https://medium.com/@hohanga

Even more articles at http://thewebdev.info/

Debugging code is often a hard and grueling process. However, it all comes down to problem-solving.

In this article, we’ll look at the ways that we can make debugging easier.

Calm Down

When we encounter a bug, the first thing we should do is to calm down.

We might already be tired and frustrated, but we got to calm down when we’re debugging so that we can look for culprit faster and easier.

Also, we should keep an open mind when debugging. Myopia isn’t going to do us any good.

We should find the root cause instead of fixing the symptom of the bug. The real culprit might be several steps away from what we’re observing.

However, what we see might not always be the root cause. Therefore, we should find the root cause to fix the bug we encounter once and for all.

Where to Start

We got to make sure that our code is built and run without errors first.

Then we need to gather all relevant data. We should note that we may be misled by coincidences.

And we can’t afford to waste time on coincidences. We got to be accurate with our observations.

The accuracy may also be diminished if the bug report comes from a 3rd party.

They may not know what’s really going on and we need to watch the user who reported the bug to something actually reproduce the bug so that we can reproduce it ourselves.

Artificial tests may not exercise the app enough to cause our issue. We may need to test edge cases and other realistic usage patterns that users may do.

Debugging Strategies

The best way to start fixing a bug is to start by reproducing it ourselves.

If we can’t reproduce it, then we won’t know that it’s fixed.

The way thing to do is to be able to reproduce something with a single command. It’s a lot harder to fix if we have to reproduce it by going through many steps to isolate the scenario that may cause the error.

Visualizing Data

We got to visualize the data that are set when we trying to reproduce the bug.

This is where a debugger comes in. It lets us watch the values of each variable and looking at them to see if there’re anything that may cause the bug by setting the wrong values to variables.

Tracing

Debuggers focus on the state of the program now. So to visualize the whole workflow, we got to trace the flow of the code.

This is where a stack trace of the code will help a lot since it lists all the code that’s run before the given result is obtained.

We can add tracing statements to our code to trace how to code is called. To do that, we can write our own logging statement to print text to the console so that we can see what’s been called.

It’s also useful to print out the values so we can see them all in the console.

This lets us drill down to the code by going down the call tree to the root cause of our bug.

Rubber Ducking

When we explain the workflow to run a piece of code, then we might catch some anomalies by explaining it to another person that watches.

He or she that we’re explaining to may also tell us something that we didn’t catch that may help find the culprit of the bug.

Process of Elimination

In most apps, there’re many parts that make up the whole app. It may consist of code that we wrote, someone else wrote, and 3rd party libraries, frameworks, and other products.

Therefore, the bug can exist in any of those places. However, it’s more likely that the code exists in the part that we or someone else on the team developed.

We shouldn’t assume anything is given until they’ve disproved by our debugging efforts.

For instance, we can’t assume that it wasn’t a simple typo that caused the bug until we actually eliminated that possibility.

Also, we may be calling something that’s part of a library incorrectly. Therefore, we should check their documentation to make sure that we called it correctly.

That’s very important since it’s definitely a possibility that we can only eliminate it by disproving it directly.

Therefore, we shouldn’t assume anything until we actually found the culprit and fixed it.

After we fixed, we should check that it’s not a fluke or coincidence by testing it a few more times to make sure that the bug is actually gone.

Conclusion

We shouldn’t assume anything when it comes to crushing bugs. Make sure that we looked at all the possibilities and eliminate them one by one before making any conclusions.

Also, we should calm down and think rationally when debugging. This way, we can actually think.

Latest comments (0)