From all the time I've spent learning design, there are a handful of things I'd hope to remember or re-read if I were to ever get amnesia and have to start all over again. For new comers and experts alike, I'd like to share a few ideas about design worth thinking about through musings and links to other material that has helped form my opinions (some more relevant than others).
The competent programmer is fully aware of the strictly limited size of his (or her) own skull; therefore he (or she) approaches the programming task in full humility, and among other things he (or she) avoids clever tricks like the plague.
Designers are something of an enigma to most people; however, the fruits of their labor are largely understood, well used and appreciated. Design is often considered to be a purely aesthetic matter: a matter of taste, of style, of opinion; we know a good design when it when we see it. But many times we can't quite put our thumb on why it's good design, or what makes it well-thought out, or pleasing. Maybe some of us can articulate what it is we like about design, but few connect the dots enough to notice recurring qualities in our favorite designs or think about underlying truths beneath those qualities. Even fewer still have the experience to know when to apply these qualities, within the proper context to produce a good design.
Programmers are equally if not more engimatic to general society. Perhaps on the surface for many different reasons. But, coincidentally developers are designing all the time; could this play a part, perhaps? Is this why we refer to the most experienced of our profession as "architects?" Aren't we, by way of programming systems and wiring them together, inherently striving for greatness as designers?
Especially when you're inexperienced, you're very much focused on learning what it is about a design that you find compelling, agreeable, or pleasing. We value a good design so much that we spend a lot of time studying, talking about and debating what makes a good design. As the narrator (Jack?) in Fight Club admits he had become "a slave to the IKEA nesting instinct," so too, I find myself in willing servitude of the design pattern instinct at times. More often nowadays I stop and catch myself, and I'd like to think I'm not the only one with this premonition. Too quick are we to whip out our design patterns books (especially right after we've finished them) and, as the first order of business, go to town solving problems we don't have.
Few products today need to ship in shrink wrapped boxes as they once traditionally had to. The connectedness of the Internet, coupled with all of the modern advances in hardware have fundamentally changed the way we look at developing software. "Fast, cheap, good — pick any two" still applies, but fast is faster, cheap is a lot cheaper, and good encompasses much more today than ever before. Software development still lags behind.
The unwise developer makes all design decisions up front, for fear of getting the solution wrong. The enlightened developer creates the closest thing to a working solution now, for fear of getting the solution wrong. The former produces a solution that fits his view of the problem. The later continually adapts his solution to encompass others' view of the problem. Which is more valuable? The unwise developer wants to be done, and will sacrifice alienating some users. The enlightened developer wants to be correct, and will compromise stability of the design. Why do this? Because inactivity leads to software rot, and we have techniques for dealing with changing designs. What good are our big up-front design skills when the requirements change?
Like Darwin encouraged us to do with our views of biology, we've ditched an up-front design model for an evolutionary one. There is increasingly a focus on software as an evolutionary process everywhere, and it's phrased in many ways: continuous production (Cal Henderson's explanation the best); the perpetual beta; "no such thing as done", agility – openness and responsiveness to change. The risk of bloated software has lead us down a path to focus on and seek to create small, modular applications that create "business" value immediately, can be chained together but never grow overly complex. Our design decisions still exist, but they are on a much smaller scale, and with much more concrete drivers and concerns factored in. And we understand that we're fundamentally in error when we make them out-of-context.
Others have thoroughly dealt with this topic in much greater detail than I can or care to. Neal Ford has written about what Evolutionary Architecture and Emergent Design look like. Martin Fowler has asked, "Is Design Dead?" and answered his own question. I would encourage you to read their thoughts on the matter, as my own conclusions are largely in line with theirs.
That being said, there are some tools that you should look to add to your collection as you go. Any craftsman must learn to master his or her tools. Just having the tool in your toolbox does not necessarily make you a good designer; because they must be used properly, in the proper context. Like Clint Eastwood's character explains of his toolkit in Gran Turino: each tool has a job, its own context and realm of applicability. Also, resist the urge to apply them every chance you get. Much of good design is about restraint. Try to see them applied correctly, or incorrectly, and talk with others about it. Keep a conversation going; don't allow your codebase to become stagnant. Continually question, strike the right balance and good designs will emerge and bad designs will improve. Your methodology may have you delivering in sprints, but good design is a marathon.
Here are the basic tools. There is a lot of material out there on these – easy to Google or find on Wikipedia. I am not going to offer any links or speculation, because I think these things should continually be discussed. You should be constantly evolving your own opinions and knowledge of them. They must be used, discussed and understood in order to be mastered.
Overarching Computing Principles – Reduce Complexity
- KISS – Keep it Simple, Stupid.
- DRY – Don't Repeat Yourself.
- YAGNI – You Ain't Gonna Need It.
- SOC – Separation of Concerns.
Basic OO Principles
- Coupling/Cohesion (dependency)
SOLID (Advanced) OO Principles
- Single Responsibility Principle
- Open/Closed Principle
- Liskov Substitution Principle
- Interface Segregation Principle
- Dependency Inversion Principle
Emergent Design Techniques
- Test Driven Development
- Continuous Integration
- Project Automation
- Continuous Production
To borrow a great closing quote from Brian Liles,
Do not seek to follow in the footsteps of the wise. Seek what they sought.
More Related Content
- July 24, 2009 — The Elements of Reusable Code (0)
- January 7, 2010 — Eliminate Branching (IF Statements) to Produce Better Code (0)
- June 9, 2009 — Mocking with JMockit (3)
- June 3, 2009 — What is Hamcrest? (0)
- April 15, 2009 — OSGi-ggity-Giggity (4)
- December 1, 2008 — 24ways (1)
- November 28, 2008 — Must Haves/References For Modern Java EE Developers (1)
- November 19, 2008 — Java 6 and Maven 2.0.9 on Leopard (7)
- August 2, 2008 — How I Escape the "Reuse Trap" (0)