Years ago now, William Rowden and I owned a business. In that business we wanted to build amazing software for our clients. We adopted several practices to help us do this.
One of the central practices we employed was Test Driven Development – a practice that essentially says you write software like this.
- Figure out what you want the code to do
- Write a test that says, “Does this happen?”
- Run the test and watch it fail (You haven’t written the code yet, so it had better fail).
- Write your code
- Run the test
- Watch the test pass
This is important to do because software development suffers from more product quality issues than brain surgeons in the 1500’s.
But, what happens to people when under the influence of a good idea?
They want to do it more. A lot more.
William and I wanted our coders to write good code that anyone in our company could later pick up and extend with very little hassle. We wanted to build quality in up front.
Therefore, we went looking for “best practices”.
Best practices are like common sense. Everyone says they are the same and everyone does them differently.
The best practices were searching for surrounded something called “code coverage.”
“Code coverage” is a procedural (legal) term that means “Percentage of features in the code with unit tests.”
There were all sorts of people fighting to get to 100% code coverage – meaning that every element of the code being written would have a unit test.
The more unit tests, the more code quality, right?
The more code quality, the happier William and I as business owners would be, right?
That’s exactly right completely wrong.
We have a problem with the concept of diminishing returns. There is absolutely a point where there are too many unit tests. When you have too many, the project bogs down. You are spending so much time fighting waste that you are creating waste.
The community saw this and debates erupted. … Well, maybe 70% of the code should have tests. No… 65% … No it’s got to be 80%.
They were desperately in search of a rule that would govern code coverage. The rule that would guarantee good product.
Meanwhile, at stately Gray Hill Solutions, William and I were noticing that if told developers that they needed to write tests for code they thought might give them problems – for some strange reason the problem went away.
As with my post on fear a few weeks ago, our professional judgment (while often flawed) is the fuzzy logic of business.
The Important Part
Here is the important part
The more specific a rule is (in this case code coverage) the more generalized a solution it is.
The more specific a rule: the more generalized the application.
When we said, “code coverage must be 80%,” that sounded extremely specific. But what we were actually saying was “all coders in all situations must have 80% code coverage,” which is painfully general. All tasks in general are now subject to this rule and all tasks, regardless of complexity, will suffer this scrutiny and burden.
When we said, “write unit tests when code is in potentially risky,” that sounds frighteningly general. But what we are actually saying is, “I pay you bozos $150,000 a year to write code. You use your professional judgment and when you have concerns, write unit tests,” much more specific. The worker doing the work can now deal with specific instances of work and apply the right amount of effort to that task.
The problem is that the specific is often much more ambiguous than we want it to be.
We believe that ambiguity diminishes and specificity increases.
That’s not how life works. When we encounter knowledge work, there are always a wide range of potential tasks, quality mitigations, and even products. We need process. We need rules. Without them we have no structure to build anything.
However, we need to recognize that there is a threshold where we encounter diminishing returns from our good ideas. Too much process is burdensome, costly (in money and quality), and a natural human tendency. Further, we must understand that the people we are trying to govern are not carrying out orders, but are actively processing information when they work. In order to process effectively, they need to have effective but minimal boundaries (so they stay within the goals of the company) but maximum possible flexibility (so they can act in the best interests of the company and respond to variation in their environment).