I had a short twit-chat yesterday with Chad Myers (By the way, Twitter really tried to wreck this interesting talk – both of us didn’t see replies correctly. Do you use unit tests, Twitter Team?). In one of his twits Chad said:
"There ARE objective qualities which evaluate to a good design. Its not black/white, but not too fuzzy either"
Lets look into this. What is a design? It’s a solution to a problem. Software is about solving problems. Why do we write software (and I’m speaking commercially, not for fun)? two reasons: Make money and save money. That’s it.
Software automation is the latest wave (we’ve gone through different types of automations in history). We can do a lot more if we have working software, we can sell better applications and services and we can save a lot of time and money if we used modern IDEs instead of punch-cards.
So, how do we create software? The design is the solution of how to write software that answers the two reasons. It helps us make money by designing our software to do what it’s supposed to do. It helps us save money if the maintenance costs of that software are low.
So far so good. If it makes/saves money it’s a good design. Now let’s look at current design methodology. I’m picking on OO (Object Oriented), because it’s popular and considered the best way to build applications today. Are the OO principles the basis for a good design? On the whole yes. By using OO the code becomes more maintainable, therefore saving money. Code is not monstrous, objects have their place and responsibility in the world, you can teach the application better to others. And it makes more sense.
But does it help the software do what it’s supposed to? Not necessarily. What if performance is an issue? We all know there are penalties with virtual calls. Ask people who wrote high performance software, and they’ll tell you: when it counts, performance rules over "good" design. DRY ("don’t repeat yourself") gets thrown out the window, because you start inlining code. Messy but works (mostly). In some cases, the first reason trumps the second.
We’re starting to drift from the "black/white" objective decisions if a design is good or not. Obviously there are many solutions (and therefore designs) to a single problem. Enter people. Ahh, if we could only remove them from the equation.
A group of people does a design review. Suggests other ways, modifies existing ways and comes up with a solution. Is it the best? It’s probably the best this group can offer. At the time. Time-travel 5 years later and you’ll see that you’ve picked the wrong technology, architecture and design to solve the problem. (In 1999, I worked on software for operating medical machine, that the R&D manager at the time thought it could be run in VBScript. Took a lot to convince him not to do that. Turned out our choice wasn’t that great either).
And so, we add another dimension to what is "good". Time changes everything. We know more today than yesterday. Agile methodology rejected BDUF (big-design-up-front) because although on paper it was supposed to solve everything in the beginning, in reality it was just a big costly process that submerged projects. Design decisions you take today will come back to haunt you 3 weeks, months, years from now.
So are there "good" or "bad" designs? Every person has an opinion. Opinions change over time. Problems and technologies change over time, and a design can help or interfere with the project, but you’ll know that in hindsight.
It doesn’t mean that all is lost, far from it. We all read blogs, books, we learn from other people’s experience, and try to come out with principles that will help us build software that makes and saves money. We improve over time, and learn from our mistakes.
We just need to remind ourselves every now and again – there might be something better than what we know today. Don’t stick to what you know, and don’t believe the flavor of the month is going to stay that way. You should always challenge what you know.
Who knows, maybe you’ll be who write the next set of the SOLID principles.