Chuck Connell is a software consultant and writer in Bedford, MA. He can be reached at BeautifulSoftware.com.
There is such a thing as good software versus bad software, and there are universal principles that define good software. This is easy to see with a simple thought experiment.
I hand you two disks containing two sets of source code, A and B. I tell you that both samples implement the same feature set, so the programs produced by A and B behave the same for all inputs. The operations performed by the programs are fairly complex, so these are large sets of source code, at least 100,000 lines each. I tell you that A is an example of high-quality software design and implementation, while B is an example of all that can be wrong with software development.
Before you look at the source code, I ask what qualities you expect to find in A versus B. You might answer "modularity" or "non-redundancy" or "no GOTOs". Every experienced programmer has his or her favorite list of software design DOs and DON'Ts. If you have been programming for more than a few months, however, you will not say, "I have no idea. Since I don't know what kind of software this is or what the source languages are, there are no general properties that lead to good software versus bad."
Experienced programmers recognize that good software looks different than bad software. Responsible programmers strive to incorporate the good qualities into their code. But our understanding of software design principles is often implicit. Good programmers seem to do it regularly; bad programmers always seem to miss the boat. We have little explicit knowledge about what the general principles are.
The answers are important. Good design, in any medium, leads to higher quality, so a clear understanding of general software design guidelines would reduce the cost of all software development. We need universal design principles, so what we learn will lead to improvements across all languages and problem domains. In cases where software performs safety-critical functions, the answers impacts human lives.
Despite the importance of software design, we hear little about it from software engineering researchers. We do hear a lot about software methodology -- how to organize teams, manipulate schedules, and do the associated paperwork. Recently, we also hear about the instantiation of design principles, i.e. patterns, both design patterns and the higher-level architectural patterns. But a pattern is not a principle. It is not explanatory. We want to know why a certain pattern is good and the general principles that make it effective. Examples of such principles might be information hiding, non-redundancy, and simplicity.
It is also important to clarify what universal software design principles are not.
- They are not tied to a particular language or style — such as Java, object oriented design, or functional programming. There were good and bad programs written in COBOL and Fortran, long before these newer techniques came about.
- They are not related to how we create software. A team can practice extreme programming, use-case design, open source, or even CMMI Level 5, and still produce lousy software. The qualities we are looking for exist in the structure of the software, regardless of how some humans got the software to that state.
We currently do not have such a general theory of software design. We tackle each project separately, with few guiding principles. We follow the latest trends in software construction, with no explanation for why this fad is better than last year's. The issue of design principles is so important that we should be having heated arguments about it, with strong proposals, harsh criticism, and competing counter-proposals.
I published my take on software design in 2001, and that article has had considerable readership since it appeared. The problem, however, is not that some software teams have failed to worship the brilliant ideas in my essay. The problem is that no one is shouting it down. If my proposal is wrong, as it may be, why is it wrong? What is the evidence for its wrongness? What would be some better ideas? What is the evidence supporting that new theory? As a community, the software engineering world is not actively searching for a universal theory of design. This is a collective failure, since progress in this direction would have dramatic impact on all software projects.