There is a very convincing argument to be made that feature-complete software is ultimately more valuable than a readable codebase. That there is more value in what an application does than in how it is put together. Perhaps it is fair to consider architecture, including the comprehensibility of a program as source code, to be of some benefit but still orthogonal to a program’s business value? After all, it’s incontrovertibly true that the most important aspect of developing software is shipping it to the customer. So then isn’t it the case that the real value is all in what the software does?
Why is so much value placed on delivering readable code?
Greg Horvath recently showed me a paper on JPL coding standards (PDF) that encouraged eschewing some pretty basic strategies (recursion, dynamic memory allocation) on the grounds that they lead to code that is somewhat more difficult to run through static analysis. The takeaway for me was that NASA cares a lot about being able to tell what the code is intended to do, without actually running it.
So while shipping feature-complete software is obviously important, it seems that shipping readable software is really important, too. Why? I think it’s because comprehensibility of components contributes to the resiliency of a system overall. A prototype that works is good. A prototype that can evolve rapidly is even better.
Complexity is an inherent property of software. Comprehensibility is not.
It’s interesting to note that Dijkstra espoused a readable-code-over-feature-completeness approach to software architecture. He contrasted the two mindsets as “postulational” and “operational,” respectively. Postulational meaning one can postulate about what a program does just by reading the source. Operational meaning that one bases one’s expectations about what a program will do, on (educated) assumptions about what operations will be carried out when that program is executed.
Dijkstra also once pronounced that software is the most complex product ever produced by human effort. When delivering any non-trivial software application, some degree of complexity is intrinsic to the task. And obviously, concepts that are complex do not lend themselves to implementations that are easily readable. So maintaining comprehensibility in the components of a complex system, turns out to be a rather difficult problem.
Incidental complexity, once identified, can eventually be factored out, leading to code that is more readable overall. Therefore it is valuable to take the (sometimes considerable amount of) time to distinguish between intrinsic and incidental complexity, and to continually either avoid or remove the incidental complexities that over time can make a codebase harder and harder to read.
The most interesting part of delivering software is watching what users do with it.
In order to provide a satisfying user experience over the long term, any software needs to be able to adapt iteratively and rapidly to the unpredictable needs and desires of its user base. Resilient systems are best able to adapt, because successful adaptation requires constant readjustment in the face of new circumstances. So there is considerable value in preserving the readability of source code throughout the life of a system.