generative design patterns - university of albertajonathan/previous/papers/papers/...generative...

12
Generative Design Patterns S. MacDonald, D. Szafron, J. Schaeffer, J. Anvik, S. Bromling and K. Tan Department of Computing Science, University of Alberta, Edmonton, AB T6G 2H1, Canada {stevem, duane, jonathan, janvik, bromling, cavalier}@cs.ualberta.ca Abstract A design pattern encapsulates the knowledge of object-oriented designers into re-usable artifacts. A design pattern is a descriptive device that fosters software design re-use. There are several reasons why design patterns are not used as generative constructs that support code re-use. The first reason is that design patterns describe a set of solutions to a family of related design problems and it is difficult to generate a single body of code that adequately solves each problem in the family. A second reason is that it is difficult to construct and edit generative design patterns. A third major impediment is the lack of a tool-independent representation. A common representation could lead to a shared repository to make more patterns available. In this paper we describe a new approach to generative design patterns that solves these three difficult problems. We illustrate this approach using tools called CO 2 P 2 S and Meta-CO 2 P 2 S, but our approach is tool-independent. Keywords: design patterns, frameworks, programming tools. 1. Introduction The most common form of a design pattern is a descriptive one such as a pattern catalogue entry or a Web page. This form preserves the instructional nature of patterns, as a cache of known solutions to recurring design problems. Design patterns provide a common design lexicon, and communicate both the structure of a design and the reasoning behind it [2]. We use the well-known Composite design pattern as an example [10]. Figure 1 shows how this design pattern maintains part–whole object hierarchies, where individual parts and compositions of parts are treated uniformly. It supports hierarchy traversal operations. A leaf class instance implements each traversal as a local operation on itself. An composite instance implements the traversal as an optional local operation on itself, together with calls that apply that same operation to each of its child objects. Each child may be a leaf instance or another composite. There are also a set of child management operations like add(Component) and remove(Component). Figure 1. The Composite design pattern. In addition to a diagram like Figure 1, the design pattern documentation usually contains a description of the pattern that consists of eleven parts: intent, motivation, applicability, structure, participants, collaborations, consequences, implementation, sample code, known uses and related patterns [10]. There are many variations of this pattern, but in this paper we are using the pattern as defined in [10] since that is the most common version. In Section 4.5 we show another version of this pattern as an example of pattern evolution. During application design, each pattern must be adapted for use, since each pattern is a family of solutions. Each family member has the same basic structure but must be adapted to its specific context. For example, if a Composite pattern is used for drawing, then particular leaf and composite classes must be identified. Perhaps the leaf classes are Line and Circle, while the composite classes are Group (an arbitrary collection of other components) and Quadrilateral (a specific collection of four lines). Some specific methods must also be identified during adaptation. For example, there may be two traversal operations: draw(GraphicsContext) and boundingBox(). During the implementation process, the adapted design pattern is a specification. Experienced programmers can quickly transform the specification into code since they have probably implemented the Composite pattern many times. For novice programmers, the process of coding the design pattern is more difficult and error-prone. This is Component operation(…) [add(Component)] [remove(Component)] client Leaf operation(…) Composite operation(…) add(Component) remove(Component) for each c in children c.operation(…)

Upload: vuhuong

Post on 11-Jun-2018

213 views

Category:

Documents


0 download

TRANSCRIPT

Generative Design Patterns

S. MacDonald, D. Szafron, J. Schaeffer, J. Anvik, S. Bromling and K. TanDepartment of Computing Science, University of Alberta, Edmonton, AB T6G 2H1, Canada

{stevem, duane, jonathan, janvik, bromling, cavalier}@cs.ualberta.ca

AbstractA design pattern encapsulates the knowledge of

object-oriented designers into re-usable artifacts. Adesign pattern is a descriptive device that fosterssoftware design re-use. There are several reasons whydesign patterns are not used as generative constructs thatsupport code re-use. The first reason is that designpatterns describe a set of solutions to a family of relateddesign problems and it is difficult to generate a singlebody of code that adequately solves each problem in thefamily. A second reason is that it is difficult to constructand edit generative design patterns. A third majorimpediment is the lack of a tool-independentrepresentation. A common representation could lead to ashared repository to make more patterns available. Inthis paper we describe a new approach to generativedesign patterns that solves these three difficult problems.We illustrate this approach using tools called CO2P2Sand Meta-CO2P2S, but our approach is tool-independent.

Keywords: design patterns, frameworks, programmingtools.

1. IntroductionThe most common form of a design pattern is a

descriptive one such as a pattern catalogue entry or a Webpage. This form preserves the instructional nature ofpatterns, as a cache of known solutions to recurringdesign problems. Design patterns provide a commondesign lexicon, and communicate both the structure of adesign and the reasoning behind it [2].

We use the well-known Composite design pattern as anexample [10]. Figure 1 shows how this design patternmaintains part–whole object hierarchies, where individualparts and compositions of parts are treated uniformly. Itsupports hierarchy traversal operations. A leaf classinstance implements each traversal as a local operation onitself. An composite instance implements the traversal asan optional local operation on itself, together with callsthat apply that same operation to each of its child objects.Each child may be a leaf instance or another composite.There are also a set of child management operations likeadd(Component) and remove(Component).

Figure 1. The Composite design pattern.

In addition to a diagram like Figure 1, the designpattern documentation usually contains a description ofthe pattern that consists of eleven parts: intent,motivation, applicability, structure, participants,collaborations, consequences, implementation, samplecode, known uses and related patterns [10]. There aremany variations of this pattern, but in this paper we areusing the pattern as defined in [10] since that is the mostcommon version. In Section 4.5 we show another versionof this pattern as an example of pattern evolution.

During application design, each pattern must beadapted for use, since each pattern is a family ofsolutions. Each family member has the same basicstructure but must be adapted to its specific context. Forexample, if a Composite pattern is used for drawing, thenparticular leaf and composite classes must be identified.Perhaps the leaf classes are Line and Circle, while thecomposite classes are Group (an arbitrary collection ofother components) and Quadrilateral (a specificcollection of four lines). Some specific methods mustalso be identified during adaptation. For example, theremay be two traversal operations:draw(GraphicsContext) and boundingBox().

During the implementation process, the adapted designpattern is a specification. Experienced programmers canquickly transform the specification into code since theyhave probably implemented the Composite pattern manytimes. For novice programmers, the process of coding thedesign pattern is more difficult and error-prone. This is

Component

operation(…)[add(Component)]

[remove(Component)]

client

Leaf

operation(…)

Composite

operation(…)add(Component)

remove(Component)

for each c in children c.operation(…)

