Debugging Guide

Debug a program with the following steps:

  • Review the bug report#
  • Characterise (determine the context where the symptoms showed) and reproduce the bug with the given input
  • Create the same bug with new input
  • Understand#, locate# and classify# the bug iteratively
  • Attempt to repair the bug
  • Deliver the fixed version of software

Note: Write a new test to reproducible bug.

Note: An unexpected behaviour might not be a defect. It is possible when a case, not thought before the formulation of the requirements, is not being handled by the program.

Note: A repaired bug must pass all the tests including the new and old one.

Note: Good version control could help.

Note: Always double-check the test assets! For the new and old tests.

Note: Always assume that the bug is coming from the application itself. If after elimination that the bug is certainly not coming from the application itself, then we can say that could result from external factors such as #operating-system, compiler or third-party component like library.

Difficulties

There might be some difficulties during the debugging which make oversight possible or bug hard to solve.

Symptoms and defects can be correlated which resulted the symptoms could change upon repaired or as the repair progressed. This could mean that the actual fault might be several steps away from what have observed. Fixing one defect could result in introducing more defects which is not ideal. [Hunt et al.](lit/@Hunt1999) suggest trying to find the root of cause of a bug.

If the symptom(s) is difficult to reproduce, it suggests a possible non-deterministic defect, a defect that given the same input could yield different results, that need more attention during the debugging process.

Documentation

Document down a defect by following the guide below:

  • How does the defect been noticed?
  • What is the context where the defect happened?
  • The step to reproduce such defect.
  • The techniques and tools involved to fix such defect.
  • What is the category of the defect?
  • What is the root cause of the defect?
  • What latent defects have been avoided after this fix?
  • Is there possible latent defects left unaddressed?
  • What is the mistake that cause such defect and how to avoid it?

Reference

Back to Basic: Debugging Techniques, YouTube, Bob Steagall

Links to this page
  • Version Control Hygiene

    Practising good version control hygiene could improve the process of debugging and backtracing. Practise it alongside with git blame.

  • Understand a Bug

    Understand a bug is essential in #debugging process in order to fix the defects implied in the problem report. The following is the recommended steps in helping to shape your understanding in the bug:

  • SOLID

    In debugging sense, the job become simpler. Base on the fact that the component is rather isolated from the rest of the codebase, the symptoms are likely to be contained in one area. These components have a high chance to be well-tested since the tests themselves are not sophisticated. Besides the simplification of debugging process, this will reduce the reliance on particular vendor, product, or platform since the interface of them are insulated from the rest of the codebase.

  • Rubber Ducking

    Let’s say you are debugging# a program and found a bug or a problem. Some might just keep their mouth shut and suffer in their own terms. Instead, Hunt et al. suggests for a companion! You can talk about the detail of the bug or problem to a literal rubber duck (if you don’t have a friend, which is relatable), a colleague, boss, or anyone who is willing to listen to you. Their role is to nod, quack, or simply making an agreeing sound, it doesn’t matter. By this way, you could organise and evaluate your thoughts more thoroughly and makes finding the solution easier. So grab a rubber duck, and take it to your workplace!

  • Refactoring: Improving The Design of Existing Code

    Tests are essential for refactoring, and it doesn’t just benefit on refactoring itself but the overall productivity as it reduces the time for debugging. Debugging# is the most time-consuming practice in software development. Fixing a bug can be quite quick, but finding it is another story. Having tests is to minimise the chance to miss a bug or the scope where bug could be located.

  • Refactoring

    Refactoring speeds up the software development by making the process of understanding a codebase easier. The code should be readable so the next guy who picks up the codebase will not waste much time on comprehending the code before becoming productive. This is with extra benefit where we can spot bugs more easily as we tend to spend more time in debugging#. Make the code speaks its purpose with more clarity. But it might drag the performance due to indirection.

  • “It Can’t Happen”

    If, for example, you have stumbling across the application codebase, run it, and found something that surprise you, reevaluate your assumptions, be willing to debug it#. Don’t just “know” your code works, prove it, in this context, with this data, with these boundary conditions. Add new test# to it, Crash Program Earlier# or put some Assertions#. You can go further by adopting Defensive Programming#, enforcing checks on precondition, postcondition and class invariant by Design by Contract (DBC)#.

#debugging #operating-system