Over the years, I have witnessed a number of attempts to develop a complete, constructive definition of good design. I have witnessed most of this in the Extreme Programming Yahoo! group, in threads that crop up every year or so. A pattern repeats itself: someone asks about how to tell how good a design is, a bunch of people offer suggestions, they start to argue the fine points, someone points out the impossibility of developing a complete definition of good design, someone else points out that a generative definition would suffice, someone else claims that a generate definition doesn’t do the job… I could almost write the entire thread myself by now. Some people lament the lack of a complete, constructive definition of good design. I don’t, and today I finally articulated why I don’t think we particular need to worry about this.

I don’t mean to disparage the search for a clear test of a design’s “goodness”, because I think great things could come from that search: automated design critics, better objective measures of design health, possibly even a model for estimating the cost of maintaining a given design. I would find these things personally useful and I believe the software community would benefit from them. Still, the fact that we don’t yet have these things doesn’t need to cause us such consternation, because we can still do so much without it.

In the past ten years I have learned some incredibly useful things about design:

  • When programmers write design tests, they tend to find more of their own defects more quickly, which reduces the overall cost of realizing their design.
  • When programmers duplicate code, defect rates increase, and when they reduce duplication, defect rates decrease.
  • When programmers first start to change unfamiliar code, they tend to start by clarifying unclear names in the code: variable names, method names, class names. This practice helps them change code more safely and less expensively.

I have learned these things through my own practice, through pairing with others, and through observing other programmers at work. I find it more significant to note that even with only these three observations, we have improved the value of software design considerably. Even more significant than that, we can still improve the value of software design more by continuing to spread these observations to ever more programmers, projects and teams. We can still do so much more good with these observations than we have already done. We can wait for the next great breakthroughs.

Imagine the day arrives when every software designer in the world uses tests (or specs, if you prefer) to guide their design, focuses on reducing duplication and pays attention to naming their design elements appropriately. Either we’ll have seen the next great design breakthrough by then, or we’ll have seen so much good design that we’ll have extracted the essential patterns of good design that can lead to a meaningful, useful, deep, objective test for design goodness. Either way, I think we will win.

In the meantime, I leave the search for a definition of great design to the programmer-philosophers. I get by with the Miller Test: I know it when I see it.