Debugging - Steps I Take in Locating and Resolving Bugs

25th May 2023

Matthew

Comprehension and replication

Once a bug has been brought to my attention, the first thing to do would be to ensure I have understood the bug and what the unexpected behaviour is and to gather information about the circumstances in which it occurs.

I can then attempt replication – the process of triggering the bug, typically within our development environment, so that I can study it further. This is an important step, as without replicating it, it can be many times more difficult to pinpoint the cause of the bug within the code, and I can neither prove that my attempted resolution fixed it.

This is because, ideally, I want to be able to investigate and follow an unexpected output through the code flow to pinpoint exactly where in this flow it is caused, but when this ceases to exist – there simply is no ‘lead’ to follow.

Investigation and the tools to assist

Once replication has been achieved, I can theorise about what may be the root cause. This can allow me to locate a part of the code that I suspect could be causing it or starting from the final output and working our way backwards. As mentioned before, I will gradually narrow it down from this starting point by eliminating parts of the code flow that are functioning as intended and, therefore, not causing the bug until I can successfully locate it.

But how can we observe the execution of the code and precisely what it is doing at runtime? Console logging is a developer’s best friend – or so the stereotype goes. Alternatively, we can also step through the code with breakpoints using tools that IDEs provide to us. Both enable us to view the output of our code statements and the data it produces.

From here, I can replicate the bug as often as I need to investigate with my console logs and breakpoints.

Another tip for quickly locating the problematic section of code – is consecutively commenting out parts of code to see if it halts the occurrence of the bug – which can be an effective strategy in specific scenarios – provided it doesn’t throw errors and deprive the project of the required functionality for testing that section of the code.

Testing my implemented fix

Once the problematic code has been located – I will work on implementing a fix and afterwards attempt replication of the bug again to check if my implemented fix has achieved the resolution status of the bug.

After I have confirmed that my implementation stopped the bug from being replicated, I need to ensure that this fix resolves the bug entirely through testing with different data and different setups (if applicable) and that it also doesn’t have any adverse effects on the rest of the codebase. From this point, it needs to be kept in mind any potential adverse effects the newly implemented fix could bring to the project. We can test these as thoroughly as appropriate to ensure we haven’t introduced further bugs.

Clearing up all occurrences of the bug and committing my work

At this stage, a tip I often use is to utilise the search function throughout the codebase to check for any other places where this bug may exist. Typically, if this bug was introduced in one place, there is a good chance that it could be present in more than one place over a large codebase that contains multiple similar variations of this same code. This can prove to be a practical step in scenarios where the bug was caused by misused or incorrect syntax.

Finally, once I have verified the bug has been successfully dealt with, I will clean up my code, removing any temporary testing changes and then committing the fix.

Related posts