There’s been a lot of blog traffic lately about the differences and merits of both upfront and evolutionary design. There are a large number of seemingly contradictory design philosophies, techniques and tools out there. You have to assume that most of these techniques have worked in some situation for somebody or they’d never have been published in the first place. I think that there aren’t very many absolutes in techniques for software design because the effectiveness of any technique is governed by the project, technology, and learning style of the designer. The few absolutes that I’d list are so general that they’re not really useful in crafting a specific approach to design. It’s probably worth reminding ourselves that there is still no Silver Bullet technology or methodology that magically solves every design problem. Here’s what I think though:
- Design incrementally. Eat the elephant one bite at a time. This isn’t to say that thinking ahead in the design is a bad thing. Like many people I think that it’s best to design in detail and code in smaller chunks.
- Challenge the coding and design every day. Complacency is evil. Pay attention to what you’re coding. Recognize a design that isn’t working and spot opportunities to improve the design as you work.
- Talk about the design with your coworkers. Socializing a design is a major part of doing design.
- Reflect on your design during and after the project
- If something about your design feels wrong it probably is (“Let go your conscious self and listen to your feelings”)
- The more design tools, knowledge, and approaches that you’re familiar with the more successful you’ll be. I think many Agilists hamstring themselves by unnecessarily dismissing any technique from outside the Agile canon. I routinely supplement TDD with UML modeling or Responsibility Driven Design concepts (but I always feel silly when I try to use CRC cards). Every so often I even draw up a database structure first as an exploratory activity.
- Architecture, design, and coding are too intrinsically intertwined to be done by separate people or teams (non-coding architects + spec coders = bad results). You can’t design what you can’t code
- Every developer is a more effective coder with design knowledge. “Spec” coding sucks. Coders that design too can make the small adjustments that lead to good systems. A coder with no design skills just muddles through or perfectly follows the designs created by the all too human architect. I don’t know if the 10-1 productivity ratio between good developers and bad developers is true, but I agree with Joel that bad developers just don’t produce good code.
How and When I do Design Might Not Work for You
I promise to never ever write a book about my personal design methodology because it won’t work as well for you unless you have a nearly identical learning style and personality type as me. I’m a big fan of “UmlAsSketch” at a whiteboard because my learning style is clearly visual, and kinematic (explaining my predilection for arm-waving in front of a whiteboard). The act of drawing UML diagrams on a whiteboard or using CRC-like notation is really just a concentration aid for me, much like school children learning to count on their fingers.
I also like to keep a design notebook as a scratchpad for design ideas. It’s an interesting exercise to go back through older notes at the end of a project or even years later to see how your design (thinking) has evolved. It also leads to quite a few “what was I thinking?” moments. I can easily trace my evolution from a database-centric VB6 guy to an OO-centric with TDD .Net guy. It’s also been a way to recycle design ideas later. I’ve managed to use concepts that were discarded on one project successfully on another.
I’ve learned the hard way that many perfectly capable and productive developers simply don’t work the same way I do. I’ve been around strong developers that cannot derive any meaning from even the simplest UML drawing. It might as well be hieroglyphics to them, even when you’re talking about code that they’re familiar with. On the other hand, I usually can’t just sit down in front of a computer screen and start banging out code. I’m usually much faster when I do a little bit of notepad sketching or even just make a list of things to do for my coding task. I’ve been around other developers who do best when they’re looking at code, so they want to jump right into the IDE, write some code, and then start figuring out which way to go. Not all of their code is bad; they just have a different way to get started. Pair programming brings out another contrast in personal style. Extroverted people are energized and think better when they are talking things through with someone else. I’m the exact (introverted) opposite, and it makes pairing difficult for me at times. I like to keep a notepad near me when I’m pairing to jot down notes or share off-the-cuff drawings with my pairing partner.
The true masters of TDD can sit right down and quickly write that first unit test to get them going. That first unit test on a task is usually the hardest and it’s what I see people struggling with. I have to go to some other activity first to break the ice. One thing I tell TDD newcomers is to just make a list of unit tests you think you’ll have to write, and start with the easiest unit test first.
Another huge difference between developers is how well they can visualize and think through a problem in advance. Some folks can easily handle and create abstract mental models. Other people need to keep things more concrete. My mechanical engineering background actually helps me with abstractions because engineering is often an exercise in creating a simplified model of reality for easier calculation. Pattern matching is a huge variance across developers. Some developers can anticipate a repeated function in the code and create an abstraction or reusable class collaboration earlier. Other people need to see the pattern in code a couple of times first.
My only real point here, assuming I have one, is that because we’re all different in our learning styles it’s worth your time to investigate multiple techniques (and never assume that Joe Bob’s nirvana design technique will work for you). If you’re aware of your own learning style you can fine tune your personal approach to play to your strengths. It’s also smart to be cognizant of your coworkers’ learning and communication style so that you can adjust to them. It’s absolutely useless to draw UML models around folks that aren’t visual. That was a painful lesson I learned the last time I was a technical lead.