Monday, January 30, 2006

Pattern drift

When I first reviewed Design Patterns, I recommended it be published as a loose-leaf notebook. I suggested that authors provide regular updates (this was before the Internet was readily available!). I anticipated frequent updates and many more additions…23 patterns didn’t seem like nearly enough.

Fast forward to 2006. Design Patterns has been in print unchanged for 12 years. Although recognized as a landmark book, it needs refreshing. In fairness, the book was so popular that there was little motivation to do so. An update is supposedly in the works.

I give my students the original text, but they struggle to read it and find relevance (C++ and graphics examples are a stretch for most). I always point them to other sources, both online and in print, to fill in the gaps. Many have written their own take on specific patterns. That is a good thing. In 1998, in a C++ Report article, John Vlissides acknowledged that pattern definitions aren’t cast in stone.

It seems you can’t overemphasize that a pattern’s structure diagram (class diagram) is just an example, not a specification. It portrays the implementation we see most often. As such, the Structure diagram will probably have a lot in common with your own implementation, but differences are inevitable and actually desirable. At the very least you will rename the participants as appropriate for your domain. Vary the implementation trade-offs, and your implementation might start looking a lot different from the Structure diagram.

In Refactoring to Patterns, Josh Kerievsky quotes Vlissides and then after illustrating the original Composite pattern:

Gives his own take on a single-class implementation:

Hmm. A single concrete class that could support either leaf or composite behaviors. Now that’s a thought…but is it still recognizable as a composite pattern? Sure…but what is it that makes a composite a composite and not just another structuring mechanism? Is it just a fancy name for a “tree structuring mechanism” or is there something more?

Bob Martin, in Agile Software Development, presents another variation. He illustrates composite with a Shape interface which defines a single method-draw(). That interface is realized by classes that are either primitive shapes or composed of other shape objects.

In 1994 when Design Patterns was published, interfaces weren’t present in popular programming language. The authors relied on abstract class definitions instead. Since I spend my time with C# and Java, today I’d likely recast many GOF patterns using interfaces instead of abstract classes, especially when there isn’t any common meaningful behavior to inherit.

But Bob’s example illustrates another important design choice. He didn’t force-fit composite behavior into a common abstraction shared by both “composite” and “leaf” objects. He isn’t alone in making this tradeoff. Many of my students after struggling to define meaningful operations common to both, throw up their hands and grumble that the GOF authors made the wrong tradeoffs when they specified the composite pattern. This sentiment is echoed on a RICE webpage:
In Design Patterns, the abstract component AComponent is shown as having accessor methods for child AComponents. They are not shown here because it is debatable as to whether one wants the Client to fundamentally view the AComponent as a single component or as a collection of components. Design Patterns models all AComponents as collections while the above design models them all as single components. The exact nature of those accessor methods is also debatable.

Debating design tradeoffs is healthy. That’s why I give my students GOF undistilled and we discuss tradeoffs as they learn patterns. This helps them gain design confidence as they articulate their values and say what they like and don’t like about the patterns as presented…But sometimes I think they’d prefer a simple “canonical” pattern form they could just use without much thought. I often point them to the Data & Object Factory website which has a quick pocket guide discussion of each pattern. But the composite pattern sample implementation there defines an abstract Shape class with empty add() and remove() methods. And leaf classes implemented add or remove by writing a console message “can’t add/draw a shape to an X”… A toy solution if I ever saw one! Perhaps if I paid $79 to purchase their Design Patterns Framework I’d see a more realistic implementation.

This leads me to wonder: what makes a pattern useful, how much change can or should it undergo, and how much “stewardship” should there be over pattern drift, pattern evolution and pattern explanations? I don’t expect patterns to be fixed and unchangeable. They should wiggle around a bit. But I like thoughtful discussions and reasonable examples. I wish there was a community that maintained an active PatternPedia repository where authors would be encouraged to keep their patterns up to date and where there were useful teaching examples, thoughtful reviews, and summaries of both new and classic patterns. The Portland Pattern Repository is a springboard for patterns, but it doesn’t seem very active. The Hillside website is useful, but it just points to other sources. I have more in mind a cross between Wikipedia and Amazon with an edge and an active editor/convener whose job is to keep us informed of the latest breaking pattern news. Sure I can search the internet and books for patterns. But my search feels scattered. I never know when I’ll stumble across some arcane shift, a mangling of a pattern’s intent, or a good trend to follow. It’s too hit and miss.

