![]()
Coding PatternsJames O. Coplien, Bell LabsC++ Report 8(9), October 1996, pp. 18 - 25 1. IntroductionPLoP was founded to create a new literature. That implies that the founders were somehow dissatisfied with the existing literature, which is true. ([Vlissides+96], p. vii)So starts the Introduction in the Pattern Languages of Program Design books, an attempt to gently warn the reader to expect the unexpected. Patterns are a clear detour from the corporate software engineering themes of the 1990s: automatic code generation, increased axiomatic formalization, etc. Patterns at last provided a perspective that tempered mathematical rigor with aesthetics, myopic object-oriented design with a system view, technocentricity with ethnocentricity. I've watched two worrisome schools of thought grow over the past year. The first school of thought attempts to automate pattern-based design, at least in degrees. Automation has become one of the recent Holy Grails of computer science. The second school of thought attempts to formalize patterns. Both of these are throwbacks to the "existing literature" with which early pattern advocates were dissatisfied. It isn't that these trends are unexpected; I addressed them at length at the Borland International Conference back in June 1994 [Stevens94]. If you understand why patterns are different, you might worry that moves to formalize patterns will encourage people to conveniently dodge the integrative, generative, and human aspects of patterns that contribute to the Quality Without a Name. That is, formal methods try to give a name (and numbers) to the Quality. Yet, in computer science, we automate what we can. Automation and patterns are clearly linked: what were the patterns of assembly language programming for me 23 years ago have been automated by contemporary compilers, and that's a good thing. In this column, I'll try to distinguish the design ideas I feel are good pattern fodder from those better suited to automation and formalization. The dichotomy recalls the discussions of the past two Columns Without a Name, which addressed efficiency. Programming tasks related to efficiency, including memory management, often beg more insight than can be automated. This article starts with a review (good for those of you who came in late, anyhow) of the distinctive properties of good patterns. I'll then look at some recent literature and research postings that advocate code generation from patterns or formalization of patterns, and try to argue why each belongs outside the pattern discipline. 2. Why Patterns Are Different than other design disciplinesThe pattern community started with a concerted effort to define what Alexander's patterns portended for software. Like other architects, Alexander uses the term "pattern" in a different sense than is found in common English usage; it is this architectural sense that was taken up by early pattern advocates, and which has taken root in software. Much--perhaps most--of Alexander's foundational material relates to humanistic and social concerns, not technical concerns. These are in large part what distinguish patterns from other design disciplines:Patterns solve problems: Many design methods strive to uncover the structure of a system; most focus on the structure of the solution. Those that focus on the problem structure use the word "problem" only in the loosest sense. Patterns are explicit about the problems they solve, and about the solutions they provide. A pattern may attack a problem that is abstractly stated, but "abstract" never means "vague." Patterns are generative: Most problem-solving techniques pair problems with solutions. In complex systems like software programs, the problem and solution are often not close in time and space. That makes it difficult to methodically hunt down solutions on demand. But insight, cleverness, or luck uncovers such solutions over time. Patterns chronicle such solutions. Alexander said, This quality in buildings and in towns cannot be made, but only generated, indirectly, by the ordinary actions of the people, just as a flower cannot be made, but only generated from the seed. ([Alexander79], p. xi)We should leave non-generative solutions in the able hands of formal methods people. By the time technology or understanding matures to the point where we can formally capture an idea, it often loses the generative, literary quality that sets patterns apart from other methods. Neil Harrison suggested to me that we call this "The Name without a Quality." Patterns build on experience: Most design methods create new structures from first principles; while the principles are well-known, their application to a given context isn't proven, and the resulting structure may be entirely novel, and perhaps unsuitable to the problem at hand. It takes insight to apply a method to a problem; in fact, it takes insight to choose the right method. Patterns encode experience by documenting proven structures, and how they relate both to the underlying principles and to the problem at hand. They convey not only the solution, but the insight behind it. So patterns both build on the experience of those who refined the idea over time, and on the experience of those who insightfully apply the pattern to a given situation. Patterns focus on aesthetics and human comfort: Most design methods focus on the needs of the computer, or on principles like coupling and cohesion. However, the computer doesn't "care" about its coupling and cohesion, and most design methods don't make it clear how their mandates improve the quality of life. Good patterns tell how humans benefit from their application. Richard Gabriel says: We are trying to bring people and humanity into the software design and development process. I think this is the goal because it's the key Alexandrian idea. If you look at his patterns, each or nearly all talk about the context and forces in terms of what people need to do to live fully and to be fully alive... (Personal communication with Richard Gabriel, April, 1995) Dick wrote a simple example of a software pattern with strong human overtones, called Simply Understood Code [Coplien95a]. Patterns address the "orthogonal" dimensions of design: Object-oriented design produces classes. The object paradigm is a good decomposition and abstraction technique, but it is weak for integration. Good patterns cut across the modular parts of design and address the important constructs of system structure. Alexander says: Design is often thought of as a process of synthesis, a process of putting together things, a process of combination. According to this view, a whole is created by putting together parts. The parts come first; the form of the whole comes second. But it is impossible to form anything which has the character of nature by adding preformed parts. When parts are modular and made before the whole, by definition then, they are identical, and it is impossible for every part to be unique, according to its position in the whole. ([Alexander79], p. 368) 3. Code Generation Examples3.1 SNIPAs discussed above, the word pattern takes on a rich and culturally sensitive meaning in the software discipline that bears its name. Many contemporary papers that propose pattern automation equate patterns with templates. An old associate of mine, Fred Wild, recently published an article in Dr. Dobb's Journal entitle "Instantiating Code Patterns" [Wild96], that I regard as falling into this category. While the SNIP paper isn't alone in that regard (one finds many of these on the Web: see http://sys3.cs.usu.edu/students/RaghuKrishnaswamy/OSMTemplates.html[1]), it did enjoy broader publication than most of its academic counterparts.Fred and I have had several occasions to interact over the years, largely in OOPSLA forums where we worked together. He's a bright guy and a fun guy to know. But that doesn't mean we agree on all matters technical. In his article, Fred distinguishes design patterns, which he views as logical, from code patterns, which he views as physical. Code patterns focus on "how a particular structure or sequence of action is accomplished using the specific mechanisms of a programming language." Most of the pattern community calls these idioms (see, for example, Buschmann's taxonomy [Buschman+96]). What is a code pattern? Fred defines code patterns in terms of rules. For example, he defines a wrapped pointer pattern in terms of rules like these:
He captures these rules in what he calls SNIP template files. He uses an example based on pets and owners:
There is also a SNIP specification that describes how to expand such classes into C++ code (Figure 1).
I know that Fred calls these code patterns, to distinguish them from design patterns--but let's reflect on whether they should be patterns at all. If these are patterns, then what is not a pattern? Remember what makes patterns different:
Automatic code generation takes fine-tuning out of the
designer's hands, and puts it in a tool where it is not
only difficult to change, but where the design suffers from
"out of sight out of mind" problems. Take, for example,
SNIP's generation of
Should I change Fred's template to declare
operator= as a const
function? Should I duplicate the template and have one
that's the same in every respect, expect for the
const modifier? If so, how do I share the
common parts of the specifications?
Isn't it better just to let the programmer decide the
right way to implement I'd be more excited about SNIP if coding were the dominant problem of software development, but it's rarely more than 5% or 10% of software cost. If you optimized it completely away, a large project may never notice the productivity difference. Furthermore, most insightful implementations of counted pointers require case-by-case insight if the resulting code is to be robust and efficient (see the previous two installations of this column). And, if you want a general implementation of reference-counted pointers, why not just use a template instead of buying a tool empire?
3.2 The GOF ConnectionThe allure of code automation reaches all the way to some of the authors of the Design Patterns book. In the IBM Technical Journal, we find an article [Budinsky+96] by Budinsky, Finnie, Vlissides (yup--my buddy who alternates pattern columns with me) and Yu that describes another tool to automatically generate code from the design patterns.The article starts off well enough, emphasizing the importance of understanding and a rationale. It emphasizes that "design patterns are not code; they must be implemented each time they are applied." This is an encouraging perspective, but let's read on. The authors point out that because a pattern can be implemented in so many different ways, you can't capture its code in a closed, reusable form. They bemoan the plight of those who can't make the leap from pattern to code (I'm puzzled, because the Design Patterns contain code examples) or who find the translation tedious. I don't fully understand why the translation is tedious, particularly if the pattern is varied each time it's applied. But sometimes the implementation is the same again and again; the tool described in the article wants to capture that code and reuse it. The user can still parameterize the code to some degree, but the basic structure is fixed. But this isn't patterns any more, because the implementation of a true pattern is never the same way twice though it may be applied a million times. So, these things aren't patterns! They are parameterized high-level coding building blocks! [Coplien96b] Someone should just organize the common code and let the user parameterize it to suit the application at hand, and dismiss the creative baggage of patterns. Indeed, it would appear that that is what Budinsky et al. have done. Yet this work can't be totally divorced from patterns, since each of these "building blocks" benefits from some very thorough documentation that describes how these "building blocks" work. This documentation (major chunks of the GOF book) is integrated with the tool. These building blocks form a language, much as programming language constructs define a programming language. (It is not a pattern language, for lots of reasons, the most mundane of which being that it does not comprise patterns.) This leads to an important conclusion: what constitutes a pattern in one language may be a natural part of another. For example, the counted handle/body idiom is a common C++ pattern, yet its semantics (if not its implementation) is in the base semantics of Smalltalk. We lose some of the generality of a pattern by codifying it as a parameterized building block, since any codification can express only so many of the million or so ways a genuine pattern can unfold. (Here's an exercise: build a general-purpose counted pointer class using C++ templates.) But, sometimes, such constraints can be useful. In conclusion, the IBM Systems Journal article is not about patterns. It's not so much about raising the level of design thinking--after all, the authors target those people who can't think their way to the code from a pattern, and those who don't have to think as they re-type the same code again and again. It's about raising the level of coding. That's not as powerful as patterns, in my opinion, but it's not a bad thing. 4. A Formalism ExampleLook at Figure 2. It purports to be a pattern--or, really, a formal description of one. Would you know how to use it?This example comes from some work in formal specifications (Abstract Data Views, or ADVs) work at the University of Waterloo (http://csg.uwaterloo.ca/patterns.html). It is like the code automation work many ways. Though formal, it specifies an explicit and specific implementation structure (that depends on inheritance, for example, though the pattern can be implemented in languages without inheritance). They have a Designer's Assistant tool that reduces ADVs to code, by "assembling components at both the design and architectural levels." Maybe it's a good thing to automate software design, but I'd like to leave patterns out of it. Alexander was very explicit about not thinking of buildings as collections of components. In more recent work, he has again raised the important issue of aesthetics: I was no longer willing to start looking at any pattern unless it presented itself to me as having the capacity to connect up with some part of this quality [the quality without a name]. Unless a particular pattern actually was capable of generating the kind of life and spirit that we are now discussing, and that it had this quality itself, my tendency was to dismiss it, even though we explored many, many patterns. [Grabow83]
I've noticed a growing trend in academia to combine formalism and patterns, probably becaue patterns are current and relevant, and because formalism is the hallmark of academic accomplishment. It isn't that formalism itself is bad. Patterns (as works of literature) are formal in that they have an "essential construction or structure" or "following or according with established form, custom or rule." They are not formal in the common academic sense: "characterized by punctilious respect for form" or "rigidly ceremonious" or (perhaps best) "having the appearance without substance."[Webster63] Pattern formalism, like that of poetry, helps focus the writer (and reader) beyond the superficial and unimportant issues of form, to meaning and significance. Significance touches us deeply, eliciting a response of recognition, understanding, and emotion. Apart from the dictionary definitions of formal--which loom almost whimsical in this context--it's important to point out that the term has at least two meanings in academic disciplines. Early use of the word formal is close to the original dictionary definition: "having form." I'm told by Mark Ardis, my local formal methods guy, that the common academic sense of formal is: Formal methods used in development computer systems are mathematically based techniques for describing sytem properties. [Wing90] In essence, a formal method is a mathematically based technique for describing a system. [Bowen95]Mark goes on to say that "the point is that formalism implies using mathematics, especially in providing semantics to a description. It used to be that formal syntax was considered formalisation, but that is no longer true." The Waterloo material is syntactically formal, but lacks formal semantics--many would not even consider it formal. Semantic formalism might have its place, perhaps in the pattern rationale, as a way to develop a deeper understanding of the pattern. At this writing, most such formalisms aren't terribly accessible to most of the audiences we must reach. To make them effective, maybe we'd have to follow the advice of many formal methods people, and teach more formal methods in undergraduate curricula. On the other hand, maybe we could teach more PhDs to program. The Waterloo work doesn't look like the patterns we usually write in the software pattern discipline, but it may not rise to the academic standards of semantic formalism. One goal of the ADV work is to build a pattern taxonomy, building an n-space around the components of the pattern form (context, problem, solution, etc.) I know we need all the help we can get in organizing patterns--with over 80 papers at the most recent PLoP, we're going to need some help sorting them out. I'm still concerned: it looks like formal clothing for constructs that should appeal to something deeper within us; the formalism really doesn't account for the forces Alexander held to be central to design. It doesn't capture the many-to-many mappings of the problem space to the solution space, nor the intricate relationship between the patterns of a pattern language. I've been enjoying dialogue with these folks and hope to meet with them in person soon. They do have some insights into pattern organization, an area where the pattern discipline still seems to be sorely lacking. I'm hoping we can learn much from each other. I'll keep you informed. 5. SummaryAutomatic code generation can't address most of the interesting problems of design, and we don't want to raise false hopes that it can or might. It won't replace patterns, since patterns will always be able to express broader designs than can be captured in code, and will always help motivate the applicability, rationale, and trade-offs of a given solution to a problem in a context.For example, consider the patterns of the past two Columns Without a Name, which addressed efficiency. A few of them are structural and could be automated. But many of the patterns would be difficult to codify formally, or to automate with a case tool. This structure-versus-other dichotomy is an important distinguishing factor, one that may distinguish the true (or at least, important) patterns from straightforward design (see [Coplien96b]). It worries me that one might justify these techniques by claiming a definition for the word pattern other than that which has adopted common usage in the pattern community. Most words in our profession are culturally sensitive: we've seen here that formal, as we use it, defies the dictionary sense. Even common (in our discipline) words like polymorphism defy their dictionary sense. Try to capture what object means from Webster. The same is true for the term pattern. To quote Doug Lea: It is a good idea to develop and/or apply formalisms to better capture descriptions of micro-architectures, protocols, policies, and idiomatic constructions. (I've been doing this a bit myself lately, constructing notations for expressing dynamics of open distributed object systems.) It's also a good idea to develop tools (especially scripting languages) to make them easier to apply.The pattern community should be careful to separate patterns from the code whose automation they support. To call the generated code "patterns" leads to the confusion this column attempts to defuse. The Budinsky paper in particular might have made that more clear. Yet, the pattern community should also cultivate tolerance for "pattern automation" and "pattern formalism." Some (but not all) of today's patterns will be tomorrow's generated code, and pattern advocates shouldn't embrace the value system of the Quality Without a Name so strongly that they are left behind. Thanks to Richard Helm, Doug Lea, Neil Harrison, Lizette Velazquez, and Dave Weiss for comments on this paper, to Raghu Krishnaswamy for interesting dialogue, and many thanks to Fred for his response. Footnotes[1] This proposal is evolving. I spent some pleasant time on the phone with Raghu, who pointed out that his work has evolved beyond the material on the web page to something that is intermediate to object-oriented design and patterns. You can see his work as a poster at OOPSLA '96. The work looks promising.References[Alexander79] Alexander, Christopher. The Timeless Way of Building. New York: Oxford University Press, 1979. [Buschman+96] Buschmann, Frank, and Regine Meunier. A System of Patterns. In [Coplien+95], pp. 330-331. [Budinsky+96] Budinsky, F. J, M. A. Finnie, J. M. Vlissides, and S. Yu.. "Automatic Code Generation from Design Patterns." IBM Technical Journal 35(2), 1996. See http://www.almaden.ibm.com/journal/sj/budin/budinsky.html. [Bowen95] Bowen, J. P. and Hinchey, M. G., IEEE Software 12(4), July 1995, p. 34. [Coplien95a] Coplien, J. O. The Column Without a Name: Software Development as Science, Art and Engineering. C++ Report 7(6), May, 1996. [Coplien+95] Coplien, J. O., and D. Schmidt, eds. Pattern Languages of Program Design. Reading, MA: Addison-Wesley, 1995. [Coplien96] Coplien, J. O. The Column Without a Name: After All, we Can't Ignore Efficiency. C++ Report 8(5), May, 1996. [Coplien96b] Coplien, J. O. The Column Without a Name: A professional dilemma. C++ Report 8(3), March, 1996. [Cargill96] Cargill, Thomas A. "Localized Ownership: Managing Dynamic Objects in C++." In [Vlissides+96], pp. 5-18. [Grabow83] Grabow, Stephen. Christopher Alexander: The Search for a New Paradigm in Architecture. Stocksfield, UK: Oriel Press, 1983. [Lea95] Lea, Doug. Mail correspondence of 11 March 1995. http://iamwww.unibe.ch/~fcglib/WWW/OnlineDoku/archive/DesignPatterns/0513.html [Stevens94] Stevens, Al. C Programming. In Dr. Dobb's Journal, September, 1994. [Vlissides+96] Vlissides, John, James O. Coplien, and Norm Kerth, eds. Pattern Languages of Program Design - 2. Reading, MA: Addison-Wesley, )1996. [Webster63] Webster's 7th Collegiate Dictionary, 1963. [Wild96] Wild, Fred. Instantiating Code Patterns. In Dr. Dobb's Journal, June, 1996. [Wing90] Wing, J. M., IEEE Computer 23(9), September 1990, p. 8. |
