A Little Bit About Patterns






A Little Bit About Patterns

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.

Note

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).

More on Martin's Principles...

A bit of explanation of Martin's principles follows:

  • Single Responsibility Principle (SRP)

    An item such as a class should just have one responsibility and solve that responsibility well. If a class is responsible both for presentation and data access, that's a good example of a class breaking SRP.

  • Open-Closed Principle (OCP)

    A class should be closed for modification, but open for extension. When you change a class, there is always a risk that you will break something. But if instead of modifying the class you extend it with a sub-class, that's a less risky change.

  • Liskov Substitution Principle (LSP)

    Assume that you have an inheritance hierarchy with Person and Student. Wherever you can use Person, you should also be able to use a Student, because Student is a subclass of Person. At first this might sound like that's always the case automatically, but when you start thinking about reflection (reflection is a technique for being able to programmatically inspect the type of an instance and read and set its properties and fields and call its methods, without knowing about the type beforehand), for example, it's not so obvious anymore. A method that uses reflection for dealing with Person might not expect Student.

    The reflection problem is a syntactical one. Martin uses a more semantical example of Square that is a Rectangle. But when you use SetWidth() for the Square, that doesn't make sense, or at least you have to internally call SetHeight() as well. A pretty different behavior from what Rectangle needs.

Sure, all these principles are debatable in certain contexts. They should be used as a guide only, not as the "only truth." For example, OCP can easily be over-applied. You might have come to a point where you understand better how a method should be implemented and want to modify it rather than extend it. And adding a method to a class could also be seen as an extension.


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.

Note

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.

Pattern Adoption

Gregg Irwin said this about pattern adoption:

"For me, many concepts, like patterns, are learned in stages:

  1. You use it without being aware that you're using it

  2. You hear about it, read up on it, and tinker a bit

  3. You learn more and start using it explicitly, if naïvely

  4. You get the fire and evangelize (optional)

  5. Something "clicks"

  6. You learn more and apply it "less naïvely" and more implicitly

  7. Time passes and you see flaws

  8. You question the concept (often because you misapplied it)

  9. You either forget about it or add knowledge and experience (Repeat steps 59 as necessary)

  10. You use it without being aware that you're using it"


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.



 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows