I've been on just enough software projects in my career to form marginally supported hypotheses about the value of testing. Here they are.
Postulate One: Tests suffer from the same, or complimentary, defects as the code they test.
I'm speaking about unit tests here. Specifically, unit tests written by the authors of the code under test. The first part should be no surprise, since the same author will commit the same sins. Copy and paste, long methods, tight coupling, etc. By complimentary defects, I mean faults that appear in the tests to compensate for defects in the code. For example, tightly coupled code seems to induce copy-and-paste hackery in the tests, as the difficulty of testing in isolation leads to large, repeated, but ever-so-slightly different test structures. This leads me to...
Postulate Two: Stubborn determination to do the right thing badly is not a virtue.
Also known as the "stop digging" principle. Tests which are painful to write without copy-paste-hack development are trying to tell you something about your code. In one case I'm familiar with, testing a single object required instantiating 19 others and fabricating a small mountain of phony data. Please, think of the children, or at least the poor sap who has to maintain your code.
Postulate Three: Bad code needs more tests, and needs tests more, to attain the same level of confidence.
I've already argued tight coupling induces copy-paste-hack in the tests. Large methods and complex classes with too much functionality require larger, more complex, tests. Fewer parts of the code will be at the simple and obviously correct level.
So what? Here's what I think all of this means.
Conclusion One:Bad tests impede refactoring, making the code harder to improve.
Even good tests add to the code that must change when refactoring. Bad tests with duplicated code and strong dependencies on lots of objects are even worse. Since bad code can induce bad tests, this suggests that:
Conclusion Two:Testing makes bad code more correct, but less maintainable.
This stinks, but I think it's true. It shouldn't be necessary to sacrifice maintainability for correctness. In fact, the opposite should be true! Stubbornly bolting tests onto bad code, however, seems to have the opposite effect.
Let's add another uncontroversial postulate, just for fun:
Postulate Four: Code must change over time, and bad code is harder to change correctly.
And this leads us to the rather uncomfortable conclusion:
Conclusion Three: Determined testing can make bad code worse over time, or at least, less better than it could be.
Having tests in place is essential to safely refactor code. The conclusions above are my attempt to explain why the cost of improving bad code is so darn high.
Subscribe to:
Post Comments (Atom)

0 comments:
Post a Comment