Continuing from our last post walking through the component parts of a software bug, now I’ll go beyond the defect and explain how we get to the resolution of the bug, Since we spend so much time preventing, identifying, and correcting bugs, it’s valuable to know and understand this process in order to talk more precisely and reason more effectively when it comes to planning and executing our bug reduction activities.
Let’s continue from where we left off…
Trigger – Many times defects will exist in the code and simply not cause any effects that are noticeable to the user. The defect may be on a bit of code that is only executed in unusual circumstances (or not executed at all — dead code), such as a confluence of multiple input values or settings. The trigger is the set of all the conditions that are necessary for the defect and the effect chain to cause the symptom.
Workaround – Sometimes during the bug analysis process, one or more techniques will be discovered that can prevent the symptom from occurring, but without actually addressing the defect. The classic example being restarting or resetting a program before some kind of a resource leak reaches the point where it causes termination, or following a certain constrained series of steps that avoids setting up the trigger conditions. Workarounds may be very helpful in the short term but should never be confused with resolutions.
Resolution – Once the defect is identified, one or more resolutions may be proposed. This could be a one-line change or a re-factoring of the entire program.
Verification – These are the steps that can be used to verify that the bug has been resolved. These can be used in turn to inform the creation of a regression test to quickly detect this defect or a similar defect if it is re-introduced at some later date.
Root Cause – Goes back earlier than the defect. What is it about the design, communication, documentation, or software development process that allowed the defect to be introduced in the first place?
Conclusion and observations
As developers we frequently talk about bugs because, lets face it, writing software is hard and we don’t always get it 100% right the first time. But we often do so in a way that minimizes or directs attention away from the hard and important work of discovering, properly specifying, analyzing, resolving and testing bugs. If we can agree that the components and artifacts that I have outlined above are all important and relevant to most or all bugs then we can start asking ourselves how we can work better as software organizations to tackle bugs. For example I’ve highlighted the difference between a sighting, a symptom, a reproducer, and a description. Often these get conflated. When we fail to recognize that each of these is important we get situations where we may miss bugs. If we insist on a reproducer before we even start talking about a bug we may miss sightings that are “sporadic” or that occur to a user who is unlikely or ill equipped to create a careful write up of a reproducer. That means we can see (sight) bugs but fail to record and fail to resolve those bugs.
By recognizing the difference between these different parts of a bug we can start to ask ourselves “what can we do to make sure that we capture all the sightings?” This might mean creating descriptions that don’t quite rise to the standard of reproducers and having a process in place to monitor these and create more detailed descriptions (including full reproducers) for some or all of the bugs that are sighted.
Similarly it is important to distinguish between the failure and the defect and recognize the value of workarounds but also the distinction between a workaround and a resolution. As software programmers and engineers we have a responsibility to identify and resolve bugs in the software we create. This is a non-trivial task and one that is worth approaching methodically.
What do you think about this taxonomy? Do the bugs you deal with resemble what I am describing? Do these features help you see any ways your tech support, quality assurance, and software development processes could be improved?
For more information on the tools and techniques that simplify and assist with the debugging process, visit www.roguewave.com.
• Watch this video to learn about debugging numerical simulations on accelerated architectures.
• Read this datasheet to learn more about TotalView, a scalable and intuitive debugger for parallel applications written in C, C++, and Fortran.