Motley: Judging a design to be "good" is very subjective.
Maven: "Good" designs satisfy fundamental design principles, like loose coupling, high cohesion, simplicity, and no undesirable redundancy.
[Context: Motley is wondering how to really judge a design is "good". This conversation picks up immediately from the last one]
Motley: … Like I said, a good design is all in the eye of the beholder. One developer may judge a design as good, and another may not. Probably depends on what they had for breakfast.
Maven: While there is some truth to that statement - good design is subjective - generally a good design is one that meets a few key characteristics:
- The design satisfies certain fundamental design principles
- The design is "done" (let's talk about what that means next time)
Motley: And what principles would those be? You mean common computer science ideas like coupling and cohesion?
Maven: You bet! Those would be two good design principles. Let's start with those. Coupling is the degree to which software components depend on other software components. You want components to be loosely coupled to make components easier to test, shorten the build process, foster reuse, and ease deployment among other things. Avoiding cycles is also super important.
Motley: Of course, you also want the relationship with your significant other to be tightly coupled.
Maven: Nice pun hotshot. Cohesion often goes with coupling - it measures the functional relatedness of a component or within a component. Highly cohesive components decrease the risk of change (components have one responsibility), eases testing, and promotes reuse.
Motley: Alternatively, a component should have only one reason to change. What else?
Maven: Keep it smart and simple. As we discussed with agile practices, keeping things simple is important. Simplicity helps keep quality up, eases maintenance, and leads to better reliability. This is arguably the most important principle in a good design.
Motley: Of course, it can be hard to judge simplicity.
Maven: Yes, but for example, highly parameterized over-engineered software is harder to understand than more static software. That's one gauge. You can also go back to basics and judge simplicity with simple rules like 7 +/- 2. If an interface contains more than 7 methods (approximately), it is going to be difficult for someone to keep them all straight. There is a reason why phone numbers (ignore the area code) are seven digits - that's about all the concepts we can keep straight in our short term memories at one time.
Motley: Although when I meet a girl, I write it down regardless because I don't want to forget it!
Maven: Yeah, I guess that is safe. Another principle we should talk about is the DRY principle.
Motley: "Disregard Recommendations from You?"
Maven: Ha, ha, Mr. Smartypants. It stands for "Don't Repeat Yourself." Avoid duplication by abstracting out things that are common and placing those things in a single location. Undesirable redundancy can be really evil - it makes change more difficult, there is duplicated effort, it leads to contradictions, and leads to increased complexity, which violates the simplicity principle.
Motley: I agree. I can't tell you how many times I've missed fixing a bug somewhere else in the code because it was copy/pasted from somewhere else. Ugh. We call that "clipboard inheritance" and I really, really dislike it.
Maven: Say, why don't we grab lunch and continue this conversation?
Motley: Sure. You buy.
Maven's Pointer: Coupling is the design principle that is frequently violated and leads to the most trouble. Tightly coupled systems are extremely difficult to maintain. There are a lack of "seams" between components that allow you to plug and play different implementations and isolate components from change. Tight coupling creates difficulties in testing and change in dependencies have effects on more components than they should.
- Agile Principles, Patterns, and Practices in C#, by Robert and Micah Martin, Prentice Hall PTR, ISBN: 0131857258, July 2006.