Debug Mantra — How to debug effectively

Debugging is what a developer does from day to day. I can usually trace the bug and find the cause using logs or dev tools. However, I get paranoid with bugs that do not seem to make sense. e.g. the Enter keydown press changes the state in a component when there is no keydown handler attached to the component…

There are 2 key parts to effective debugging: 1. the clarity of mind 2. a systematic way to trace the root cause. Here, I am going to share the 3 mantras that I find useful in carrying out systematic debugging and explain why the clarity of mind is important.

Debug Mantra

This one was taught by Hack Reactor. It works in a similar way to rubber duck debugging technique where we are encouraged to explain the problem line by line, which helps us spotting areas where we overlooked.

In one daunting debugging journey where I was left puzzled as to

  • why a try…catch block does not catch an error
  • why an Enter keypress removes the states in my React Component when there is no keyDown event handler
  • why the action dispatched doesn’t reach the reducer when my Redux store states are not mutated in any way...

“It doesn’t make sense!” I was scared to see bugs like this as it was not obvious where to investigate to find out the root cause. Gradually, I developed the Debug Mantra to help me systematically debug when in panic mode.

My reasoning was: Because an error comes through to this line of code, it should be caught by the try…catch block. If it doesn’t, could that be there is an issue with the way I use try…catch block? After some stackoverflow searching, I found nothing…

At that point asking why try…catch block doesn’t catch my error is not very helpful. It is time to take a break (to keep a clear mind) and come back using the 2nd Mantra.

Write down the flow of the program and examine the validity of each statement. Following the previous example, I believed the error was produced within the try block, but what if it wasn’t? Assuming I was wrong, how could I trace the code to find out where the error occurs? This question opens a new direction for investigation! When something almost taken for granted stops working, forming a hypothesis first helps divide/conquer the bug.

“I think the error might be from this other area because…” Forming hypothesis helps us getting more insights into the program as we naturally would test our hypothesis to confirm the other cases where the program is expected to work/ fail based on our perception.

By putting break points and logging on other areas that i was able to investigate in other directions. I was like a detective who was finally able to leave the current dead-end valley and resume the journey to track down the culprit bug again new new clues in hand.

Debugging can sometimes be like a marathon and we need to make sure we are always in our best state, with a clear mind and good health to reach the end. When we get tired in the debugging marathon, it is important to take breaks to ensure the clarity of mind.

Why is the clarity of mind was important?

A bug that makes you panic is not an easy, usual one. It is often critical and obscure that put your working software at stake. That kind of tricky bugs usually require us to think outside of box in order to avoid rabbit holes and quickly trace the root cause.

In the famous Coursera course, Learning how to learn, Professor Barb Oakley introduced 2 modes of thinking: focused mode and diffused mode. In focused mode, a person would concentrate intently and tries solving problems that are related to something familiar by tracing familiar thought patterns in the brain. On the other hand, a person in the diffused mode is able to see from different perspective by linking different fields of thoughts together and create new ideas, approaches to solve a problem. In the face of a tricky bug that you have no prior experience to rely on to solve, do not panic. Also do not dive in and change code blindly, keep calm and help yourself to settle in diffused mode with a clear mind to come up with different hypothesis to the root cause.

To settle in diffused mode and keep a clear mind, it is important to remove any unrealistic time constraint in resolving this issue. Time constraint is one reason that people would dive in and change code blindly. If you discover this critical tricky bug at 4pm while the solution is expected to be released at 5pm, it is important to communicate clearly the impact of the issue to the stakeholders first. Discuss with them about the severity and likelihood of the issue, and let them know that you need time to properly investigate the root cause and implement a solution or mitigation. Manage expectation would help releasing yourself from immediate time pressure is another key part to settle in the diffused mode and investigate in the tricky bug from different perspectives.

In a psychological experiment, the candle problem, that Daniel Pink talked about also illustrates how the stress can shut down the creative thinking and problem solving part of the brain, which in turn makes debugging slower.

Anther way to reduce the stress is to share that stress with other people. (Sharing is caring!) Talking the problem through with colleagues and inviting their fresh perspectives would definitely help!

To enable effective debugging, remember to maintain clarity in mind and use debugging mantra to systematically trace the bug. To maintain clarity in mind, remember to reduce excessive stress by managing expectations and asking for help when needed!

A software engineer passionate about learning and growth