partly due to the fact that design patterns are writtendocuments that are subject to human interpretation. Thismakes them vulnerable to the ambiguities in naturallanguage. An incorrect interpretation of a pattern can leadto an incorrect implementation. It would be beneficial touse generative design patterns that generate code. Theyreduce implementation time, are less prone to programmererror, promote rapid prototyping and code reuse, supportperformance tuning, and provide better overall softwareengineering benefits.

1.1 Generative design pattern problemsUnfortunately, there are several problems that must be

solved to make design patterns generative. The firstproblem is related to design pattern adaptation and theinterplay between adaptation and code generation. Thereare three choices for when to generate code: beforeadaptation, during adaptation, or after adaptation.

First, consider code generation before adaptation. Sincea design pattern represents a broad solution family, thegenerated code will be quite complex and quite generic.There are several ways of dealing with the complexity.First, the generated code could be a framework so thatadaptation is done by framework specialization [11].However, most design patterns represent families ofsolutions whose structures cannot be adequatelyrepresented by a static framework.

As an example, consider the name and arguments ofthe traversal operations in the Composite pattern. Oneprogram may require draw(GraphicsContext), whileanother program may require containsPoint(Point). Astatic framework cannot meet these conflictingrequirements unless the traversal code is not included inthe framework. This defeats the purpose of generating thecode from the design pattern. Un-adapted design patterncode is too complex to represent by a static framework.The complexity can sometimes be mitigated by amechanism that supports cross-cutting. For example, thenames and parameter lists of the traversal operations couldbe generated using aspect-oriented programming (AOP)[12]. In this case the names and signatures could beweaved with a generic framework to produce the finalframework code. However, this is just an example ofgenerating code during adaptation.

In fact, there are many situations when cross-cuttingcannot compensate for generating code too early. Forexample, in the Composite pattern, there is a choice(safety or transparency) about where to declare the childmanagement operations. In the safe implementation, theyare declared in the composite class. Applying theseoperations to a leaf class instance results in a compile-time error. The disadvantage is that you must query acomponent to get its type or perform an unsafe type-castbefore you apply a child management operation. In thetransparent implementation, child management operationsare declared in the component class. In this case, you canapply them on any components without type testing or

casting. The disadvantage is that you must implement theoperations in the leaf classes. You might implement theseoperations to do nothing for a leaf instance. However, inthis case, trying to apply one of these operations to a leafclass instance might signal a logic error that you wouldmiss. The important point is that it is impossible togenerate a single static framework that will be adaptive toboth choices: safety or transparency.

When code is generated before adaptation, there can bea genericity problem. Design patterns try to introduceflexibility to support application evolution that is oftencalled “designing for change” [10]. This flexibility isusually achieved by adding indirection between objects.Unfortunately, this approach requires more code to bewritten and maintained and the indirection can reduceperformance. In effect, the indiscriminant use of patternscan result in a slower application [17]. For example, wemay not want to use the same kind of implementation forour Quadrilateral and Group classes. We can avoidindirection in our Quadrilateral class by using fourLine instance variables.

In summary, it is very difficult to generate code beforeadaptation that is general for all of the problems thepattern is designed to solve. If this problem could besolved, the code would often be too complex and oftentoo generic to achieve good performance.

Second, consider code generation after adaptation,which can generate simple efficient code. Unfortunately,during adaptation, the pattern quickly gathers application-specific characteristics. For example, the identification ofa draw(GraphicsContext) during pattern adaptationmeans that if code is generated after this adaptation, thegenerated code is only applicable to applications similarto our graphics application. This approach leads to anexplosion of specialized versions of each pattern or thesituation where we need a version that is slightly differentthan the available versions and we don't have it.

The third approach is to generate code duringadaptation. In general, there can be an arbitrary number ofadaptation and code generation cycles. However, we areinterested in the simplest process that provides usableresults. Therefore we propose (and have created) a simplethree-phase process consisting of: initial adaptation, codegeneration and final adaptation. The initial adaptationphase adapts the design pattern to a single structural andcontrol flow model suitable for the application. The codegeneration phase generates a framework for thisarchitecture and the final adaptation phase performsstandard specialization operations on the framework toadapt it to the final application domain. This approachsolves the problem that frameworks cannot be easilyadapted to support different structures or control flows,while maintaining the advantage that frameworkspecialization is a good technique for specializing code forspecific applications. A framework is the most popularadaptation technique that can be used after codegeneration. Other popular adaptation techniques (such asAOP) occur before code generation.

1.2 Parameterized design patternsPublished descriptive design patterns include lists of

participants, implementation issues and sample code.These three parts of the pattern are used most whenimplementing a design pattern manually. However, theyare not sufficient for generative design patterns. The keynovel contributions of our research efforts is to quantifyeach adaptation option as a parameter with a fixed set ofpossible values that must be set during the initialadaptation process. There have been several efforts toproduce generative design patterns. Some of theseapproaches are ad-hoc and some use more structuredapproaches [4][6][7][8][9][19]. However, our approach isnew. Each descriptive design pattern is transformed into agenerative design pattern using quantitative parameterswith specific domains. We have discovered that althoughthe specific parameters vary from design pattern to designpattern, the parameters can be classified into a few distincttypes. After this initial adaptation, our approach has theflexibility of further adaptation by specializing aframework that still spans many application choices.

In this paper we show that our approach is viable bydescribing solutions to these three important problems:1. Generative design patterns are conceptually complex.However, with good abstractions, a well-defined process,and proper tool support, the difficulties can be managed.Each design pattern must be analyzed to identify specificadaptation parameters. Then, the legal values of theseadaptation parameters must be specified and code must bewritten that implements each combination of legal values.Since the number of combinations is exponential in thenumber of parameters, tool support is essential.2. Generative design patterns must be adapted by thepattern user, and this is conceptually complex. Onceagain, the right abstraction, a well-defined process, andtool support are required. Tool support should help theuser assign legal values for each design pattern parameter,generate code based on these parameter values, andsupport specialization of the generated framework code.3. If only a few generative design patterns exist, fewpeople will use them. A standard tool-independentrepresentation is necessary to foster sharing and toencourage the construction of generative pattern

repositories. However, due to the wide variability ofapplication requirements, generative design patterns mustbe living entities.

In this paper, we present a solution to these threeproblems. Our approach to generative design patterns isindependent of programming language and tools.However, to validate our process we have implementedtwo support tools, CO2P2S (Correct Object-OrientedPattern-based Programming System - www.cs.ualberta.ca/~systems/cops) [1][13][14] and Meta-CO2P2S [5].CO2P2S is used to adapt design patterns and generateframework code for use in specific applications. Thecomplete process takes three steps. First, the user selectsan appropriate generative design pattern from a set ofsupported patterns. Second, the user adapts this patternfor their application by providing parameter values.Finally, the adapted generative pattern is used to createobject-oriented framework code for the chosen patternstructure. Meta-CO2P2S is used to create new generativedesign patterns, to generate tool-independentrepresentations and to edit and evolve existing designpatterns. Figure 2 shows the specialization flow, fromgenerative design pattern to final application code.

