designPatterns10yearsLater Gamma2002

Download as pdf or txt
Download as pdf or txt
You are on page 1of 13

688

Design Patterns

Erich Gamma
Technical Director.
Object Technology International. Zurich
erich_gamma @oti.com
Doctorate in Informatics.
University of Zunch
Union Bank of Switzerland
Tahgent
Major contribution: design patterns
Current interests:
Java development tools. frameworks.
building large object-oriented systems

M. Broy et al. (eds.), Software Pioneers


© Springer-Verlag Berlin Heidelberg 2002
M Broy. E Oenert (Eds) Software Pioneers
Sprmger·Verlog Berlm Heidelberg 2002 689

Erich Gamma

Design Patterns - Ten Yea rs later

Design patterns have changed the way software developers design abJect-
oflented systems. Rather than rediscovering solutions to recurring design
problems over and over again, developers can now refer to a body of litera-
ture that captures THE best practices of system design. This article looks
back to where design patterns came from, shows design patterns in action,
and provides an overview of where patterns are today.

Some History

looking back, we can see that patterns came to us via two routes: the
pattern language route and the micro·archltecture route.

The pattern language route came first, thanks to Christopher Alexander,


author of several books on building architecture [2]. Alexander's goal was
to create architectures that improve quality of life. His theory begins by
identifymg what makes a bu ilding great: freedom. wholeness, completeness,
690 Erich Gamma

comfort, harmony, habitability, durabil ity, openness, resilience, variability,


and adaptability. But he concl udes that greatness lies in something even
more fundamental , someth ing he calls the "Quality Without a Name."

To Impart this quality systematically, Alexander and his colleagues develo-


ped a "pattern language" - aset of patterns that build on each other.
Each pattern captures a proven solution to a problem that arises dUring
design . Alexander characterizes them this way: " Each pattern describes a
problem which occurs over and over again in our environment and then
describes the core of the solution to that problem, In such a way that you
can use this solution a million times over, without ever doing It the same
way twice." A pattern language guides a designer's application of individu -
al patterns to the entire design .

Ward Cunningham and Kent Beck had Alexander's books on their shelves
long before they recognized the applicability of hiS Ideas to software. By
1987 they began introducing those ideas to the object-oriented program-
ming community [25) . Ward and Kent were successful in generating in-
terest in Alexander's ideas, but it all sounded rather theoretical to software
developers. What was lacking were concrete examples for software de-
velopment.

Coincidently, the micro-architecture route got started . I was In a doctoral


program working With Andre Weinand on ET++ [31], a framework for inter-
active graphical applications written In C++. You can't publish C++ code as
a dissertation, of course, so I planned to write about research Issues In
object-oriented design based on my experience With ET++.

As I reflected on ET ++, it became apparent that a mature framework con-


tains recurring deSign structures that give "frameworkers" warm and fuuy
feelings. These structures promote qualities like decoupllng, abstraction,
openness, and flexibility. They can be conSidered micro-architectures that
contribute to an overall system architecture. I ended up documenting a
dozen such micro-architectures In my thesis (13). This approach to patterns
differed from pattern languages: rather than coming up with a set of inter-
woven patterns top-down, micro-architectures constitute Isolated patterns
that eventually relate to each other bottom -up.

I "outed" my thesis work at an informal OOPSLA '90 session organized by


Bruce Anderson titled, "Towards an Architecture Handbook." Richard Helm
Immediately understood my intent, and we found that we had similar
ideas on good object-oriented deSign . This motivated us to meet for a day
In 1991 in Zurich Fueled by iJters of Ice tea, we came up with the idea of
a catalogue of design patterns. We wanted to move away from prose
towards a more structured format, which we hoped would make It easy to
compare, categorize, and finally catalogue the different patterns. We
ended up with a rough sketch of the pattern format and skeletal descrip·
tions of several patterns adhering to It
Design Patterns 691

We were not shy about showing our catalogue to people. Surprisingly, most
of the feedback we got from experts was along the lines of, "Oh, I've done
that " Such feedback encouraged us to continue, but we also realized that
we should leverage insights from some of these experts to move forward
faster.

As a first step, we Infected John Vlissldes with the idea John was a contri -
butor to InterViews (20], a C++ library that was popular at the time.
InterViews and ET++ were competitors, giving nse to debates over which
system's way of solving problems was best. A lesson of these diSCUSSions
was the Importance of documentmg not just one solution but multiple
alternatives, along with their trade-offs.

