Test-Oriented Programmers (TOPs) vs. DetestersPosted: July 10, 2011
As the cliché goes, there are few certainties in life. For programmers, bugs are one of the certainties. How we react to bugs matters.
There are plenty methodologies, processes and technologies that deal with bugs. These are all important and are widely written about.
I think that programmers also benefit from a better understanding of behavioral and emotional responses to bugs. These responses can lie close to the surface and affect the performance of individuals and teams. This post looks at both constructive and negative responses to bugs as a kind of “field guide” to identifying these behaviors in yourself and others.
Professional Tester’s Perspective
Professional testers have a great perspective on programmers and their ‘relationship’ with bugs so I sought out some experts for a chat. So, with particular thanks to Mags and Shez, here are some of their experiences. They each have worked with great programmers and bad. They each have had positive and negative interactions; good projects and bad.
Here are some of their negative experiences.
“The worst programmers to work with [as a tester] don’t care about the test team. They operated in a vacuum with no communication or interaction.”
“The worst developers are elitist and don’t respect testing. When presented with a defect their response is defensive. They blame the tester. They blame the customer. They don’t accept there might be a problem.”
Conversely, their best interactions were with programmers who respected the testers (and other non-programmers), who communicated openly, who were receptive to concerns about quality, who had a broader understanding of where their work fits into systems and who took responsibility for their work.
“Responsibility” and “accountability” came up often in discussions with testers. Working environments that encouraged individual responsibility and accountability were favored. Individuals that shirked their responsibility for software quality bring the team down.
The Defensive Response
Defensiveness is not a constructive response when you’re told of a potential bug in your work. Here are some responses I’ve heard many times when a programmer is informed of a bug.
- I tested my software. I’m confident there are no bugs.
- A bug? You must be using my software wrong.
- A bug? If you understood my code you’d know it’s supposed to work that way.
- That’s not a bug. The customer is an idiot.
- Why are you blaming me? I wasn’t given enough time to write it.
- Yeah. It’s a bug but it’s not important and I’m not going to fix it.
- You must have your configuration wrong or something. It can’t be my software.
- The problem must be in somebody else’s code. It can’t be my software.
To be clear, there are times when some of the responses to bugs listed above have been appropriate. It is, instead, a consistent pattern of defensiveness that suggests an unconstructive emotional response.
Emotional Reactions to Bugs
The Kübler-Ross model of grief — often referred to as the Five Stages of Grief — is a widely known model of people’s response to life changes from disease to disaster to death. If not taken too prescriptively you can see the responses play out in software teams when bugs are raised, when projects go off the rails, or even when companies fail.
If you’re not familiar with the Five Stages of Grief here they are exhibited by Homer Simpson.
or, if you prefer, explained by a giraffe.
Here are the five responses with “translation” to typical programmer-speak. [The Kubler-Ross model posits the five as stages but that’s not empirically supported. Nevertheless, the reactions remain useful in describing common reactions.]
|Denial||“The software is fine.”
“There is no bug.”
“My code is perfect.”
“That’s not possible.”
|Anger / Blaming||“It’s not fair.”
“I don’t deserve this.”
“The project/hardware/requirements are crap.”
“I wasn’t given enough time.”
|Bargaining||“Surely this is minor?”
“Can’t we just leave it as it is? Nobody will notice.”
“Can you just let me work first on this other project for a few more days?”
“Can’t somebody else do it?”
|Depression||“What’s the point in fixing it?”
“I don’t want to work on this project but I’m being forced to.”
“Oh sh*t. Not another bug to fix. When can I do some real programming?”
|Acceptance||“I suppose it won’t be too bad to fix this.”
“I will get it fixed soon [and test my fix].”
I have a clear memory of the first bug reported to me by a test team. It was the late 1980’s, early in my professional programming career, and I was working in a team developing laser printers (hardware and software). A colleague had developed new hardware with a fancy new chip for driving the printer and I was responsible for porting the existing software. A few days after submitting the first implementation to the QA team the QA lead turned up to my desk with a printed page that was perfectly rendered except for the bottom half which was printed completely in black.
My first reaction was denial. “That can’t happen,” I said. A half-blackened page demonstrated the stupidity of my denial. I moved on to acceptance and a fix. The problem was in software that I thought couldn’t go wrong so I hadn’t tested it. It was a good lesson; I test as I go; I hire great testers; I aim for a constructive relationship between testing teams and developers.
Test-Oriented Programmer vs. The Detester
The table below contrasts two types of programmer. The test-oriented programmer is both active in testing their own code and actively supporting and engaging with test teams. The Detester-type (or Detestee if you prefer) avoids testing their own work or engaging with anyone else that might test their code and potentially point out flaws.
To be clear, nobody I have ever worked with exhibits all the positive or negative characteristics in the table.
|TOP: Test-Oriented Programmer||Detester Programmer|
|Sees their role as writing code that works.||Sees their role as writing code.|
|Accepts that bugs are inevitable, even for the best programmers.||Assumes their code is perfect unless proven otherwise.|
|Responds constructively to bug reports. Doesn’t take them personally.||Emotional reactions to bugs include denial, anger, bargaining etc.|
|Knowing that bugs are inevitable, writes code that deals well with failure and tests it well.||Since my code is perfect I don’t need much error handling.|
|Understands how their software fits into the system.||Thinks narrowly about their software.|
|Thinks their code must be useful to its users.||Thinks users can be idiots.|
|Anticipates failure.||Is surprised by failure.|
Checks and Balances
It has struck me that the smartest programmers I have worked with know that as they are writing code they are potentially creating bugs. Their response is to create their own checks and balances to catch problems. The techniques are well-documented and varied — unit testing, pair programming, code reviews and many more. By applying these techniques to already-good code they create even better results.
And I believe that (nearly all) Detesters can learn to apply these techniques. The challenge is not usually the technical side of the techniques but instead adopting a genuine belief that they can and should make the effort to do so. Being forced to apply good procedures doesn’t necessarily achieve the positive TOP attitude.
It helps to understand the potential for the cost of a bug to escalate. As dropping a rock into a pond creates a ripple that can spread wide, a bug can have a wide impact with ever-increasing cost.
I use the “Rule of 3” as a simple explanation. It is a rough generalization but proper studies indicate it is still a pretty good generalization. Since this blog is programmer-centric let’s say the baseline cost is a bug introduced by the programmer during coding.
If the developer detects and resolves that bug during their initial coding/testing phase then the impact is contained. (And, typically, nobody else needs to know about the bug.)
If the bug remains when it is released for testing then the cost to resolve is 3x higher. That’s because the testers must find and report the bug plus provide a reproducible case; then the developer must replicate and resolve; then the software needs to be rebuilt; then the failed test cases are re-run (and possibly many more tests); then the issue closed. That can be a lot of overhead that might have been saved by minutes of work during initial development.
If the bug is not found in testing and goes “into the wild” then the cost to resolve is 3x higher (that’s 9x in total). Customers are now affected by the issue. For major issues there can be serious commercial impacts. For less important issues the customer might not report it but can take an ongoing hit. The process of submitting and resolving bugs for released software can be far more intensive than the internal processes and the costs to the supplier and customer are higher.
Programmers should heed the adage that “a stitch in time saves nine”.
A Test-Oriented Programmer seeks to not just write code but write code that works. They accept that creating software almost always involves creating faults and so it follows that they adopt practices to remedy those bugs early.
Detester Programmers should learn to recognize behaviors like denial, anger, blaming, negotiation and “depression” and to move beyond them to open and constructive responses and accepting responsibility.
Bugs are a virtual certainty for programmers — it is rarely a profession that deals in perfection. If you take faults personally or expect perfection from yourself then programming can be a tough career. The paradox is that by lowering your expectation from perfection you can achieve better software.
Andrew Hunt – Psygrammer