Section 2 describes our process for generative designpattern adaptation using the Composite pattern as anexample. Section 3 describes our solution to the difficultproblem of constructing generative design patterns.Section 4 looks "under the covers" at the tool-independentrepresentation that is generated during the generativedesign pattern construction process described in Section3. Section 5 summarizes the paper. One of the importantchallenges of our approach is to manage the evolution ofgenerative design patterns, especially the tension betweengenericity and simplicity.

2. Design pattern adaptation - parametersIn this section we describe a new view of generative

design patterns that is parameter-based. We use theComposite pattern as an example pattern because it iswell-known and has a variety of parameters. We also usethe CO2P2S tool as an example of an adaptation andgeneration tool. The specific pattern and tool are not asimportant as the idea of parameterized patterns.

Figure 2. Patterns to frameworks to applications.

Generative PatternDescription

GraphicalRepresentation

ParameterDescriptions

Source CodeTemplate

GenerativePattern

Generator

GraphicalDisplay

User-suppliedParameter Values

Application-specificCode

GenerativePattern

CodeGenerator

FrameworkCode

StructuralCode

HookMethods

2.1 Parameters for the Composite patternThe Composite design pattern has seven parameters.

The parameters are divided into four categories, lexicalparameters, design parameters, performance parametersand verification parameters. A lexical parameter is usedto specify a class name, method name or some othersyntactic structure in the generated framework. A designparameter affects the structure of the generatedframework. A performance parameter only affects theperformance of the generated code. When a verificationparameter is turned on, the generated code performs run-time semantic checks on user-supplied code. When it isoff, no verification code is generated. The Compositepattern has four lexical parameters, two design parametersand one performance parameter:1. (lexical) The name for the abstract component class inthe generated framework, called component name.2. (lexical) The name for the abstract composite class inthe generated framework, called composite name.3. (lexical) The name for the abstract leaf class in thegenerated framework, called leaf name.4. (lexical) A name for the pattern superclass, calledsuperclass name.5. (design) The location of the child managementoperations – safe versus transparent, called safe-transparent.6. (design) A traversal list, called operation list.7. (performance) The types of containers used, calledcontainers.

Each parameter has a name so that it can be referencedand a type that specifies its legal domain of values.Although the parameter names are pattern-specific, thetypes are re-used across patterns. We use the simpledrawing application from Section 1 to illustrateparameters and parameter value selection. Assume wewant to generate a framework that supports an operationdraw(GraphicsContext), that draws any component ona GraphicsContext, and an operation boundingBox()that returns a Rectangle that bounds an arbitrarycomponent. To make the framework more realistic (andchallenging), we assume that when a composite instancedraws itself, it must first draw a background and thendraw each of its components. We assume that we willneed at least two application leaf classes: Line andCircle. We will also need at least two composite classes:Group and Quadrilateral. A Group can contain anarbitrary collection of components. A Quadrilateral isa specific collection of four Lines.

The user controls the names of the abstract classes inthe composite pattern of Figure 1, by supplying valuesfor the component name, composite name and leaf nameparameters of type Class Name. For example, the usermight use the names: DrawingComponent,ListComposite and DrawingLeaf. The user also entersan arbitrary superclass name for the component class.This facility is necessary to support general composition

of generated framework code. If no superclass is required,the user can enter Object. In this paper, we will use Javaas an example target language. If C++ was the targetlanguage, an empty superclass name could be used.

The design parameter, safe-transparent, has parametertype Enumeration. Each Enumeration parameter has asmall set of legal values. In this case, there are twovalues: safe and transparent. If the safe value is selected,the child management operations are generated in thecomposite class. If the transparent value is selected, thechild management operations are also generated in thecomponent class.

The sixth pattern parameter is used to select all of thetraversal operations that are generated for the pattern. Theoperation list parameter has type List. In general, a Listparameter is a list of parameters of arbitrary type. In thiscase, each parameter in the list represents a traversaloperation. For a List parameter, the user can add as manyelements to the List as necessary. In our example, the listhas size two since we must generate two traversaloperations. Each list element in the operation list hastype Structure. A Structure parameter has a fixed numberof sub-parameters. In this case, each operation listelement must represent all of the information necessary togenerate code for one traversal operation.

To define the structure of each operation list element,we must look at what kind of information it mustspecify. In some composite applications, it is necessary toperform a computation in each composite instance, inaddition to delegating the traversal operation to its childinstances. In general, this composite action may occurbefore or after the child instances are traversed. Forexample, in our draw(GraphicsContext) method, acomposite instance must draw a background before callingthe draw(GraphicsContext) method on each of itschildren to draw the foreground. This is an example of aprefix method since it is called before traversing the childinstances. As a second example, consider ourboundingBox() method. Each composite instance mustinvoke this method on each of its children and then usethe results to construct a bounding box from all of theRectangle objects that are returned from the children.Such a method is called a suffix method and it takes as anargument an array of the results of the traversal operationthat has been applied to its children.

Each element in the operation list must specify thesignature of the operation method, whether the operationhas a prefix method or not and whether the operation hasa suffix method or not. If the operation has a prefixmethod, the name must be specified. The signature of theprefix method will be the same as the operation methodthat calls it. For example, the user will specify that thedraw operation has method signature void

draw(GraphicsContext gc), that it has a prefix methodand that it does not have a suffix method. The user willspecify that the prefix method is called"drawBackground". The signature of the prefix methodwill be void drawBackground(GraphicsContext gc).

If the operation has a suffix method, the name of thesuffix method must be specified. The signature of thesuffix method will include all of the parameters of theoperation method that calls it, plus an array of the returnvalues of the operation method applied to the children.So, in our example, the user will also specify that theboundingBox operation has method signature RectangleboundingBox(), that it has no prefix method and that ithas a suffix method. The user will specify that the suffixmethod is called "computeBoundingBox". The signatureof the suffix method will be generated as RectanglecomputeBoundingBox(Rectangle[] anArray).

Each element of the operation list has type Structureand has three sub-parameters. The first sub-parameter,called operation signature has type Method Signature.The other two sub-parameters, prefix and suffix, each havetype Structure and share a common structure.

The containers parameter is the only performanceparameter of the Composite pattern. Each compositeobject must store its child components in a container. Forexample, a vector, array, linked list, or hash table couldbe used. The overall structure of the generated code isindependent of the kind of container used and the choiceof container mainly affects the relative performance of theadd(Component), remove(Component) and traversalmethods. However, the choice can have some semanticconsequences as well, since if a hash table is chosen, theorder of elements is arbitrary and a traversal may selectchildren in any order. Similarly, if an array is chosen, thenumber of children has a fixed maximum.