Around the same time, another contributor was making patterns more con-
crete. Jim Copl ien collected and published a catalogue of C++ "idioms" -
small-scale patterns applicable to a particular programming language [9] .
As useful as idioms are, though, one of our goals was language neutrality.
We did not want to limit ourselves to one language, no matter how popu -
lar; we wanted to capture problems and solutions that applied across
obJect-oriented languages.

To that end, we sought to broaden our group skills to include Smalltalk


expertise, and we eventually convinced Ralph Johnson to join us. Ralph
was particularly interested in using patterns to document frameworks (18).
The group, quickly dubbed "Gang of Four" or just "GoF" by onlookers, was
complete. Much as some of us disliked that moniker, it became a conven-
ient shorthand for the Internet-wide discussions that ensued.

A summary of the group's initial work was presented at ECOOP 114]. That
effort convinced us that we cou ldn't do justice to the to pic with anythmg
less than a book-length work. We also quickly learned that you can't get a
pattern right the first time. It took us more than two years and several
rewrites, requiring over 2000 sometimes-heated e-mail exchanges, to ar-
rive at the catalog of 23 patterns we finally published 115].

While we GoF worked on our patterns, Kent Beck began forming the
Hillside Group, which was instrumental in the pattern community's forma-
tion . In particular, Hillside was the catalyst for the various Partern lan-
guages of Programs (PloP) conferences. The PloP charter was to create
a new literature of what is explicitly not new, but works in practice. The
centerpiece of a PloP conference is its Writers' Workshops. Instead of one
or more authors presentmg their work to a large audience, they listen
silently as a small group discusses each pattern and debates its strengths
and weaknesses. The products of PloPs are carefully reviewed and revised
patterns [10, 16, 21 , 30] from many different domainS.

Several other pattern books appeared around the time of the first few
PlOPs, and they did much to popularize patterns. Examples include Pattern-
Oriented Software Architecture 17], Smalltalk Best Practice Patterns [5], or
the semmal work on analysis patterns (11)
692 Erich Comma

This short history would be Incomplete without mention of the GoFs 1999
indictment by the International Tribunal for the Prosecution of Crtmes
Against Computer Science for crimes too numerous to Itst here [28]. A
show trial held at OQPSLA that yea r had a predictable outcome, though
only one of the defendants received a Jail sentence. He subsequently es-
caped and remains at large.

Conceptions and Misconceptions


The popularity of design patterns has given rise to many different opinions
about what they are and how they should be wrttten . Iwon't try to come
up with the ultimate definition here. Iwill focus instead on conceptions
and misconceptions about patterns.

A design pattern has three key characteristics:

1. It promotes design reuse and provides guidance. The whole point of


a pattern is to reuse, rather than reinvent, someone else's successful
design . It represents a bite-sized chunk of engineering knowledge.
A pattern can help you ask the right questions at the right time. In par-
ticular, it can help you avoid obvious but flawed solutions.
2. It conforms to a literary style. A pattern articulates design deCISions, dis-
cusses their trade-offs, and provides implementation hints using a speci-
fic style of presentation . Many different pattern styles are in use today
3 . Together, they define a vocabulary for discussing design. DeSigners
can use pattern names to communicate concisely. They can deSign at
a higher level of abstraction.

The following, meanwhile, are misconceptions:

• A pattern is a Unified Modelmg Language (UML) diagram with a nome.


Name aSide, the most memorable part of a deSign pattern is its struc-
ture diagram. But It IS wrong to reduce a pattern to a diagram. A
pattern Will have variations that one diagram can't capture. So while
the diagram IS important, equally Important IS a pattern's discussion
of trade-offs, variant Implementations, and examples.
• Patterns make software more reusable. Design patterns are the fruit of
studYing reusable object-oriented software. But just because a system
was designed using patterns doesn't necessarily mean it's reusable.
As a matter of fact. the same is true of object-oriented programming:
objects merely enable reuse; they don't guarantee it.
• The more patterns, the better the system. Patterns make it easy to make
a system complex. They achieve flexibility and variability by introducing
levels of indirection. which can complicate a design. It's better to start
simple and evolve a design as needed. This is in contrast to the over-
enthusiasm evident in the following quote from a newsgroup: "In thiS
project I tried to use all the GoF patterns, but I was able to use only 21
of them "
Design Patterns 693

