What does a light bulb teach us about Test Driven Development?
January 25, 2008
Electrical Engineering is a hobby of mine. Electronic components fascinate me, and I usually have a little EE side project going on just to satisfy my solder-lust.
Lately, I've been watching some of the MIT open courseware and one particular class has been getting most of my attention, EE 6.002: Circuits and Electronics.
One of the topics covered in this class is a EE principle known as the Lumped Circuit Abstraction. What the LCA does is assume that the current into a component, less the current out, is equal to zero. This makes modern electronics possible, because without it, you're left only with Maxwell's Equations to describe the flow of electricity. Trying to compute the flux over something as simple as a light bulb would be extraordinarily complex, even for the most accomplished engineer. The LCA simplifies Maxwell's equations down to a small set of laws, that anyone with a high school math education can apply.
Of course, the LCA does have a drawback. It assumes certain things that may or may not be true for a given object. In order to gain this simplicity, electrical engineers have to restrict their work to discreet components that fit neatly within the constraints of the LCA. Resistors, capacitors, transistors, diodes...all these components can be treated as a black box, and used to build systems that do interesting things.
Could EE's use components that don't fit in the LCA? Sure. And I would bet that in some very rare cases, they do. But these engineers have recognized that keeping system designs simple almost universally outweighs the benefits of making them more efficient, compact, cheaper to build, or whatever else a non-discreet component would buy them...because the cost of trying to design a system using only Maxwell's equations is enormous.
So what does this have to do with Test Driven Development? Often, you'll hear the objection that TDD is too hard because not all software is easy to automatically test. That's true. But at the same time, we have to make sure our software works before we ship it out the door. While an untestable component may be cheap to write, the net cost of creating and maintaining it is much higher.
So what do we do? The LCA makes it pretty clear. Don't build components that cannot be automatically tested. At first, this can seem pretty restrictive. However, experienced Test Driven developers will tell you that sticking to this rule actually helps improve their designs, because they're more naturally decoupled and cohesive.
So I think if you're objecting to Test Driven Development because you can't find a way to test the software you're writing, you've got it all backwards. I would propose that you're building the wrong components to solve the problem, and that you should consider using something that's testable. At a minimum, you'll eliminate the test/fix/test cycle that's likely occurring at the end of all your release cycles. You may actually wind up with a better design.