Currently, most patterns are copyrighted by authors and are locked up in relatively static media—books or conference proceedings or magazine articles—or static online versions of the same. There’s no central source, no common repository for a growing body of pattern wisdom gained from experience. So when pattern interpretations shift, as they invariably do, it is in a quirky ad hoc manner. I don’t mind Kerievsky’s compact interpretation of Composite. I just wish his version was accessible to those who didn’t buy his book, and that there was a place for open debate about the merits of this implementation choice that was readily linked to other Composite pattern interpretations. Is this asking too much? Isolated works make it difficult to change/refine/invigorate patterns with in a larger community of users/developers/pattern authors. What would it take to create a patterns commons? I’d be interested in hearing your thoughts.

9 Comments:

Anonymous Anonymous said...

I think it is a great idea and a wiki with the organization you propose is a good start.... like a wikipedia
The problem to be useful is that it has to get enough momentum, that's the difficult part....

9:36 AM  
Anonymous Rebecca said...

Momentum and traction are always problems. Instead of "just saying it can't be done", I want to start saying..how can I start to create such a community...and then attract some people with some passion around the idea. But I am somewhat of a pattern outsider (consumer, really) so don't know if there is much of a pattern community any more that could help.

10:53 AM  
Anonymous Scott Bellware said...

I think that Ward Cunningham was trying to achieve a patterns commons with PatternShare while he was at Microsoft:
http://patternshare.org/default.aspx/Home.HomePage

The site seems a bit dormant. I hope that the site won't be de-missioned. It's usually the first place I go for a quick reference of Eric Evans' Domain-Driven Design patterns when I'm not near the book.

9:51 PM  
Anonymous Anonymous said...

I thought this was the best discussion of the composite pattern on the web. Thank you!

The Hillside site is tedious to use. The results of a search are not retained; after visiting each "hit", a search must be re-submitted.

A colleague is trying to develop the type of repository you suggest with even more features. I will send him a link to this blog.

5:01 PM  
Anonymous Paul Oldfield said...

I had always assumed the patterns were never intended to be used strictly as-is. What they taught me was how to separate concerns (or at least, gave me a thorough revision of my practices to-date).

It is the individual context where one may want to separate out the concerns which determines how they ought to get separated. As such, it is probably sensible for any textbook to show them fully separated, then we get to choose whether or not to re-combine them.

5:24 AM  
Anonymous Anonymous said...

Well done!
[url=http://oxhhnmxf.com/seyv/ijtk.html]My homepage[/url] | [url=http://cvfqzcfe.com/exza/rsgl.html]Cool site[/url]

4:16 PM  
Anonymous Anonymous said...

Good design!
My homepage | Please visit

4:16 PM  
Anonymous Anonymous said...

Thank you!
http://oxhhnmxf.com/seyv/ijtk.html | http://hzsyoinl.com/izub/vvva.html

4:16 PM  
Anonymous Philipp Bachmann said...

Hello Rebecca,

thank you for this entry. I just read it that late primarily because my RSS reader seems to randomize your entries...

Last week I skimmed over Mary Lynn Mann's PhD thesis http://www.cs.unca.edu/~manns/FINALSubmittedforprinting.doc, and read with great interest especially her Chapter 2.7 - "Popular view of software patterns" -, that summarizes different views on patterns and on the GoF book. To me a central sentence was "In contrast to Alexander, the Gamma patterns do not contain the following: [...] an emphasis on the problem, rather than the solution" (p 34). Your blog entry reminded me of this, though you don't state this opinion.

Nevertheless I consider (even large) code examples important not because I thought they represented some kind of "reference code", but because they are just another way to understand the pattern at least in part. Different people need different media to learn best - some are more textual oriented, some more visually, and some are more code oriented.

Concerning text, code, and graphics the author is always faced with the decision of what's really important. Concerning the Composite pattern I consider the method(s) "operation()" far more important than the question of how to build the instance hierarchy and to navigate through it. So if "add()", "remove()", and "getChild()" would have been skipped in the class diagram, the description would have been less confusing than it seems to be.

Concerning your "PatternPedia" idea I'd like to point you to Lise Hvatum's presentation at PLoP 2006: She suggested http://cnx.org/ as a potential platform.

Best regards,
Philipp.

1:25 PM  

Post a Comment

<< Home