• A pattern is a new way of solving a problem. A pattern never suggests


a new way to solve a problem; it's necessarily a proven solution found In
existing systems. Experienced designers shouldn't be surprised by a
pattern. The rule we followed In our catalogue was that unless we could
poi nt to at least two uses In eXisting systems, we didn't conSider It a
pattern. The fact that a pattern IS a proven solution lends confidence
when It is applied, since others arrived at the same solution.
• DesIgn patterns afe all you need to know Today there IS a wide range of
pattern domains and styles. To understand the full breadth of patterns,
you have to learn more than Just our own The Patterns Home Page [26]
is a good starting pOint for pattern -related material.

Frameworks
Design patterns have their roots In object-oriented frameworks A frame -
work is a set of customlzable, cooperating classes that Implements a reusa -
ble solution to a given problem. To make a framework reusable, It'S Impera-
tive to design -in flexibility and extensibility. Frameworks are therefore
design-dense, making them a rich source of design solutions. Many pattern
authors have experience In framework development.

When we wrote Design Patterns, we were excited abo ut frameworks and


forecast that there would be lots of them In the near future. Time has
shown, however, that frameworks aren't for everyone. Developing a good
framework IS hard and requires a large up-front Investment that doesn't
always payoff. It ISnot uncommon for a framework to be deemed a success
on the supplier Side, only to produce frustration ("frameworkltis") on the
consumer Side thanks to a steep learning curve. Iwas actively Involved 10
one such framework [29], and so I know what I'm talking about. But this is
not a diatribe agamst frameworks; If you have a f ramework that matches
your problem, then by all means use It. However, be careful when
developing a new framework, even if you know all about patterns.

DeSign patterns are interesting 10 this context because they let you app ly
inSights garned 10 framework deSign to day-to-day application develop-
ment. Design patterns are more abstract than frameworks; they are mainly
prose descnptlons with few opportunities for code reuse. As a consequence,
patterns are highly "portable" and can be adapted and tweaked when
they are applied. Patterns are also smaller architectural building blocks
than frameworks. You can comb1Oe them 10 myriad ways.

Mature frameworks use many patterns. The same Isn't typically true
of applications, because they do not require the flexibility of a framework.
An application's pattern density is generally lower than a framework's.
694 Erich Gamma

Design Patterns in Action


The best way to understand design patterns IS by seeing them In action.
The example I'll use IS the Java JUnit testing framework [27]. JUnit sup-
ports writing and running tests. At the press of a button, the developer can
run a collection of tests to gain confidence In the current state of develop·
ment. I had the pleasure of pair-programming JUOIt with Kent Beck. JUnit
is a compel ling example - simple, yet with several patterns working
together in a handful of classes.

Modeling Tests

Let's examine the design of modeling tests using patterns as a guide. First
we need an abstraction for the tests themselves. JUnit should be able to
run a test without knowing any details about it. Scanning through our
patterns' intents, we encounter this one: "Encapsulate a request as an
object, thereby letting you parameterize clients with different requests,
queue or log requests, and support undoable operations." That's the Intent
of the Command pattern. While we're not particularly Interested In the
undo aspect, the idea of representing a "run test" request as an object
will effectively hide details of the test from JUnit - and make the tests
extensible as well.

We apply the Command pattern by introducing a TestCase class with a


single method, run. Figu re 1 illustrates the result of this first design step.

TestCase

run()

Fig. 1. Applying Command

We use UML class diagrams to show snapshots of our design as it evolves.


We annotate the UML with shaded boxes identifying the pattern being
applied .

Breaking Down run

At thiS stage, implementing a test reqUires subclasslng TestCase and over-


riding the run method. We can do better - once we observe that the execu-
tion of a test has a common structure: fi rst the test setup is created, then
the test IS run, and finally the test setup IS cleaned-up. The framework can
codify thiS common structure.

The Template Method pattern can do just that. Its intent is to, "Define the
skeleton of an algorithm 10 an operation, deferring some steps to subclas-
ses. Template Method lets subclasses redefine certain steps of an algorithm
without changing the algorithm's structure." The pattern shows us how to
turn ru n into a template method made up of primitive methods setUp,
runTest, and t earDown. Figure 2 shows the result
Design Patterns 695