Alternately, to increase performance by reducingindirections, a fixed number of named instance variablesmay be used. This container choice must be made beforecode generation, since the code for add(Component),remove(Component) and the traversal operations isgenerated. In fact, the user may want to create applicationsubclasses for more than one choice. For example, theGroup of drawing objects should be a subclass of acomposite that uses a variable sized container like vector,linked list or hash table. For efficiency, Quadrilateralcould be a subclass of an abstract composite class that hasfour named instance variables.

The containers parameter has type Dictionary. Itsupports an arbitrary number of abstract compositeclasses, with different names and implementations. Eachkey in this Dictionary is an Enumeration value from:{vector, array, list, hash table, two children, threechildren, four children}. The last three choices generate afixed number of instance variables. If a fixed number ofchildren are required that is more than four, then an arrayshould be used. This Dictionary starts with one entrywhose default key is list and whose value is the value ofthe composite name parameter. New entries are added foreach container that is selected from the Enumeration. Forexample, in our application the composite name isListComposite. Notice that there are two abstractcomposite classes, ListComposite to support Group andFourComposite to support Quadrilateral.

2.2 Tool support for setting parametersFigure 3 shows a sample CO2P2S screenshot with

parameter values for this drawing application. Toolsupport can make the adaptation process straightforward.The left side of the tool provides a palette of supportedgenerative design patterns, of which the Composite is oneexample. The right side of the tool shows the current stateof the selected pattern. The set of generative patterns in anapplication is shown in the center pane. CO2P2S usesdialog boxes to guide the user through the parametervalue selection process, by constraining user choices. Forexample, CO2P2S uses radio buttons for Enumerationparameters and checks for syntactic correctness ofIdentifier parameters after they are entered in a text field.

Figure 3. Composite pattern for theDrawing application.

The parameter types described in Section 3.1, ClassName, Method Name, Method Signature, Enumeration,Boolean, Structure, List and Dictionary, are most of thetypes required to implement our current set of supporteddesign patterns. In fact, as described in Section 3.1, theseparameter types can be expressed in terms of three simpleparameter types: String, Enumeration and List. Allparameter types can be constructed from these three basictypes and a fourth type, called Extended.

After parameter value specification, the adapted designpattern is used to generate a code framework. Thisframework can be further adapted using frameworkspecialization. For example, the user can create the classesLine, Circle, Group and Quadrilateral as subclassesof the abstract classes DrawingLeaf, DrawingLeaf,DrawingComposite and FourComposite respectively.The user inherits the code for the two traversal operationsdraw(GraphicsContext) and boundingBox() in each ofthe composite classes Group and Quadrilateral. Theuser must implement each of these methods in the leafsubclasses Line and Circle. In addition, the user mustimplement the drawBackground(GraphicsContext)

prefix method in the Group class to draw whateverbackground is desired. The Quadrilateral class can justinherit the default implementation ofdrawBackground(GraphicsContext) which doesnothing. The user must also implement the

computeBoundingBox(Rectangle[]) suffix method inthe Group and Quadrilateral classes. Other leaf andcomposite classes can be added by frameworkspecialization. However, if the user wants another abstractcomposite class with a different implementation strategy,the user will have to edit the adaptation parameters and re-generate the code. For example, if the user wants to add aTriangle class as a subclass of an abstract compositeclass that has three instance variables, another entry mustbe added to the containers Dictionary and the code mustbe re-generated. This regeneration will not affect the codealready written in the user's concrete frameworksubclasses.

3. Constructing generative patternsFor a new generative design pattern, the designer

begins by defining each parameter and its parameter type.This information should be stored in a tool independentrepresentation. In Section 4, we will describe ourproposed XML-based representation. Besides storingparameter names and types, the representation alsosupports information that can be used to generate agraphical user interface when the pattern is loaded into anend-user tool that supports pattern users. Patterns andparameter values can be attributed with labels, images andlayout information.

For example, the CO2P2S tool uses such patternattributes to generate a graphical user interface for eachpattern, so that the pattern user can easily set all of thepattern parameters. The basic CO2P2S environmentincludes no patterns. Instead, any generative designpattern can be loaded into CO2P2S using a simple loadpattern operation from a menu. At this point, the patternrepresentation is read and the entire GUI for that pattern isgenerated and added to CO2P2S. The new pattern appearsin the palette and all of the dialogs for setting parametervalues are also added. The user is free to add as few ormany patterns to CO2P2S as needed. As new patternsbecome available, they can be loaded on demand.

Even though the pattern representation is toolindependent, tool support for parameter definition servestwo fundamental purposes. First, it reduces errors byproviding menu-based choices for legal parameter typesand by automatically generating the details of the storageformat. Second, it supports rapid editing or generalizationof existing generative design patterns. The patterndesigner can load a pattern, browse its parameters and addnew parameters. The CO2P2S tool was first constructed tosupport parallel programming. In fact it was calledCO2P3S, where the third "P" stood for Parallel. It beganwith several "built-in" patterns. We quickly realized thatadding patterns by hand was too slow and error-prone. Wecreated the pattern representation and Meta-CO2P2S toolto support rapid pattern addition.

3.1 Generative pattern parameter typesGenerative pattern parameters allow a pattern designer

to customize a pattern and alter the framework code that itgenerates. These parameters are a key part of preservingthe idea that our generative patterns are still a family ofsolutions that can be applied in a particular context. Itmust be possible to adapt the generative pattern to itsintended use.

If we permit the pattern designer to create generativepatterns with arbitrary parameter types, then describingthese parameters will require considerable effort. Instead,to simplify the description of the generative patterns, weenumerate the different types of parameters that can beused. There are three basic parameter types (String,Enumeration and List), and all other types are derivedfrom them. Figure 4 is a specialization diagram for thesetypes.Each String is a simple legal string value.An Enumeration is a value from a fixed set of values.A List handles the common situation where the patternuser supplies a list of other parameters, which may be ofany type.An Identifier has a value that is any legal identifier in thetarget programming language.A Class Name is included in each generative pattern.Pattern users should be able to specify class names in thegenerated frameworks so that they are meaningful in thecontext of the application. In addition this allowsmultiple instances of a pattern in the same application,without name clashes. All of the generative patterns haveat least one class name that the user provides. Normally,this is the name of the class that the user must specialize.The framework class names are derived from this user-supplied name by adding text to make them unique. A Method Name represents the name of a method. It isespecially useful when the rest of the signature is fixed bythe pattern or by previous user choices.A Boolean is a special case of Enumeration, where thelegal values are true and false.A Structure deals with the common case where aparameter consists of a fixed number of sub-parameters.A Method Signature specifies the name, return type andargument types of a method. It is a special case of aStructure parameter since a signature consists of the returntype (Identifier), a Method Name, and an arguments List.The elements in the arguments List are Structureparameters with two sub-parameters, an argument type(Identifier) and an argument name (Identifier). It ispossible to define a separate argument parameter type forthe Java target language. An argument type would berestricted to a Class Name or a primitive type. It is alsopossible to define a return type since it is either anargument type or void.A Dictionary maps keys to values for the code generator.This is particularly useful for multiple selectionparameters, where each selected value must be mapped toa class name for code in the generated framework.

