I searched the Wiki for a basic principles of "good design" and didn't find it. (There's GreatDesign
but I'm just looking for "good," or even "good enough.") With a level of hubris that risks unleashing the wrath of the gods, I now present mine. There's one saving grace: nothing here is terribly original, nor should it be. --JimShore
(signing my name up here rather than down below so people will modify what's below)
Before we define the characteristics of good design, we have to be clear on what a good design is. This question alone could tie up a committee for years, so no attempt to come up with an answer that pleases everyone; just an answer.
- The better the design, the cheaper it is to maintain (and add features to) the software. Good design is design that's easy to maintain.
This implies a few things. The following is unapologetic in its belief that TheSourceCodeIsTheDesign
... or, at least, the design is in the source code. There's also an implied belief that context matters; a design that's good for one team isn't necessarily good for another.
Here are the thoroughly-disclaimered implications.
- The software is correct.
- The correctness of the software is readily apparent from the source code.
- Few source code changes are required in order to introduce feature changes.
- When feature changes are needed, the specific code to change can be found readily.
- Changes don't introduce obscure defects.
- New team members can learn to maintain the software easily.
The characteristics above are ideals. Real-world designs aren't likely to achieve them. But better designs come closer. Good designs come close enough that the software is easy to maintain. To determine the quality of the design, observe it being maintained. Experienced designers will have opinions on the quality of the design but it's all speculation until the rubber meets the road.
There are some common approaches for achieving a good design:
And that's all there is on this page.
We Are All Students of Change
The biggest problem agreeing on GoodDesign
is estimating future change patterns. Almost every design makes assumptions and tradeoffs with regard to handling future changes with the least amount of pain. Time is often the only way to test if a design weathers changes better. Prior experience can give us some some guidelines, but I find that different people have been burned in different proportions in different things. So, they tend to focus on some change patterns more in some areas and less in other areas than I would, based on my experience. Person X may have been chewed out for a problem handling change type A in the past, but person Y chewed out about change type B. These experiences shape our probability and cost estimates for various changes. Not that this is "bad", for there is no alternative because we each only live one lifetime. -- top
I think the above list of one misses the most important aspect
- The software has to work. It has to solve the problem it was designed to solve or accomplish the task it was designed to accomplish.
If the software doesn't work, it doesn't matter how maintainable it is, nor how elegant its design, nor how spectacular its performance. Conversely, the real world is chock-full of terrible, ugly, "expensive" and completely revolting programs that, nevertheless, solve the problem they set out to solve better than anything before or after.
Could we move this point up to sibling status with the existing bullet?
I completely agree about the software needing to work and I've added a bullet about correctness. More than that is a bigger question than design, I think. See LevelsOfSoftwareSuccess. --JimShore