I’ve been thinking a little bit lately about the notion of completeness in programming. I think it’s a valuable concept because those of us who write software have a hard time defining what the word “done” means with respect to our product. The old saw about model railroads is that they are never finished, and I think a lot of us feel the same way about the code we write.
A similarly ephemeral concept is that of correctness. When is a body of code “correct?” Can a given piece of software be “correct” without being “complete”? The problem with correctness is that software is too complex to support any but the narrowest definitions of the term. We could define correctness as the state of development at which a piece of code produces correct outputs for all possible inputs. But it’s difficult to assert that any non-trivial system meets even that fairly specific definition, and that definition leaves out a lot of possibilities for things to go wrong due to external factors.
In practical terms software is perceived to be complete when it does all the big things we asked for it to do. This idea is reinforced by methods of requirements definition such as Use Cases, which focus on large-grained behaviors of actors in the system. I think it’s safe to say that we can get all that stuff right, and yet not have “complete” code.
So what is complete code? I’ll take a stab at a definition: Code is complete when it produces the correct outputs for all possible inputs, and fails safely and gracefully in all possible situations where a correct output cannot be produced. In my experience it’s often that second part of the definition that gets short shrift in the development process. Time and again I run up against code that takes the straightest possible path between input and output, and ignores a slew of potential boundary conditions and failure points along the way.
Putting the blinders on and dashing straight for the finish line is usually defended as pragmatism and a “get ‘er done” attitude, and there are times when it is absolutely a virtue. If you ever do a technology start-up you’ll encounter many of those occasions, often strangely correspondent to meetings with potential investors. But for just about any system that has to actually run reliably and do important stuff in a production context completeness is a more important quality than brevity. Brevity will make you feel good now, but it will cost you in the long run.
Unfortunately completeness is hard to see, doesn’t provide any immediate benefit in the eyes of users, and is therefore something they hate to pay for. Buying an incomplete piece of software is like buying an old, worn out car with a new paint job and refurbished interior. It feels great, and it’s fun to show it to your friends, but step on the gas and the wheels fall off. I’ve seen the wheels fall of a few software systems when the throttle was opened. I guess it’s a lot easier to place a value on completeness when the lack of it means you have to walk.