TestCase

runO Template Method


run Test()
setUp()
tearDown()

Fig. 2.Applying Template Method

Modeling Test Suites

The next design problem has to do with how JUnit supports suites of tests.
Tests should be composable with other tests for two reasons. First. you
might want to test scattered modifications all at once. Second. you might
want to combine your tests with those of other developers.

Composite is a powerful pattern for assembling objects. Its intent reads,


uCompose objects into tree structures to represent part-whole hierarchies.
Composite lets clients treat individual objects and compositions of objects
uniformly." To that end, we introduce TestSuite, a composite class for
assembling tests.

The power of the Composite pattern stems from the conformance of the
TestSuite and TestCase interfaces - a TestSuite is a TestCase. How you
express this conformance depends on your programming language. In Java,
you introduce a common interface; in Smalltalk, you simply define the
same method selectors.

This conformance lets you assemble TestSUIte objects recu rsively to form
larger suites. In other words, clients no longer have to distinguish between
a single test and many tests. Figure 3 illustrates the Introduction of
Composite.

Test Composite :Component

run(TestResult)
,j '.
r-------·--------,
I
I

I
I I

TestCas e TestSuite
Composite: Leaf
run(TeslResull) run(TesIResult) fTests
addTest(Test)

Fig. 3. Applymg Composite


696 Erich Gamma

Collecting Test Results

At the end of the day, you run tests to see whether they succeed or fall.
xecuting tests. Smal/talk Best
To do that, we need to collect the results o f e
Practice Patterns [5] has a pattern called »Collectlng Parameter"
for t his purpose. When you need to collect results over several methods, the
pattern suggests adding a parameter to each method and passing In an
object In which to hold the results. In our design, then, we create a new
object, TestResult, that holds the results of running tests (Figure 4) .

Test.Case

TestResult run(TestResult)
run Test()
Collecting Parameter setUp()
tearDown()

Fig. 4. Applying Col/ecting Parameter

Cutting Down on Classes

Our design is coming along nicely, but the framewo rk remains harder
to use than It could be. Developers must create a new subclass of TestCase
for every test. Loads of classes, each im plementing a lone method, are a
maintenance burden .

We can always put multiple tests into the class to reduce subclassing. But
we still have a problem: JUnit offers just one method, runTest, for carrying
out a test.

The Adapter pattern comes in handy here. Its intent is to "convert the
interface of a class into another interface." Of particular interest IS an
implementation variation called pluggable adapters. A pluggable adapter
builds interface adaptation into a class. The aspect we want to make plug-
gable IS the test method that TestCase executes.

Test Composite:Component
run(TestResuJI)
I'
j-
I
r- - -----~--------,
I I

TestCase TestSuite

run(TestResult) run(TestResult) fTests


run Test() addTest(Test)
setUp{)
tearDown() ComposIte: Leaf