An Extended parameter supports the case where theparameter values have an arbitrary form. The patterndesigner must provide extra information for each of theseparameters, such as a way for the pattern user to supplythe parameter value and how different values affect thegenerated code.

These parameter types are sufficient to cover a broadrange of generative pattern parameters. Extendedparameters can be used to implement any other parametertypes. In fact, if a new parameter type is needed for apattern and it cannot easily be derived from one of theexisting types, it usually starts out with type Extended.All parameter types except for String, and Enumeratedstarted as Extended parameters before they were promotedto named types and derived from existing types.

Figure 4. The specialization hierarchy forparameter types.

3.2 Framework generationAfter a pattern user specifies values for all of the

parameters, the set of values is used to generate object-oriented framework code. The code generation problem isa problem of conditional compilation of a code template,based on the set of parameter values. We need a way torepresent each parameter in the code template and totransform each parameter to concrete code. Thetransformation is based on:• the parameter definitions for a particular design patternlike the ones described in Section 2.1.

• the design pattern independent parameter typedefinitions listed in Section 3.1,

• and the values of the parameters for a particular designpattern as described in Section 2.1.

We can enumerate the set of representations and thepotential transformations that must be supported by thecode generator to derive its basic requirements:• Each String parameter is represented by a StringPlaceholder in the source code template. It must bereplaced with its parameter value during code generation.Sometimes, a transformation directly replaces the StringPlaceholder by a user-supplied parameter value.Sometimes the String Placeholder is constructed from theuser supplied String value. For example, framework classnames that are hidden from the user are derived from theuser-supplied class names by adding additional text thatdescribes the role of the class in the framework. Identifier,Class Name and Method Name parameters all map toString Placeholders.

• Each Enumeration parameter is represented by a GuardVariable that can be assigned one value from the domainof the Enumeration parameter. The key requirement forcode generation is that methods, parts of method bodiesand variables can be conditionally generated based on thevalue of a Guard Variable. To reduce the complexity ofcode generation, conditional generation based on acombination of values for different Guard Variablesshould also be supported. Boolean parameters map tosimple Guard Variables with legal values true and false.

• Each List parameter is represented in the code by a ListPlaceholder that indicates its location. As the parametersin a list are expanded, the code for each parameter in thelist is decorated and concatenated. Note that it is possibleto nest lists. Structure parameters, Method Signatureparameters and Dictionary parameters also map to lists.

• Each Extended parameter has no fixed transformationtechnique for code generation. An Extended Placeholdermarks its location in the code template. However, it is anad-hoc parameter type for which the pattern designer mustprovide custom code generation support. When theplaceholder is encountered during code generation, adesigner-supplied method must be called that returns thecode to be inserted.

3.3 Using Javadoc for code generationIn this Section, we describe a code generator that we

implemented using Javadoc. Although Javadoc does notdirectly support all of the types defined in the previoussection, it has sufficient functionality to test ourapproach. All types that weren't implemented directlywere implemented using the Extended parameter type.

Javadoc is a tool whose original purpose was togenerate HTML formatted API documentation for Javaclasses. Javadoc parses Java source code files. In fact, itonly parses declarations. However, Javadoc also parsesspecially formatted comment blocks that:• start with /**,

• end with */,

• include lines that contain a pre-defined or user-definedtag name ( @identifier ) followed by a blank and text,

• are followed on the next line by a class declaration, fielddeclaration, or method declaration.

For example, Figure 5 shows a Javadoc commentblock that contains two tag names and precedes a methoddeclaration. The first tag, @param, is a pre-defined tagname. It is a standard part of Javadoc that is used toprovide a comment for each parameter in a methoddeclaration. The other tags, @parameter and @editable,are user-defined tags that we have defined for codegeneration purposes (described below).

Javadoc has been extended to support pluggableDoclets. A Doclet is a Java program that can receiveparsing information from Javadoc. This informationincludes declarations and comment blocks and is provided

String

Identifier

Class Name Method Name

ExtendedEnumeration

Boolean

List

Structure

Method Signature

Dictionary

using the Doclet API, which provides access to thefollowing information for each class: the imported classesand packages, the package of the class, the classdeclaration, and the declarations of the constructors,methods and fields.

/** * Iteration op for a top edge node in a 4 point mesh. * * @param east the node to the right * @param south the node below * @param west the node to the left * @parameter numNeighbours 4 * @parameter boundary Non * @parameter boundary Horizontal * @editable */ public void topEdge(SP_MeshElement east, SP_MeshElement south, SP_MeshElement west) { }

Figure 5. Using javadoc for parameters.For each declaration, Javadoc also provides the text and

tags from any associated comment block. By defining ourown tags, we can allow the pattern designer to write codetemplates in standard Java with all pattern parameterinformation either in String Placeholders or encoded inJavadoc comments. This means that the code templatesare much easier to read and that they can be compiledwith no pre-processing during testing. Our code generatorcalls Javadoc and gains access to the parsed informationusing a Doclet. Javadoc has been used before for codegeneration [16], but in a simpler context.

String Placeholders are represented using the syntax ofJava identifiers, so Javadoc can parse them. Since theyall begin with a distinctive SP_ prefix the Doclet canrecognize them. Since they contain the parameter name,the Doclet can simply look up the parameter name in theparameter dictionary and replace them by the parametervalue that is also a Java identifier. For example, Figure 5shows the String Placeholder, SP_MeshElement thatrepresents the user-defined class name of a mesh element.All other representations can be expressed in terms ofGuard Variables, List Placeholders and ExtendedPlaceholders.

Guard Variables that guard classes, methods or fieldsare expressed using the @parameter tag. The declarationthat follows the comment block containing the tag is onlygenerated if the parameter named in the tag has the valuethat follows the parameter name. If generation depends onone of several acceptable values, then the parameter valueis repeated on separate lines, each with one acceptablevalue. If two different parameters must have specificvalues for code generation, then each different parametershould appear on a separate line with its required value.This allows arbitrary ORing of parameter values for thesame parameter and arbitrary ANDing between differentparameters. For example, Figure 5 shows the first line ofa method that is generated only if the boundary parameter

has the value Non or Horizontal, and thenumNeighbours parameter has the value 4.

