Darrell hit the nail on the head about design patterns in his last post.
It’s my belief, too, that design patterns are better thought of as a solution to a problem – a real problem that you encounter while coding (refactoring), not a problem you think you are going to encounter.
And, as Darrell mentioned, Joshua Kerievsky obviously feels the same way, because in his book, Refactoring to Patterns, he dedicates a number of chapters to showing you how to identify a code / design smell during refactoring and implement a design pattern to solve it. It’s a great book by the way.
Using a design pattern that solves no real problem adds unnecessary complexity to an application. This is point #5 in my last post, Agile Software Development – Principles Patterns and Practices, that lists 7 design smells that are characteristic with rotting software:
- Rigidity – System is hard to change in even the most simple ways.
- Fragility – Changes cause system to break easily and require other changes.
- Immobility – Difficult to entangle components that can be reused in other systems.
- Viscosity – Doing things right is harder than doing things wrong.
- Needless Complexity – System contains infrastructure that has no direct benefit.
- Needless Repetition – Repeated structures that should have a single abstraction.
- Opacity – Code is hard to understand.
Everyone has been guilty of unnecessary design patterns and over-architecting a solution. I think it’s the normal evolution of a developer and something you learn to tame with experience.
I have noticed that I really started to appreciate design patterns more and began implementing them only during refactoring when I started to:
1. Practice test-driven development and other agile and iterative development methods
2. View and build applications as a collection of loosely-coupled, and highly cohesive components (i.e. libraries)
IMHO, as soon as you do one or both of the above and do the necessary refactoring during development to create healthy software, you begin to see and easily identify smells and the design patterns that solve them. Even if you “knew” the problem would show up from the beginning, I personally think it is much more fun to address it during the refactoring process as it not only makes coding much more enjoyable but also definitely substantiates the use of the design pattern.
It has been my experience that if you are pretty good about refactoring while developing, it is easy to turn around an implement a design pattern later on when a new requirement pops up as opposed to adding the unnecessary complexity from the beginning when there is no direct benefit.