The difficulty of a bug can be measured as the distance, in lines of code, from the cause of a bug to the visible symptom of a bug.
Good developers know this equation intuitively and find a way to whittle down the playpen of a bug. When coding, they create simple and easily understood interfaces between code so that the bugs are trapped in small playpens from the start. When debugging, they create experiments to trap the bug into smaller and smaller snippets of code. They get turned on by Object Oriented Programming, Service Oriented Architecture, Inversion of Control, Plug-Ins, and other things that create walls between code.
In the easiest case, the symptom and cause of the bug are on the same line of code. In the hard case, the location of the cause is unknowable, making the bug infinitely hard to solve. The hard case happens when the system is non-deterministic or random. This could be caused by problems internal to the system, such as a threading race condition or deadlock situation. It can also be caused by problems outside of the system, such as faulty hardware, or an unstable network, or by a bug in a third party component or the underlying framework or operating system.
An unknowable cause is very different from an unknown cause, and this is why a good QA team helps. A good QA team will help leverage a good developer by telling the developer exactly what inputs or actions cause the bug–quickly turning the cause from unknowable to unknown–and providing the developer with all of the information necessary to nail down the line of code causing the bug. A bad QA team will create bugs so vague that the cause is impossible to find, ie: “The application crashed.”
I’m still undecided as to whether the Klophaus Equation of Bug Difficulty should take into account the amount of code required to fix the bug. I don’t think it matters, and here is why. The difficult part of debugging is understanding what is going wrong and how it should be corrected. In most cases the fix, even for the hardest of bugs, only involves a few lines of code. This is because most bugs are typos–the developer meant one thing but typed another.
Bugs that require a large amount of code to fix are usually no longer bugs, they are tasks. They are the signs that the software’s design was incomplete, that scope changed, that the developer didn’t fully understand the functionality he was developing, that the developer cut corners, or that a code merge somewhere went horribly awry. In other words, they are an indication of a glitch in the software lifecycle, a bug in the process or the team.
And a bug in the process or the team is the same as any other bug… the difficulty of a bug can be measured as the distance from the cause of a bug to the visible symptom of a bug. But causes and symptoms are more difficult to pin down in processes or teams than in code.