List Placeholders and Extended Placeholders are bothsupported in Javadoc using the tag @extParameterfollowed by the parameter name. For example, considerthe operation list parameter for the Composite pattern.Code for the operation list must be inserted in twodifferent locations in the Composite code template. A listof traversal operation methods must be inserted into thecomponent class. This list could either consist of abstractmethods, or methods with empty bodies. The same list oftraversal operation methods must be inserted into thecomposite class. However, this list must have functioningmethod bodies that delegate the operations to the childobjects plus optional calls to prefix and suffix methods,depending on user-selected parameter values. The patterndesigner will place the same Javadoc tag and parametervalue, @extParameter operationList, into the classfiles for the component class and the composite class.Somehow, Javadoc must expand these two tags intodifferent code in the two contexts.

The pattern designer must implement a Java class foreach List or Extended parameter that is used in a pattern.If the class represents an Extended parameter it must be asubclass of a pre-defined CO2P2S class calledAbstractPatternParameter. If the class represents aList parameter, it must be a subclass of a pre-definedCO2P2S class called PatternListParameter. In eithercase, it must implement the method public List

getCodeGenMethod(String classname).When Javadoc encounters the @extParameter tag, it

calls our Doclet and passes it the tag name and parametername. The Doclet code maps the tag and parameter nameto the corresponding class written by the pattern designer.For example, the parameter operationList may be mappedto a class called OperationList. The Doclet creates aninstance of the class and invokes thegetCodeGenMethod(String classname) method on thisinstance. The pattern designer must implement thismethod in each List or Extended parameter class that isdefined for the pattern. This method checks the classnameargument and generates the appropriate code that shouldappear in this class. For example, in the Compositepattern, the code would generate abstract methods for thecomponent class and traversal methods for the compositeclass. To generate the correct code, the method checks thedata structure that contains the user-selected parametervalues for the pattern being adapted.

Unfortunately, our simple Javadoc implementation willnot work for generating code inside a method body, sinceJavadoc does not parse method bodies. Therefore, we havewritten a small macro processor to support codegeneration inside method bodies. To simplify the macroprocessor and to support default method bodies for somegenerated methods, we have separated the bodies of allmethods in the code template from the methods thatcontain them. Therefore, each class in a code templatecurrently consists of a class skeleton file that contains

empty method bodies together with a directory of files,one for each method body, defined in the class. At codegeneration time, the class skeleton file is processed byJavadoc and the method body files are processed by theCO2P2S macro-processor.

CO2P2S provides an HTML-based browser for viewingthe generated framework. The pattern designer markssome of the framework methods as editable (using a user-defined Javadoc tag called @editable). The editablemethods are called hook methods and although defaultimplementations are supplied to the user, the browserallows the user to edit the bodies of these methods, butnot their signatures.

The macro processor supports Guard Variables using a#IF# macro, which guards portions of method bodies.The macro-processor supports List Placeholders andExtended Placeholders using a single #Extended# macrothat has the parameter name as an argument. When thismacro is found by the macro-processor it calls the sameJava code as was called by Javadoc to compute a Stringreplacement for the macro.

3.4 Tool support: Meta-CO2P2SCreating a generative design pattern is not a simple

task. The parameters for a pattern must be specified and aframework must be created. To support graphical toolslike CO2P2S, the pattern's graphical components mustalso be created and assembled so they can be displayed ona user interface.

To simplify this process, we provide tool support inthe form of Meta-CO2P2S. One goal of this meta-programming environment is that its generative patternsshould be first-class. That is, they should beindistinguishable in form and function from thosepatterns supplied with CO2P2S. We do not want to createa dichotomy of generative patterns: those supplied by thetool builders and those created by pattern designers usingMeta-CO2P2S. The pattern designer's ability to create newpatterns should not be hindered in any way.

Meta-CO2P2S provides dialogs for defining eachparameter in a generative pattern, as well as otherinformation that the pattern user never sees. Forconvenience, parameters are grouped into categories. The"Class Names" category is one example. Each class isassigned a role as structural or user-accessible. Structuralclasses are internal framework classes that a user does notnormally need to access. User-accessible classes, whichexport hook methods that the user must implement, areflagged so that these files can be preprocessed beforebeing presented to the user. For example, CO2P2Sconverts these files to HTML, as explained later inSection 4.4. The @editable tab in the source codetemplate indicates which methods in these classes can bechanged by the user.

User interface descriptions are in the "Constants" and"GUI Configuration" categories. Some of the constantsare label strings that appear in the pattern description or in

menu items. The GUI configuration describes the layoutof the graphical pattern representation, including theimage that shows the pattern structure. The appropriateimage is selected by concatenating parameter values, andusing the resulting text as the name of a GIF image. Thisprovides a simple mechanism for updating graphicswithout needing to write display code.

Finally, the "Parameters" category describes thegenerative pattern parameters. Each parameter can be oneof the parameter types listed earlier in the paper. Eachitem in this category fully describes the parameter,including its type, necessary extensions, and its set oflegal values.

Meta-CO2P2S bundles the parameter information andGUI attributes together and stores the information in a filewith standard XML format as described in Section 4.

4. Generative pattern representationThis section focuses on the representation of the

different components of our generative design patterns(parameters and frameworks) and shows that thisrepresentation is not tied to a particular programmingsystem. We also show how it is turned into a generativepattern form suitable for use in programming tools, ofwhich CO2P2S is just one example.

The exact requirements of this representation depend onthe particulars of the programming system. However, oneof the goals of this representation is to be system-independent so that patterns for any number of tools canbe generated from the same pattern description.

4.1 Pattern parameter representationThe parameter descriptions must be stored for use in

programming systems. The parameter representationconsists of two parts. The first part is a description of theparameter, including its type (Section 3.1). Thisdescription uses XML format that has the benefit of tool-independence. In addition, the format of an XML file canbe verified using a DTD (Document Type Definition) file,so that a custom verifier is not required. Finally, XMLhas a number of system-independent support tools forparsing and manipulating files.

The second part of the parameter description is anXML description of the graphical elements needed toenter the parameter values. Text-based tools can ignorethis part of the parameter description. This XML is notintended for humans. It should be generated by anypattern design meta-tool and read by any patternadaptation tool.

4.2 Automating parameter value entryThe descriptions of the parameters for a generative

design pattern must be stored so that they can beincorporated into a pattern adaptation tool. However,during adaptation, pattern users must have somemechanism for assigning parameter values. Themechanism for parameter value entry is actually a property

of each parameter and that mechanism should be generatedfrom the pattern description.

A String parameter can be entered in a standard dialogbox with a single text field. A specialized Stringparameter, like an Identifier or Class Name can beverified before the typed text is accepted. An Enumerationparameter is entered by a set of labels or graphical imagesand associated radio buttons. A List parameter uses a listpane, and buttons for adding and removing elements. Ofcourse when an add button is pressed, a dialog that isappropriate for the element type is launched.

