Patterns provide simple, elegant solutions to recurring design problems. The key advantages patterns provide are flexibility, modularity, and creating understandable and clear design. Note that I skipped reusability, although it's a bit unfair. Patterns take away focus from code reuse and move the focus to knowledge reuse instead. So patterns are very much about reusability, too, but just not in the way we usually think about reuse.
Gregory Young pointed out that many patterns are about reuse, through decoupling. The Dependency Injection pattern (which will be discussed in Chapter 10, "Design Techniques to Embrace") is a good example of that.
When you study patterns, you might think "OK, isn't that how we always do it?" An important point about patterns is that they aren't invented, but rather harvested or distilled. It's about proven solutions. But the solution part isn't the only piece of a pattern. They are described in three pieces: the context, the problem, and the solution.
Learning from your mistakes is very powerful, but from time to time it's nice to take a shortcut by studying other people's amassed knowledge, which is a good reason for learning patterns. Let's see if we can find other reasons.
Why Learn About Patterns?
The most obvious reason is probably that patterns are good abstractions that provide building blocks for system design.
If a development team is patterns-conscious, patterns become a very important part of the language. Instead of having to describe each and every design idea in minute detail, it's often enough to say a pattern name and everybody in the team can evaluate whether or not it's a good idea for that particular problem. Adding patterns to the team's language might be the single most important reason for embracing patterns because the common understanding, richness, and expressiveness of the language increase. Again, development is very much about communication.
Another reason I like patterns is that being able to utilize patterns is a long-lasting skill. As a comparison, I learned SQL in around 1988, and I can still make a good living from just working with that. The products and platforms I work with have changed several times, though the underlying concepts are the same. Patterns are similar. The Design Patterns book [GoF Design Patterns] came out in 1995, and it's still extremely relevant today. Also worth pointing out is that patterns are language-/product-/platform-agnostic. (Different platforms might have specific support for certain implementation variations, and it's also the case that the [GoF Design Patterns] have been written with object orientation as an assumption.)
If you study Design Patterns [GoF Design Patterns], you will find that the patterns there are very much in line with the principles of good object-oriented design. What is good object-oriented design, you might ask? Robert C. Martin discusses some such principles in Agile Software Development: Principles, Patterns, and Practices [Martin PPP]. Examples include the Single Responsibility Principle (SRP), the Open-Closed Principle (OCP) and the Liskov Substitution Principle (LSP).
Patterns are not only great with up-front design, they are very usable (perhaps even more) during refactoring..."My code is just becoming messier and messier. Ah, I need to use that pattern!" It's like the chicken or the egg problem, but I decided to start with patterns in this book and discuss refactoring after that (in the next chapter).
Is There Something to Look Out for Regarding Patterns?
Honestly, I see little reason for not learning about patterns, but there is at least one very common negative effect to look out for. What I'm thinking about is that for developers who have just learned about patterns, it's very common that they feel compelled to squeeze in 17 patterns in each and every solution. Most often that effect won't stay around for very long.
What might stay around for a little longer is the risk of over-design. If not 17 patterns, there might at least be a lot of thought about how a problem should be solved. The initial solution doesn't feel right because it doesn't use a certain pattern.
A friend of mine told me about a recent design problem he discussed with some developers at a company. It took him three minutes to come up with a very simple solution to the problem. (The problem itself was a simple one.) Yet the other developers weren't happy with the solution so they spent three days of hard thinking to get it just right.
Been there, done that. In my opinion, Test-Driven Development (TDD) is a good technique for avoiding that over-design problem. The design focus will be much more on solving the problem at hand and nothing else, and patterns will be introduced when needed via refactoring.
You might get the feeling that the patterns concept is the silver bullet. It's notof course notit's just another tool for the toolbox.
Patterns are often perceived individually as being pretty "simple," but they get very complex in context and combination with other patterns. I don't remember how many times I've heard people on the newsgroups say something like "I understand pattern X, but when I try to use it in my application together with pattern Y and pattern Z, it's extremely complex. Please help!" That isn't really a reason not to learn about patterns. This book will address that to some degree, but not here and now; first we will discuss some patterns in isolation.
I believe Joshua Kerievsky's Refactoring to Patterns [Kerievsky R2P] sets this straight by pointing out again and again that the way to most often use patterns isn't to use them in up-front design, but to refactor toward or to patterns.
OK, time to move over to the first pattern category. Let's see if we can create an "Aha!" and not just a "Huh?" for those of you who are pattern newcomers.