A couple of years ago I worked with a team that had exactly the problem Michael describes. Many of the classes were nearly impossible to instantiate in a test harness, and many of their methods couldn’t be tested without dire consequences for the development environment. Refactoring in the subsystems that contained these classes was also impossible, because of the unpredictable side-effects incurred by doing almost any method call. In the end, after months of frustration, we decided to very carefully and incrementally throw away those classes and replace them with something testable. In fact, that large-scale refactoring was never finished (due to circumstances outside the team’s control), but the improving code definitely “felt” better.
I believe Michael has hit on the perfect first-pass measure for code quality: how long does it take to write a unit test for a randomly chosen method of a randomly chosen class? Until the answer is under 5 minutes throughout a codebase, the design isn’t testable.
And once that measure is achieved, something remarkable happens: the team is no longer afraid to work with that code. The code itself no longer inhibits its own use in the development of new stories. It’s as if the code is somehow a better place to work. So here’s an intriguing analogy with the lean manufacturing world: If the code is the gemba (the workplace in lean thinking), making it testable promotes the flow of customer value through it. Kaizen!