|Home • Patterns • Ramblings • Articles • Talks • Download • Links • Books • Contact|
Design Patterns: More than meets the eye
Jan 13, 2009
Blogging about design patterns seems about as original as blogging about the Java (TM) Programming Language, except for the missing (TM). However, as I just attended a workshop on software service engineering, I realized once again that people from different fields have very different notions about the concept and usage of patterns. Many workshop attendees raised questions about formalizing patterns, tooling, etc. I touched on this subject a tiny bit in a post from long time ago, but I figured that the topic really deserves more attention, especially since to me a pattern is so much more than the "proven solution to a recurring problem within a specific context."
Obviously, there is already a lot of good work out there on this topic. My favorite books on the topic of patterns (as opposed to patterns on some topic) are the late John Vlissides' Pattern Hatching and Pattern-oriented Software Architecture 5 (aka POSA5) by Frank Buschmann and Kevlin Henney. Martin Fowler has also written a nice article on what patterns are and aren't. My intent is to give you an abridged version and also inject my personal opinion :-)
An Example: Bed Alcove
Especially in the academic world, it's easy to get stuck on definitional issues. So rather than try to define "what is a pattern" I just want to show one and proclaim "This is a pattern." Where else to start than with Christopher Alexander? Let's look at one of his patterns in detail. I abbreviated it from the original works, but I believe all the salient points remain. I also omitted the much discussed diamonds and other formatting details as they are not relevant to the point I am trying to make.
Patterns for the Smallest Rooms
Bedrooms make no sense.
First, the bed in a bedroom creates awkward spaces around it: dressing, working, watching television, sitting, are all rather foreign to the side spaces left over around a bed. Second, the bed itself seems more comfortable in a space that is adjusted to it.
Don't put single beds in empty rooms called bedrooms, but instead put individual bed alcoves off rooms with other nonsleeping functions, so the bed itself becomes a tiny private haven.
Communal Sleeping, Marriage Bed
Ceiling Height Variety, Half-open Room, Thick Walls
This pattern is taken from Alexander's extensive catalog of patterns, published as the book A Pattern Language and discusses the placement of a bed in a house. First off, the pattern has a descriptive name. The name is important because it allows us to use the pattern easily in a spoken or written sentence: "should we add a bed alcove to our house?" Since patterns are primarily meant for human consumption, enabling humans to embed patterns in their natural language is important.
The pattern is also part of a larger pattern language. It is part of the section Patterns for the Smallest Rooms. Patterns do not live in isolation, but are part of a pattern ecosystem or "pattern language." Alexander's language is organized from the macro level, discussing cities and neighborhoods, down to the micro level, describing where to put your bed or how high to make a room's ceiling. The bottom section of the pattern description, Related Patterns, links to other patterns in the language. Some patterns are "earlier" in the language, i.e. apply to a broader scope and are applied before one comes to the topic of bed alcoves. Communal Sleeping falls into this category. The second set of related patterns, such as Ceiling Height Variety, comes "later" in the language. If I decide to put a Bed Alcove into my house, I should consider the ceiling height next.
True to the oft-cited definition "a pattern is a proven solution to a recurring problem", the pattern starts with a problem statement. Note that the problem isn't "Where should I put my bed?" which feels more like a design step or decision to be made than an actual problem to be addressed. Instead, the problem is that traditional bedrooms make no sense. Why not? The forces tell us why. The forces are often described as the "heart" or the "meat" of the pattern. They elaborate the problem and tell us why it's difficult to solve. The forces often also explore alternatives and tell us what's good or bad about these alternatives. In our case, the forces talk about the notion of "negative space" and how a bed stuck into a rectangular room results in awkward negative space. While that makes sense, it's also somewhat non-obvious. Experienced interior designers are very familiar with the notion of "negative space", but to many people placing beds this may not be the case. Similarly, the notion of coupling and cohesion is quite familiar to many experienced (software) engineers and architects, but not to everyone hooking software components together.
Next, the pattern presents a solution. First you notice the sketch, which gives us a quick impression of the solution. Note that the sketch is not a design specification or precise architectural drawing. It's meant for people using the patterns to quickly grasp the essence of the solution. It's not something you throw over the wall to a builder to be built, but rather something you can use to help the builder understand your ideas and preferences.
In the software world, the discussion often arises whether the solution is a piece of code. While the solution is specific enough that someone can implement it based on the pattern, it's not meant to be cookie cutter code. A pattern is not a recipe or a code repository. Source code can be very useful as an example to illustrate one implementation of the pattern in a specific language or platform. But the solution itself is usually described with text, in combination with the sketch.
At this point, it's useful to repeat that the pattern is a lot more than the solution. The solution covers the "what" and some of the "how", but is lacking the "why", or the motivation for choosing this solution. The solution is specific enough to solve the problem and resolve the forces, but generic enough to be applied in a wide variety of contexts.
The solution is usually accompanied by a resulting context, which describes how this solution addresses the various forces, the strengths and weaknesses of the solution, related patterns, etc. It may also give tips for the actual implementation. I abbreviated this section from the above example.
When I speak about patterns to vendors or the academic community, one of the first questions is usually about tooling. Tools are (usually rightly so) a key ingredient into making software engineering better and more efficient. It's also something people pay for, which is not to be neglected. The idea of a patterns tool is typically along the lines of an IDE that allows you to create a solution by picking a pattern plus maybe some fine-tuning. Such a tool would raise the level of abstraction and improve productivity. In the case of the Bed Alcove, such a tool could be a CAD tool that allows you to draw the floor plan of the house. Rather than just placing individual lines representing walls, the tool would give you ready-made "pattern" building blocks, such as a Bed Alcove. In principle that's a good idea, and one of the reasons we supply a Visio Stencil for our Enterprise Integration Patterns.
There are a few things to watch out for, though. In the case of the EAI Patterns Visio stencil, the target environment is a drawing to help humans understand the solution. It's not an executable language or specification, or a component framework (more about patterns and components). A drawing stencil is relatively natural extension of the pattern, but still not without problems. First off, the pattern sketch is meant to be just that – something that conveys the essence of the pattern, not a precise specification. These sketches typically also do not follow a common underlying metamodel. Bed Alcove uses black lines to represent walls, other patterns in the same language may use black lines to represent roads, studs, or electrical wiring. Another challenge is that clean composition of the patterns is not addressed by the sketch. It's fairly natural to "add" a Bed Alcove to a room, but how to you add Communal Sleeping or Varying Ceiling Height? It becomes difficult to claim that this piece of wood and drywall maps back directly to a single pattern. Yes, the patterns are in there somewhere, but it's not clear which part comes from which pattern, which is usually important for tools, especially if we think about round-tripping, a common requirement for software tools. As explained in my earlier blog post the fact that this works relatively well with the EAI Patterns is thanks to the fact that the composition is based on the very simple (and strict) pipes and filters architectural style.
So I'd say some tooling for patterns comes fairly natural while other tooling requires more thought and effort. The distinguishing factor is often whether the tooling requires the pattern to be formalized, a topic that is often also raised when I talk about patterns to the academic community.
When talking about pattern tooling, and how patterns can be formalized, the word variability point frequently comes up. The idea behind variability points is to distill the common elements of a design construct, and separate the elements that still have to be decided later during the design process, for example because they depend on the specific platform or implementation. A quick stab at identifying some variability points for Bed Alcove could be:
The relevance of variability points lies in the notion that pattern + specific values for the variability points yield an (executable) specification. So if I provide all the values for the points above, I could in fact hand this over to a builder, come back in a week and find my Bed Alcove constructed exactly like I envisioned it. Or at least that's the idea.
I generally like the notion of variability points as they help me find abstractions, but like to highlight two important limitations. First, a list of variability points and the associated tools are less about describing the pattern, but about projecting the pattern solution to a specific platform. Nothing wrong with that, but I always like to remind people that the pattern is much more then than just the implementation. The canonical example in this context are Strategy and State, patterns from GoF, which have identical solutions, but obviously quite different intents. I'd say that distilling variability points is one thing you can do with (and also without) the pattern, but the pattern has enormous value as a design tool without any mention of them.
The second challenge is whether the variability points can really describe the whole solution, or are simply an attempt at shrinking the gap between the pattern and the implementation. The Bed Alcove dimensions fare reasonably well here. If I want my alcove to be 200 x 120 x 150cm made from wooden stubs covered with drywall and painted with paint foo from vendor bar, I am pretty likely to get one that meets these specifications. It gets tougher on the decorative elements. Can I specify a "rustic" vs. a "contemporary" look with variability points? If possible, does it make sense to do so or would I end up creating more paperwork than it takes to actually build the alcove? Do we have a precise enough language to express these implementation details? Imagine trying to define variability points for the design of a chair. Some books show hundreds of successful chair designs, which have very little in common besides the fact that a person can sit on them.
Finding a formal specification that allows the injection of platform-dependent parameters is much closer to the domain of generative programming than patterns. Patterns can provide some inspiration, kind of like Las Vegas casinos are "inspired" by Paris or Venice. For a more elaborate description of the gap between patterns and formalisms, see Chapter 2 of POSA 5.
An immediate follow-up to variability points is usually the notion of componentization. The hope is that if I can drive out all the variability points, I can develop a generic component, and inject the actual values for the variability points via configuration. Voila, I have a (semi-) automated pattern tool. This tool raises the level of abstraction from Java or C# source code to patterns and supplied variability points. This can work in some circumstances, as demonstrated for example by the Simple Messaging Toolkit.
The closest analogy to componentizing the Bed Alcove is heading to IKEA and picking up the "Sloep" bed from the shelf, making sure the dimensions match the requirements. This can certainly speed up construction, but again we have to remind ourselves that Sloep the bed is only loosely related to the pattern. Bed Alcove discusses trade-offs of where to place a sleeping location, focusing primarily on human well-being and comfort. Sloep is all about inexpensive manufacturing and quick assembly, which certainly has value, but in a different context. Bridging the gap between the pattern and the component two is valuable, but my fear is that the gap is so big that one is tempted to fudge the pattern a bit to make the gap smaller and thus be able to find better a tie-in. For example, instead of Bed Alcove, someone who focuses on components may be tempted to define the pattern as Bed, the problem as "Where should people sleep?" ,the forces as "People like to sleep horizontally", and the solution as "Buy Sloep the Bed". Now pattern and parameterized component solution are unified, but in the process the pattern has lost most of its value. Where people should sleep is not a very interesting design challenge and buying a bed, while recurring, is really not a surprising solution. The pattern also no longer forms a vocabulary for design decisions. "Bed" is a piece of furniture, not a design problem. We don't really need a pattern for this.
Again, I am not saying it can't be done, but too many times I have seen people fall into these pitfalls that I am tempted to put more energy into making a good pattern and pattern language than to try to componentize the patterns.
Patterns are for Humans
The primary purpose of patterns is to help humans understand design problems. Solving design problems is generally much more difficult than typing in some code, so patterns have enormous value in themselves. Patterns owe their popularity to this value. A better hammer can help speed up the construction of a bed, but a pattern helps us place the bed in a way that makes us feel comfortable.
MORE RAMBLINGS SUBSCRIBE TO GREGOR'S RAMBLINGS
Gregor is the Chief IT Architect of Allianz SE. He is a frequent speaker on asynchronous messaging and service-oriented architectures and co-authored Enterprise Integration Patterns (Addison-Wesley). His mission is to make integration and distributed system development easier by harvesting common patterns and best practices from many different technologies.
|© 2010 • All rights reserved.|