Colloctlng Parameter (Name Pluggable Adapter

FIg. 5. Framework summary


Design Patterns 697

Accordingly, JUnit lets you specify a test method name when creating
a TestCase. The runTest method can then Invoke that method uSing Java
reflectIOn Figure 5 Illustrates the final design of the JUnit framework.

Postmortem

Some observations are in order on our use of design patterns in this


example:

• Design patterns provide a vocabulary for communicating design con·


cisely. A reader can immediately understand a design problem, ItS solu -
tions, and the consequences thereof by referring to a pattern .
• Patterns work In teams. Note how TestCase, the central abstraction in
the framework, embodies four patterns. Pictures of mature object
designs show similar "pattern density." As another example, conSider a
diagram (Figure 6) showing the key classes In Java's AWT toolkit [17],
annotated with patterns.
Abstrlct Faclory Client

Brrdye AblMilc:lIolI

Compoalle Compo l1 unl

Observor SubJec.t

ICompaQ. nlPH' ~ Compan.ttI I. - -

· ..L
Bridge Implf!'mfl' nlo1l1on

A bst rac t Factory Producl


" .

"'!b@i'AM4 ~
~

Fig. 6. The Java AWT toolkit

• Patterns speed up your understanding of a design. They make design


motives and elements explicit. In particular, patterns help you under-
stand how classes relate and interact Since you understand the
designer's intent better and faster, you're less likely to struggle with
the design itself.

Design Patterns Today


The patterns literature has expanded greatly In the past few years.
Published patterns and pattern languages cover a wide range of domainS.
Many contributions come from the PLoP conferences held throughout
the world. In fact, the ever-growing body of patterns is increasingly difficult
to manage

This IS a good problem to have, as It attests to patterns' popularity. But


at the same time, the pattern community must work to bring structure
to the morass. A good first step In this direction IS The Pattern Almanac
[23], an Index and cross-reference of most of the patterns published
through 1999.
698 Erich Gamma

It takes time, but design patterns eventually emerge from challenging new
problem domains where design expertise is especially appreciated. For
example, concurrent programming has many degrees of freedom beyond
conventional sequential programming. This relatively new and complicat-
ed problem domain is already covered by patterns for concurrent Java pro-
gramming [19] and for programming networked objects (24). Another
recent example is the work on J2EE patterns for Java enterprise applica-
tion development [1] . You can expect this trend to continue and new
pattern catalogs to be developed as new technologies emerge.

Many people have reported anecdotal success with patterns in various


domains [4]. Quantitative results from controlled experiments tend to back
them up [22]. They have corroborated, for example, that documenting the
patterns in a system does indeed make the system easier to understand.

Patterns are now used to teach software design and programming at many
universities. They have found their way into the APls of today's software
platforms, most notably Java and .NET. (Figure 6 depicts an example from
the Java platform .)

Meanwhile. design notations and case tools have incorporated pattern sup-
port. UML [8] can document the structural aspects of design patterns with
so-called parameterized collaborations. Whenever a pattern is applied,
actual classes are substituted for parameters in a corresponding pattern
definition. But such diagrams cover on ly the structural aspects of a pattern:
its most important parts - the trade-ofts. implementation hints. and exam -
ples - have to be documented in text as before.

Finally. there's the relationship between Extreme Programming (XP) [6]


and design patterns. The XP methodology balks at some cherished atti-
tudes of software development. In particular, It de·emphasizes up-front
design in favor of evolutionary design. In evolutionary design. you start
with the simplest design that could possibly work and continually evolve it
through refactoring [12] . Patterns are about building flexibility IOto a
design up front. So the question IS. can design patterns be Ignored in XP?

It's true that pattern over-enthusiasm is In strong conflict with XP practICes.


However. XP emphasizes refactoring to improve a system's design. and
that's where patterns come into play. Design patterns serve as targets for
refactoring: they show you how to Improve existing code. particularly
how to make it simpler. For example, the State and Strategy patterns show
you how to transform conditional code into polymorphic code.

Given the centrality of refactoring 10 XP. I have no doubt that patterns


belong in an XP developer's skill set. By the way. as Kent (the father of XP)
and I pair-programmed JUnit, the pattern names I've mentioned peppered
our conversation as we coded along.
Design Patterns 699

Conclusion
Design patterns have been successful and influential because they tackle
design problems In a way many developers can appreciate. Here are my
nominees for the four biggest benefits of deSign patterns

• They accelerate discourse by providing a vocabulary for deSign


• They let you repeat successful deSigns rather than rediscover them
• As targets for refactonng, they show you how to Improve an eXisting
system
• A system that documents Its patterns IS easier to understand than
one that doesn't.

Design patterns are tools, not rules Applying a pattern Involves tweaking
and adapting it to your needs. You can't turn off your brain when you
use patterns. You have to choose them Wisely and then decide how to use
them or - perhaps more importantly - how not to.

The most powerful patterns are the ones you've Internalized, and they're
not easy to come by. You can't absorb patterns solely by reading a book
or by attending a course. Unless you have experienced a deSign problem
firsthand, you cannot appreciate the solution a pattern deSCrIbes.

Acknowledgements
Thanks to John Vlissi des for carefully reading and many suggesting
corrections to improve the readability of this article.

References
(II Oeepak. A. J Crupi. 0 Malks. Core J2EE Patterns: Best Pracllces and DeSign Strategies
Prentice Hall. 2001
121 Alexander, C.. S Ishikawa, M.SllverstelO. et al. A Pattern language. Oxford University
Press. New York 1977
[3] Alexander, C The Timeless Way of Building Oxford University Press. New York, 1979
[41 Beck, K , J 0 Coplten. R. Crocker. et al. industrial expellence With deSign patterns
Proceed lOgs of the 1Bth International Conference on Software Engineering (pp 103· 114).
Berltn. Germany, March 1996.
[5J Beck, K Smalltalk Best Practice Patterns PrentICe Hall. 1996
16) Beck, K. Extreme ProgrammlOg ExplalOed' Embrace Change. Addlson·Wesley. ReadlOg.
MA, 1999
[71 Buschmann, F. R, Menunter, H, Rohnert, M.Stal Pattern·Orlented Software Architecture ·
A System of Patterns Wiley, ChIChester. England. 1996
181 Booch. G, I Jacobson. J, Rumbaugh The Untfled Modeling Language User GUide
Addlson ·We~ley,ReadlOg, MA, 1998,
[91 Cophen, J Advanced CH Programming Styles and Idioms. AddlsonWesley. ReadlOg. MA.
1992
[IOJ Cophen. )O . D.C. Schmidt (Eds.) Pattern Languages of Program DeSign.
Add lsonWesley (Software Patterns Selles), ReadlOg, MA. 1995
700 Erich Gamma

[111 Fowler, M,Analy~i~ Patterns Reu~ble Object Models AddlsonWesley, Readmg. MA,
1997,
[12) Fowler, M .Refactormg ; Improvmg the DeSign of EXlsllng Code. Addlson .Wesley, Reading .
MA, 1999
[13[ Gamma E ObJec\·Ollenled Software Development Based on ET ++' DeSign Patterns, Clas~
library, Tools (In German) Doctoral thesIs, University of ZUllch, Insmut fur Informalik,
1991
[14] Gamma E, R.Helm, R Helm, R Johnson. and J Vllssldes. DeSign Patterns' Abstraction
and Reuse of ObJect-Onented DeSig n ECOOP '93, lecture Notes In Computer SCience 707
Springer, Berlin Heidelberg New York, p.406 If.
[IS) Gamma, E, RHelm, R Johnson, J.Vlissldes. DeSign Patterns. Elements of Reu~ble
ObJect·Onented Software. Addlson .Wesley, Reading, MA, 1995
[16] Harrison, N., Bfoote, H Rohnert (Eds.) Pattern Languages of Program DeSign 4 Addison -
Wesley (Software Patterns Serres), Reading. MA, 2000
117) JavaSolt, In t. Java Development Kit Mountam View. CA, 1997
[18[ Johnson, R.Documenting Frameworks USing Patterns In Proc. OOPSLA '92, pages 63 ·76.
Vancouver BC, Oct 1992.
[19[ Lea, D.Concurrent Programmmg in Java, DeSign Prmciples and Patterns, 2nd edition.
Addlson ·Wesley, Reading , MA, 1999
[201 linton, M ..J Vhssldes, and P Calder. Composmg User Interlaces With InterViews.
Computer 22(2)8-22, 1989
(21 [ Martin. R. 0 Riehle, and F. Buschmann (Eds). Pattern Languages of Program DeSign 3.
AddlsonWesley, Reading, MA, 1998.
[22) Prechelt. L An experiment on the usefulness of deSign patterns: Detailed deSCription and
evaluation. Technical Report 9/ 1997, University of Karlsruhe. Germany, June 1997
123) Rising. L The Pattern Almanac 2000 Addison -Wesley, Reading, MA, 2000.
[24) Schmidt. D.• M. Stal, H Rohnert. F Buschmann . Pattern-Onented Software Architecture ·
Pattern~ for Concurrent and Networked Objects Wiley and Sons Ltd., Chichester. England.
2000
[25) http;//c2 .com/dot./oopsla87 html
[261 http.!lhlllslde.net/patterns
[27) http.!/www.Junrtorg
(28) http.!Iwww.acm.org/sigplan/oopsla/oopsla99/2_ap/tech/2dla_gang.htm.
(29) Cotter, S, M. Potel. InSide Tallgent Technology
Add,sonWesley, Readmg, MA, 1995.
(30) Vhssldes, J, J Cophen, and N. Kerth (Eds.) Pattern Languages of Program Design 2.
Addison-We5Iey, Readmg, MA, 1996.
[31] Wemand. A., E Gamma. and R. Marty. ET ++- An object-oriented application framework 10
C++. In Object-Oriented Progra mmmg Systems, Language5, and Applications Conferenr;e
Proceed lOgS, pages 46-57, San Diego, CA. ACM Press. 1988

You might also like