Other parameter types may require more work becausetheir structure is more ad-hoc. Although it is possible foran Extended parameter to be completely arbitrary, this isunusual. Rather, an extended parameter tends to be textthat contains logically related information that cannot beeasily captured as a set of choices. As a result, simplyproviding a text field for these parameters may not be theideal choice. Instead, the pattern designer may find itbetter to create a customized dialog that allows users toeasily enter the parameter value and that allows the data tobe verified more easily.

As well as providing additional help for obtainingparameter values from the pattern user, it is necessary fora pattern designer to provide code generator extensions forinterpreting the Extended parameter values and generatingthe appropriate code based on them. The dialog thatgathers the parameter value can have an effect on how easyit is to perform this task. Using the method signatureexample, consider inserting a call to the method in theframework structure. With a table, we can easily generatea call statement by printing out the signature without theargument types. If the signature was a line of text, theparser would need to determine the function of each tokenin the text and print it out accordingly.

User interface and code generator extensions arepossible because the CO2P2S interface is itself aframework. The reflective nature of Java allows theseextensions to be instantiated and used when necessary.Part of the description of the parameters indicates thenecessary extensions for each parameter, for obtaining theparameter values from the user and processing them forcode generation.

4.3 Framework representationWe need a format for storing this framework code that

facilitates the transformations described earlier. We referto this family of frameworks as a source code template. Ingeneral, this template is a set of annotated source codefiles, where the annotations indicate how the generativepattern parameters alter the code. It includes all of thecode for all possible variations of the pattern that can bespecified using the pattern parameter values. A codegenerator performs a source code to source codetransformation using the template and the parametervalues. The result is a framework that implements theadapted pattern structure.

As described in Section 4.3, our current code generatoris based on Javadoc and a Doclet. This means that somecode is actually generated procedurally instead of residingin a declarative template. Each Extended parameter can beviewed as a behavioral component. It is possible to createa library of these reusable behavioral components tosupport parameter sharing between patterns.

4.4 From pattern descriptions to generativepatterns to frameworks to programs

The relationships among all of the parts of thegenerative pattern description are shown in Figure 2. Thepattern description, created using Meta-CO2P2S and storedusing the format described earlier, holds all of theinformation needed by a programming tool to incorporatethe generative pattern.

A pattern generator processes the parameter descriptionsand (optionally) the graphical representation and outputs agenerative pattern, in an analogous manner to the wayframeworks are constructed from a source code templateand pattern parameters. An adaptation tool incorporatesthe new generative pattern (discussed later) and makes itavailable to programmers. When a programmer selects thegenerative pattern, the tool obtains values for theparameter values based on their descriptions. The codegenerator described in the previous section takes theseparameter values and the source code template andproduces a customized framework implementing theselected pattern structure. The framework consists ofstructural code and hook methods. The user creates anapplication by supplying application-specific bodies forthe hook methods exported by the framework.

Our pattern generator is implemented using XML andXSL (Extensible Stylesheet Language). An XSLTprocessor processes the parameter descriptions, written inXML, using the XSL stylesheet. The output is a toolconfiguration and associated graphical components for theuser interface. The programming system incorporates thenew generative pattern by including the configurationinformation, and can then provide the pattern to its users.If the tool has a graphical user interface, then the graphicalcomponents can also be used. These components consistof images and labels that are displayed in the interface sothe user can visualize the state of the generative patternduring application development.

In CO2P2S, the tool configuration generated by thepattern generator is a set of Java classes that augment theuser interface. The classes generated by the patterngenerator use this framework to provide user interface andcode generator support for the new generative pattern.These classes are compiled and are subsequently includedin the tool using dynamic class loading in Java.

Other tools may require different configurationinformation from the pattern generator to include newgenerative patterns. For example, a tool may use aspecification language to write programs, and not have agraphical user interface. Generating configuration

information is a matter of providing a tool-specific XSLstylesheet for the pattern description. However, thedescription does not need to be changed. Once created,this description can be used in any tool that provides astylesheet for the pattern generator (the XSLT processor).

Unfortunately, extensions to the user interface,specification language, and code generator will be system-specific until the parameter type system is completed. Inaddition, interface support for combining these types intoparameters will be necessary for each system that wants touse our generative design pattern description.

4.5 Evolving generative design patternsWe have shown an example use of the generative

Composite pattern. This pattern can support a variety oftraversal operations for common cases. However, there aresome problems that this pattern does not address.

For example, the traversal methods always visit thecomplete structure of the composite. For some problems,this may be inefficient. To support applications wherepartial traversals are necessary, the Composite pattern canbe extended to include guard and continuation methodsthat control the traversal. These two methods are similarto the prefix and suffix methods except that rather thanbeing part of the traversal, they dictate the flow of controlthrough the composite structure.

The guard method determines if the children of acomposite object should be traversed. It has the samearguments as the original method. If the guard evaluatesto true, then the composite object executes its optionalprefix method, traverses its children and then executes itsoptional suffix method. If the guard evaluates to false, thetraversal method returns immediately. If the traversaloperation has a return value, the default value is returned.

The continuation method is evaluated before each childobject is visited. Like the guard method, it takes the samearguments as the traversal method. If this method returnsfalse after traversing any child, the remaining children arenot traversed. Regardless, the prefix and suffix methodsfor the composite object are always executed if they arepresent.

To provide this functionality, the pattern designer has achoice. The original generative Composite pattern can beextended, adding new parameters and augmenting thegenerated framework code, or a new pattern based on itcan be created. Pattern flexibility must be balancedagainst ease-of-use. The more parameters that a generativepattern presents, the more flexible it will be. However,with too many parameters, the pattern becomes difficultto specify and use. Since we have no general solution tothis problem, we have considered this balance on apattern-by-pattern basis.

To provide guard and continuation methods, we createda new generative pattern, the GuardedComposite. Wecopied the original Composite description and then usedMeta-CO2P2S to make the changes. We added two newBoolean sub-parameters to each traversal method,

indicating the presence of the guard and continuationmethods. We also added two more Method Name sub-parameters to record the names of the guard andcontinuation methods, if they exist. This approach issimilar to using prefix and suffix methods. Recall that thedescription of a generative pattern consists of an XML filefor parameter descriptions, graphical images, and possiblysome tool extensions. Once copied, the parameterdescriptions were edited using Meta-CO2P2S to add thenew parameters. The copied source code template for theframework was modified as well. Finally, the interfaceand code generator extensions were augmented. The userinterface needed to obtain values for the new parametersfor the generative GuardedComposite pattern, and thecode generator needed to be altered to generate correctcode for the guard and continuation methods in thetraversal methods of the composite classes.

