The reason for dividing bugfix work into steps
I don’t like to waste time when I’m working. And there’s hardly a surer way to waste time than to be sitting in front of the computer not even knowing what piece of work I’m trying to accomplish.
I also don’t like to think any harder than I need to. Brainpower is a limited resource. I only get so much in one day. If I spend a lot of brainpower on a job that could have been done just as well with less brainpower, then I’ve wasted brainpower and I will have cheated myself.
Dividing a bugfix job into three distinct steps helps me not to violate either of these principles. When I’m working on reproducing the bug, I can focus on reproduction, to the exclusion of all else. This helps me stay focused, which helps me work quickly. Focusing on one step also helps cut down on mental juggling. If I decide that I’m only thinking about reproducing the bug right now and not trying to think about diagnosing the bug or fixing it, then that limits the amount of stuff I have to think about, which makes me a clearer, more efficient and faster thinker.
Here are the three steps I carry out when fixing a bug as well as some tips of carrying them out effectively and efficiently.
When I become aware of the purported existence of a new bug, the first step I usually take is to try to reproduce the bug.
A key word here is “purported”. When a bug is brought to my attention, I don’t immediately form the belief that a bug exists. I can’t yet know for sure that a bug exists. All I can know for sure at that point is that someone told me that a bug exists. More than zero percent of the time, the problem is something other than a bug. Perhaps the problem was, for example, that the behavior of the system was inconsistent with the user’s expectations, but it was the user’s expectations that were wrong, not the behavior of the system.
Once I’m able to reproduce the bug manually, I often like to capture the bug reproduction in an automated test. The reason I like to do this is because it cuts down on mental juggling. Once the reproduction is captured in a test, I can safely unload the reproduction steps from my mind, freeing up mental RAM. I can now put all of my mental RAM toward the next debugging step, diagnosis.
Many developers take a haphazard approach to debugging. They sit and stare at the code and try to reason through what might be going wrong. This works sometimes, but most of the time it’s a very painful and inefficient way to go about diagnosis.
A better approach is to try to find where the root cause of the bug is rather than determine what the root cause of the bug is. I write about this approach in detail in a separate post called The “20 Questions” method of debugging.
Sometimes a bugfix is an easy one-liner. Other times, the bug was merely a symptom of a deep and broad problem, and the fix is a serious project.
Whatever the size of the fix, there’s one thing that I always make sure of: I make sure that I’ve devised a test (manual or automated) that will fail when the bug is present and pass when the bug is absent. Otherwise I may fool myself into believing that I’ve fixed the bug when really my “fix” has had no effect.
- You can work more efficiently when you know exactly what you’re working on.
- Brainpower is a limited resource. Save brainpower for tasks that require high brainpower. Don’t waste brainpower on tasks that can be low-brainpower tasks.
- Dividing a bugfix job into distinct steps can help you focus as well as save brainpower.
- The three steps in fixing a bug are reproduction, diagnosis and fix.
- Don’t take bug reports at face value.
- Don’t try to find what the cause of the bug is, but rather try to find where the cause of the bug is. Once you accomplish that, the “what” will likely be obvious.
- Before applying a bugfix, make sure you’ve devised a test (manual or automated) that will fail when the bug is present and pass when the bug is absent.