Pattern Hatching
Seven Habits of Successful Pattern Writers
C++
Report, November/December 1996
If you think object-oriented development is hard to do well, try
pattern development! The mathematician in me likes to think of it
as the ``integration'' of object-oriented design: it's the sum of
innumerable little experiences over an interval of applications. Yet
pattern development seems a good deal harder than what I learned in
calculus class. Integrals don't interfere with one another, which
lets you solve them independently (although knowing how to solve one
often helps you solve others). A pattern, in contrast, doesn't work
in a vacuum. It provides the solution to just one problem; so it must
cooperate with other patterns. Therefore a pattern writer must
contemplate not one pattern but several, even some as yet unwritten.
And that's but one of many challenges in the pattern development
process. If you're an aspiring pattern writer, you'll need all the
help you can get.
We certainly learned a lot about pattern development in writing
Design Patterns. So what I've tried to do this time is boil down
our experience into seven habits we adopted, largely unconsciously,
over the four-some-odd years it took to write the book. Taking these
habits to heart should help you hone your pattern-writing abilities
far faster than we did.
HABIT 1: TAKING TIME TO REFLECT
The single most important activity in pattern writing is reflection.
Bruce Anderson, an early influence on our work, has offered up this
mantra for years. Take time off periodically to reflect on what
you've done. Think about the systems you've built, the problems
you've had, and how you solved (or didn't solve) them.
Such diversions are all but unthinkable in this day of ever-shortening
development times. But reflection is crucial. There's no better way
to get into a creative rut than to hack mindlessly. You may produce
lots of working code, but code mass is a poor measure of one's
productivity. The mark of a good design is precisely the
opposite---it is small and elegant. It does much without bulk. It
implements everything ``once and only once,'' as Kent Beck likes to say.
It's also flexible; large bodies of code generally aren't.
Now, it's probably impractical to expect people to take a month off
per year for contemplation. But what you can do is record your
experiences incrementally. When you have a non-trivial problem to
solve, try to write about it immediately. Jot down some notes
describing the problem and why it's difficult. Then start working on
it. Whenever you try a new approach, jot it down. If it fails, jot
that down too, along with why it failed. Do the same if it
succeeds. Almost everyone can spend five percent of their time
jotting down experience---it just takes discipline.
If you do this religiously, you'll be amazed at the written experience
you accumulate. This is the raw material of patterns. There's still
much to do, certainly, but you've got the all-important nuggets of
wisdom from which to refine the gold.
Another important activity along these lines is to look at as many
other systems as you can, systems designed by other people. The best
way to learn from other systems is to actually build with them. If
you don't have the time or money to do that, then at least read about
them. Seek an understanding of the problems they address and how they
address them. Study specifications and documentation. Read papers on
research systems. Browse through OOPSLA and
ECOOP proceedings.
Software---Practice & Experience is another good source of design
and implementation information.
When you examine a system, glean everything you can from it. Try to
identify patterns you already know. Evaluate how the solutions you
find vary from those of published patterns. Be on the lookout for
novel design solutions---they may represent new patterns. But keep in
mind that relatively few design solutions are truly new. More often,
people use variations on known solutions. A new and unique solution
might not be widely applicable enough to cast in pattern form.
If you do find something that seems new, make sure it is applicable in
other contexts before you try to write it up as a pattern. We had one
inviolable rule as we developed Design Patterns: we had to find
two existing examples of a problem and its solution before we would
write a pattern for it. This was a particularly important rule for us
to follow, because we were exploring unfamiliar territory, and we
wanted to make sure what we wrote was grounded in reality. We didn't
want to end up with a set of solutions to problems no one had.
Ultimately we discarded many patterns that seemed quite appealing and
potentially useful but hadn't seen real use.
HABIT 2: ADHERING TO A STRUCTURE
Once you have the raw materials, how do you go about writing them up
in pattern form?
Well, first of all, don't assume there is only one pattern form. No
one form suits everybody. Some people prefer a more prosey style like
Alexander's. Others favor the more fine-grained approach used in
Design Patterns. Still others adopt totally different structures.
The attribute shared by all these structures is just
that---structure.
If there's one catchphrase that people largely agree on, it is the
Alexandrian canon that a pattern is ``a solution to a problem in a
context.'' Now I'll be so bold as to amend the canon: A pattern is a
structured exposition of a solution to a problem in a context.
Patterns have recognizable parts that guide their application and
comparison. These parts include a name, a statement of the problem,
the context and justification of its solution, and the solution
itself. This is essentially the structure of Alexander's patterns.
Our patterns further decompose these fundamental elements into more
focused treatments, such as the Applicability, Participants, and
Consequences sections. The proceedings of the 1994 Pattern Languages
of Programming (PLoP) conference includes surprisingly diverse
variations on these themes.
So the first step in getting a pattern down on paper is to decide on
its structure. The more information your average pattern has, the
more important the structure becomes. Consistent structure lends
uniformity to patterns, letting people compare them easily. Structure
also helps people search for information. Less structure means more
prose, which might be fine for casual reading but unacceptable for
comparison and reference purposes.
Once you've settled on a structure, make sure you follow it
consistently. You needn't be afraid to change the structure, but
you'll have to change it in every pattern---and that gets increasingly
expensive as your patterns mature.
HABIT 3: BEING CONCRETE EARLY
In our patterns, the Motivation section comes up-front. That's
because people seem to understand concepts better when they are
presented in concrete terms first and then more abstract terms. The
concrete example in the Motivation section gives the reader a frame of
reference for the problem and its solution. Another thing this
section demonstrates is why other approaches to the problem fail,
again in concrete terms. With the Motivation section as an
introduction, the reader is better able to appreciate the general
solution.
A corollary to concreteness is the need for lots of examples from the
real-world. Examples should not be the sole estate of a Motivation
section. Use examples and counterexamples throughout the pattern to
illustrate key points. Even the most abstract sections in our
template (i.e., Applicability, Structure, Participants, and
Collaborations) at times include examples. For instance, some of the
Collaboration sections include interaction diagrams that show how
objects communicate at run-time. Refer to such examples when
discussing the abstract aspects of the pattern---be concrete even when
you're being abstract.
Another corollary might be termed ``telling the whole truth.'' That
means you must warn your reader about potential pitfalls of the
pattern. It's all too easy to dwell on its positive aspects; it's not
so easy to appreciate its faults and talk frankly about them. No
pattern is free of drawback, be it extra cost, ill-behavior under
certain circumstances, or whatever. Make sure your reader understands
how the pattern can fall short.
HABIT 4: KEEPING PATTERNS DISTINCT AND COMPLEMENTARY
There's a tendency to avoid when you're developing multiple patterns.
As a you work on a pattern, it tends to grow both in detail and in
scope. It's easy to forget about other patterns in the meantime. The
distinctions between patterns blur as a result, making it hard for
others to understand the patterns collectively. They start to overlap
in scope and purpose. It all may seem perfectly clear to the author,
but it probably won't be clear to newcomers. They won't know when to
use one pattern and not another, because their differences aren't
obvious.
Therefore make sure your patterns are orthogonal and that they work
synergistically. Continually ask yourself, ``How is pattern X
different from pattern Y?'' If two patterns solve the same or
similar problems, you can probably merge them. Don't worry if two
patterns use similar class hierarchies. There are only so many ways
to use the relatively few mechanisms inherent in object-oriented
programming. Often the same arrangement of classes will yield
substantially different object structures that address widely varying
problems. Let the intents of the patterns be your guide to their
differences and not the class structures that implement them.
A good way to test how orthogonal and synergistic your patterns are is
to keep separate documents in which to compare and contrast your
patterns. In Design Patterns we dedicated several sections to this
purpose. The simple act of trying to explain pattern relationships in
written form gave us new perspectives on our patterns. More than once
it forced us to rethink some of them.
My only regret is that we didn't concentrate on relationships earlier
in the game. I recommend you start writing down such supplemental
material as soon as possible. It may seem like a silly thing to do,
especially when you don't have a lot of patterns to compare. But as
soon as you have just two patterns, the possibility of overlap
emerges. Spending time comparing and contrasting them early on will
help keep your patterns distinct and complementary.
HABIT 5: PRESENTING EFFECTIVELY
The quality of your patterns is determined by how well you present
them. You could discover the best pattern in the world, but it won't
help anybody unless you convey it effectively.
By ``presenting'' I mean two things: typesetting and writing style.
Good typesetting is a matter of skill in page layout, typography, and
graphics, not to mention printer quality. Use the best software tools
(word processor, drawing editor, etc.) you can. Make liberal use of
drawings to illustrate key points. You may not think you need any
drawings, but chances are you do. At the least they break monotony,
and at best they'll get your point across as no amount of explanation
can. Not all drawings have to be formal class and object diagrams;
informal drawings and even sketches often convey just as much
information and more. If you are ``artistically challenged,'' then have
someone else do the drawings for you.
Good writing style is even more important than good typesetting. Write
clearly and unpretentiously. Favor a down-to-earth style rather than
a stuffy, academic one. People understand and appreciate a
conversational tone, making them more receptive to the material.
Clarity and ease of reading are important in most writing, but they're
especially important for pattern writing. The pattern concept is new
enough and the subject matter complicated enough that some people have
a hard time seeing the point of it all. Everything that can be done
to make a pattern approachable should be done.
The best way to learn how to write conversationally is to try your
hand at it. Make sure that everything you write is something you
could hear yourself saying to friend. Avoid the passive voice. Break
up long sentences and paragraphs. Use everyday words, and don't be
afraid to use contractions. Above all, make it sound natural.
Another thing everyone should do at some point in life is read a book
or two on writing style. There are many to choose from. My three
favorites are Strunk and White's The Elements of Style (whose
organization, remarkably, is not unlike a series of patterns), Joseph
M. Williams' Style: Ten Lessons in Clarity and Grace, and John R.
Trimble's Writing with Style: Conversations on the Art of Writing.
Books like these are packed with tips and techniques for good, clear
writing. They can help you improve your patterns independent of their
technical content.
HABIT 6: ITERATING TIRELESSLY
You won't get a pattern right the first time. You won't even get it
right the first ten times. In fact, you'll probably never get it
totally right. Pattern writing is an on-going process. The fact that
the field is new doesn't help matters. But even if it weren't...even
if there were lots of examples of good patterns and books to help you
write them, pattern development (like any other kind of development)
would still be an iterative process.
Expect to write and re-write your patterns many times. Don't look for
perfection in one pattern before you begin work on the next.
Remember, patterns don't exist in isolation; they affect one another.
A significant change to one could very well impact others. As with
any iteration, your efforts should converge at some point, but that's
just the point where the patterns have stabilized enough to let other
people read, understand, and comment on them.
HABIT 7: COLLECTING AND INCORPORATING FEEDBACK
Cervantes was right: ``The proof of the pudding is in the eating.'' The
acid test of a pattern comes when it's put to use. Actually, no
pattern can be trusted until it is used by someone other than its
author. Patterns have the insidious property that they are usually
perfectly understandable to people who are familiar with the problem
involved and its solution. Such people have used the pattern before
unconsciously. Thus when they see the pattern, they can recognize it
immediately, even if it isn't presented very well. The real challenge
is to make the pattern understandable to people who have never run
across the problem before. There's no way to do that without getting
and incorporating feedback from just such people.
Encourage your colleagues to discuss design in terms of your patterns.
(It's okay for the author to participate in such discussions.) Look
for opportunities to use the patterns in your day-to-day work. Try to
disseminate your patterns as widely as you can. You might even submit
them to conferences like PLoP or to publications like C++
Report, Smalltalk Report, and Journal of Object-Oriented
Programming. Such exposure will maximize the use of your patterns.
Once the feedback starts rolling in, be prepared to hear the worst. I
can't remember how many times I was shocked to learn that something
that seemed thoroughly comprehensible to me thoroughly confounded
someone else. The negative feedback can be disheartening, especially
at the beginning when you're most vulnerable and also most likely to
receive it from people. While some criticism might not be valid or
might result from a simple misunderstanding, most of it will probably
be legitimate. Give your reviewers the benefit of the doubt. Bend
over backwards to make them happy. You may end up making many, many
more people happy in the long run.
NO SILVER BULLET
Adopting these habits won't guarantee your success as a pattern
writer, of course. Nor is this list exhaustive. But at least it
should help you focus your efforts profitably. The better your
patterns are, the more impact they'll have.
That's not to say everyone should be a pattern writer, however.
Pattern writing involves a nontrivial investment, and not everyone can
justify it. Everyone should try pattern writing at least once, since
you can't know if you're good at it otherwise. As time passes,
though, I expect the number of pattern writers to be dwarfed by the
number of pattern users---much as programming language users
(thankfully) dwarf the ranks of language creators.
Acknowledgements
I first articulated these habits at a workshop on software
architecture in Dagstuhl, Germany, in a position paper titled ``Reverse
Architecture.'' A summary of the workshop appears in ACM Software
Engineering Notes, July '95, Vol. 20, No. 3, pp. 63-83.
References
Coplien, J. and D. Schmidt, eds. Pattern Languages of Program
Design, Addison-Wesley, Reading, MA, 1995.
Gamma, E., R. Helm, R. Johnson, J. Vlissides. Design Patterns:
Elements of Reusable Object-Oriented Software, Addison-Wesley,
Reading, MA, 1995.
Strunk, William, Jr. and E.B. White. The Elements of Style,
Macmillan, New York, 1979. Third edition.
Trimble, John R. Writing with Style: Conversations on the Art of
Writing, Prentice-Hall, Englewood Cliffs, NJ, 1975.
Williams, Joseph M. Style: Ten Lessons in Clarity and Grace, Scott,
Foresman and Co., Glenview, IL, 1985. Second edition.
This page and its contents ©1995 by John Vlissides. All Rights Reserved.
Back to Design Patterns
Back to Patterns Home Page
|