A more sophisticated approach would be to derive anew generative pattern from an existing pattern, using aninheritance mechanism. This would support reuse of partsof a pattern description and source code template.

5. SummaryWe have presented an approach to generative design

patterns that incorporates three new ideas:1. Generative design patterns are defined by a set of typedparameters with specific legal values and a code templatethat generates frameworks whose structure depends oncombinations of values for these parameters.2. Design pattern adaptation is a three-phase processwhere the first phase involves parameter value selection,the second phase involves framework code generation andthe third phase involves framework specialization.3. A two part tool-independent representation ofgenerative design patterns consists of an XML-basedrepresentation of pattern parameter values and a codetemplate with simple parameter-based annotations.

We have described two tools, CO2P2S and Meta-CO2P2S that support our process and that have be used toadapt and generate design patterns. In addition, ourgenerated code does not suffer from the performancepenalties that plague many "automatic programming"approaches. In fact, our generated code has been successfulin the performance-conscious domain of parallelprogramming [1][14]. For example, CO2P2S has beenused to generate efficient solution code [2] for allproblems in the Cowichan problem set. This problem setis used to evaluate problem coverage and performance inparallel programming systems [18].

CO2P2S currently supports six design patterns forparallel computing: mesh, wavefront, pipeline, search-tree, distributor and phases. It also supports sequentialpatterns: composite, decorator, abstract factory, chain(tree) of responsibility and observer. However, Meta-CO2P2S can be used to quickly add new design patterns.

Any programmer who wants to use a generative designpattern to write an application, follows four steps:

1. Pick an appropriate set of design patterns. Oneapproach is to use a pattern language [15].2. Use a tool like CO2P2S to adapt design patterns to anapplication by selecting values for the pattern parameters.3. Press a button to generate frameworks for each designpattern that has been customized for your application.4. Use framework specialization to finish the application.We have also described a new approach to generativedesign pattern construction. To create a new generativedesign pattern, a pattern designer follows four steps:1. Find an existing descriptive design pattern that appliesor create a new descriptive design pattern.2. Analyze the descriptive design pattern with emphasison the: participants, implementation issues and samplecode, to identify pattern parameters that could affect thestructure of the framework code you will need. Studyexisting generative design patterns for similar issues andparameterization requirements. If possible, find anexisting generative design pattern that is similar and editit, instead of creating a new one.3. For each parameter that was identified in 2), determinethe legal parameter values by considering the necessaryparameter values for your application (you may needmultiple adapted copies with different values) and theknown uses section of the pattern documentation. Alsoconsider legal parameter values of similar parameters inother generative design patterns and use existingparameter types as a guide.4. Construct a code template that spans the legalparameter values defined in 3). Use other generativedesign patterns to guide you, or if possible, edit anexisting generative design pattern to take advantage of thecode template that has already been written. Use theparameter types to guide the construction of your codetemplate. If possible, use a tool like Meta-CO2P2S tosimplify the construction of behavioral components.

Writing parameterized design pattern code can be hard.We need strong tool support and in this paper we havedescribed some support that we do provide. However, weneed more tools. For example, we need tools to check forcoverage. In other words, did the pattern designer providecode for all legal parameter value combinations? We needsupport for testing. For example, we need a tool togenerate test application code that exercises allcombinations of legal parameter settings. Creating newprogramming languages that support higher levels ofabstraction is a useful goal. However, tools have becomethe new programming languages of modern softwaredevelopment. We believe that the future of masteringgenerative design patterns lies in open representations andtools that support them.

6. References[1] J. Anvik, et.al. Generating parallel programs from the

wavefront design pattern. In High-Level Parallel

Programming Models and Supportive Environments, Ft.Lauderdale FL., CD-ROM April 2002.

[2] J. Anvik. Asserting the utility of CO2P3S using theCowichan problem set, Master's thesis, Department ofComputing Science, University of Alberta, 2002. Inpreparation.

[3] K. Beck and R. Johnson. Patterns generate architecture.ECOOP, Vol. 821 of LNCS, pp. 139-149. Springer, 1994.

[4] J. Bosch. Design patterns as language constructs. JOOP,11(2), pp. 18-32, 1998.

[5] S. Bromling. Meta-programming with parallel designpatterns. Master's thesis, Department of ComputingScience, University of Alberta, 2002.

[6] F. Budinsky, M. Finnie, J. Vlissides, and P. Yu.Automatic code generation from design patterns. IBMSystems Journal, 35(2), pp. 151-171, 1996.

[7] TogetherSoft Corporation. TogetherSoft ControlCentertutorials: Using design patterns.www.togethersoft.com/services/tutorials/index.jsp.

[8] A. Eden, Y. Hirshfeld, and A. Yehudai. Towards amathematical foundation for design patterns. TechnicalReprort 1999-04, Department of InformationTechnology, University of Uppsala, 1999.

[9] G. Florijn, M. Meijers, and P. van Winsen. Tool supportfor object-oriented patterns. In ECOOP, Vol. 1241 ofLNCS, pp. 472-495. Springer, 1997.

[10] E. Gamma, R. Helm, R. Johnson, and J. Vlissides. DesignPatterns: Elements of Reusable Object-OrientedSoftware. Addison-Wesley, 1994.

[11] R. Johnson and B. Foote. Designing reusable classes.JOOP, 1(2), pp. 22-35, 1988.

[12] G. Kiczales, E. Hilsdale, J. Hugunin, M. Kersten, J. Palm,and W. Griswold. An overview of AspectJ. In ECOOP,volume 2072 of LNCS, pp. 327-353. Springer, 2001.

[13] S. MacDonald. From Patterns to Frameworks to ParallelPrograms. Ph.D. thesis, Department of ComputingScience, University of Alberta, 2002.

[14] S. MacDonald, D. Szafron, J. Schaeffer, and S. Bromling.Generating parallel program frameworks from paralleldesign patterns. In Euro-Par, Vol. 1900 of LNCS, pp. 95-104. Springer, 2000.

[15] M. Massingill, T. Mattson, and B. Sanders. A patternlanguage for parallel application programs. TechnicalReport CISE TR 99-022, University of Florida, 1999.

[16] M. Pollack. Code generation using javadoc.www.javaworld.com/javaworld/jw-08-2000/jw-818-javadoc_p.html, August 2000.

[17] D. Schmidt, M. Stal, H. Rohnert, and F. Buschmann.Pattern-Oriented Software Architecture: Patterns forConcurrent and Networked Objects, Vol 2. Wiley, 2000.

[18] G. Wilson. Using the Cowichan problems to assess theusability of Orca. IFIP Working Conference onProgramming Environments for Massively ParallelDistributed Systemsy, 183-193, 1994.

[19] ModelMaker Tools. Design patterns in ModelMaker.www.modelmakertools.com/mm_design_patterns.htm.