Overview of Composing Themes


With Theme's symmetric approach to separation, there is a theme for each concern in a domain. In order to specify a coherent application, you must compose the themes that address the needs of the application. The set of themes to be composed for an application may include all the themes you have designed, or different applications may require only different subsets of those themes. In all cases, Theme/UML provides a means to specify how the themes you select should be composed. Figure 6-1 illustrates the steps to follow when you are composing themes.

Figure 6-1. General view of the composition process.


In general, the steps are these:

1.

Pick the themes to be composed. Composition in Theme/UML is at the theme level of granularity.

2.

Identify the design elements within the themes that match. Up to now, we have described themes that may have specifications for the same domain concepts. Now is the time to work through matching up those concepts.

3.

Specify how the themes should be integrated. Theme/UML provides two kinds of integrationmerge and override.

4.

Specify how conflicts should be resolved between matching design elements. When themes are merged, resolving conflicts may be needed.

5.

Identify triggering behavior in a base theme to bind to templates in an aspect theme.

In this section, we give you a very brief introduction to the concepts and notations for these steps, and do not allow ourselves to get sidetracked in describing all the finer points. In the remainder of the chapter, we go through the steps again in the context of the Crystal Game application, presenting the full set of rules and features.

Pick Themes

The first thing you need to do is pick the themes to be composed for your application and draw a composition relationship between the themes you've picked. A composition relationship is a new kind of relationship defined within Theme/UML that provides you with the means to specify all the steps for composition identified above. In Figure 6-2, you can see how different compositions are possible from a pool of theme designs.

Figure 6-2. Pick themes to compose.


The notation for a composition relationship is a curved, dashed line between the design elements to be composed. In Figure 6-2, there are three examples,one for each application. As we go through the steps, we describe more notations to the line, such as arrowheads and tags, to denote further composition choices.

In Theme/UML, composition happens at the theme level of granularity, and you must first pick the themes to be composed. You can use further composition relationships between design elements inside the themes, denoting that those design elements should themselves be composed within the context of the theme composition, which we see in the next section.

There is no upper limit to the number of themes that you can compose at once.

Identify Matching Design Elements

In the Theme approach, you modularize themes based on encapsulating related requirements to handle a particular concern. As a result, you are likely to have multiple design themes with design elements that represent the same core concepts in the domain. An example of a core-concept might be the concept of a player in the Crystal Game. This might appear as a Player class in one theme, and as Participant class in another theme, but they would refer to the same concept. When you're designing an individual theme, it's useful to have a design from the perspective of the requirement(s) of that theme. When you compose themes, however, you want to be able to identify those concept-sharing elements and ensure that they are composed together. This is because when you compose themes, you are essentially taking every element from each of the input themes and putting them together into a new themeyou therefore want to ensure that the concept-sharing elements are put together in the new theme.

The simplest kind of composition occurs when there have been no common concepts designed within the themes. For example, in Figure 6-3, classes in the input themes represent different concepts in the domain and so appear separately in the composed theme. Notice also in Figure 6-3 that you can specify a name for the composed theme with a ThemeName("Name") tag on the composition relationship.

Figure 6-3. No common concepts.


It is likely, however, that your input themes do provide designs for common concepts, each from its own perspective. In a composed design, common concepts should themselves be "composed." In other words, if you have a design for ClassA with its own attributes and methods in one theme, and a design for ClassA in another theme with different attributes and methods, and both ClassAs represent the same domain concept, then there should be one ClassA in a composed design that contains all the relevant attributes and methods. You must specify a matching for such design elements, which can be done with composition relationships.

Figure 6-4 shows two ways to specify what design elements within input themes match, giving the same result. On the left side, the composition between Theme1 and Theme2 is specified with two composition relationships. The first is, as always, a composition relationship between the themes to be composed. The second composition relationship is between ClassB in Theme1 and ClassB in Theme2. This relationship identifies these two classes as matching concepts, and so ClassB appears once in the composed design. On the right side of Figure 6-4, there is only one composition relationship between the themes to be composed. However, notice that there is an additional tag on the relationship that reads match[name]. This tag indicates that classes in the themes with the same name match and should be composed. You must take the former approach, with explicit composition relationships, when classes don't have the same name but yet do represent the same concept. The latter approach is convenient when the classes have the same name.

Figure 6-4. Common concepts in themes.


You can have further composition relationships between design elements of any type that make sense to compose, but each composition relationship must be between design elements of the same type. In other words, you can only compose a theme with a theme, a class with a class, an operation with an operation, and so on. A composition relationship between design elements within the input themes indicates that the elements represent the same concept and should be composed.

Design elements other than classes can be matched with a match[name] tag like the one illustrated in Figure 6-4. Indeed, any elements of the same type with the same name that are contained in matching classes will be matched for composition purposes. For example, in Figure 6-5, attributes a and b in ClassB are matched and appear once in the composed ClassB class. Notice that attributes a and b in ClassA are not deemed to match with any attributes in ClassB, because ClassA itself does not match with ClassB.

Figure 6-5. Matching with match[name].


What happens with matching behaviors (i.e., with operations that "match") is dependent on the kind of integration you define, which we look at next.

Specify Integration

Theme/UML defines two different kinds of integration policies to determine the composition choices to be made for input elements in the composed result. Merge integration is useful when you have multiple themes that were each designed to capture its own concern (as represented by the different set of requirements for which the theme is responsible) and you want to compose these themes for the required application. If we merge themes, then all the structure and the behavior defined within each theme should exist in the composed result.

Override integration is useful when you have a new version of a theme that provides a more up-to-date specification of the requirements than an existing theme. With override integration, you can specify that one theme overrides another theme such that elements in the overriding theme replace matched elements in the overridden theme. Unmatched elements are treated in the same way as in merge integrationin other words, they are simply added to the composed result.

Merge Integration

In general, the composed result of merging themes is the union of the models in the input themes. Behavioral models such as state machines, sequence diagrams, and activity diagrams are all added to the composed result. Class models are merged into a single class model for the composed result. When composing class models, unmatched structural elements are all added to the composed class model. Matched structural elements appear once in the design. Matched operations are merged in the sense that the execution of one of the matching operations triggers the execution of all matching operations. Figure 6-6 illustrates the output of merging two simple themes.

Figure 6-6. Merge integration.


The op1() operations in the two input ClassB classes match. To indicate that the behaviors are merged, a sequence diagram is generated to specify that when a request is made to op1(), the two operations are called. Note that the input operations have been renamed to avoid a name clash both in their class model representation and in their sequence diagram specifications.

Matching classes (i.e., the two ClassB classes) and their matching attributes (a and b) appear once in the composed model. All other elements are added unchanged to the composed model.

A final interesting point to note is the arrowheads on the composition relationship. You denote merge integration with an arrowhead at all ends of the composition relationship.

Override Integration

With override integration, you are replacing matched elements in the overridden theme with their matching elements from the overriding theme. Elements from both themes that are not matched are added unchanged to the composed theme. Figure 6-7 illustrates an example.

Figure 6-7. Override integration.


The match[name] tag on the composition relationship results in a match for the ClassBs from the input themes, their attributes a, b, and their operations op1(). Notice that the specification of a in the result is public, as defined in the overriding theme (Theme1). In addition, the behavior of op1() in the result is as defined in Theme1the sequence diagram for op1() from Theme2 has been replaced with the sequence diagram for op1() from Theme1.

Notice again the arrowhead on the composition relationship. You denote override integration with an arrowhead at the overridden theme end of the composition relationship.

Finally, we have defined the following rule for override integration:

A composition relationship with override integration must be one-to-one. In other words, one design element overrides another design element.

This rule ensures that there is no conflict as to which specification the result should have for the overridden element. See later in this chapter for some more detailed rules when we specify overriding in the Crystal Game.

Specify Resolution of Conflicts

In Figure 6-7, matching elements had different specifications in the input themesfor example, attribute a is defined as public in Theme1 (the overriding theme) and as private in Theme2 (the overridden theme). This is fine when one theme overrides another, but what happens if we are merging themes and such a conflict exists in the input themes? With merge integration, matched elements such as attributes and classes appear in the result once. We therefore need a means to specify how to resolve conflicts in the specifications of matched elements.

Theme/UML provides three different mechanisms to allow you to state what should happen when a conflict arises: explicitly specifying values for a specific conflict; specifying default values for particular design constructs; and defining theme precedence. If a conflict arises during composition, Theme/UML first determines whether that conflict has been explicitly resolved, then searches for default values for the relevant construct, and finally selects the specification from the theme with the highest precedence. Each of these mechanisms is specified by means of a tag on the composition relationship, as follows.

Explicit Values

The most basic way to resolve a conflict between two design elements is to explicitly state what the specification should be in the result. Figure 6-8 illustrates an explicit resolution for attribute a in ClassB.

Figure 6-8. Conflict resolution with explicit values.


In this example, the conflict arises because of a difference in the visibility specificationClassB in Theme1 deems the attribute a to be public, while ClassB in Theme2 deems the attribute a to be private. In the resolve tag on the composition relationship, we explicitly state that ClassB.a's visibility should be private.

There is potential for any of a construct's properties[1] to conflictfor example, attributes also have a name, type, initial value, multiplicity, and so on. You can state the required values for all of these on the tag if necessary.

[1] See the UML specification for general UML constructs' properties.

You can imagine that explicitly specifying a lot of conflict resolutions for individual conflicts might become rather tedious. The next two conflict resolution mechanisms allow you to provide a more general statement of what should happen when a conflict arises.

Default Values

Instead of picking out individual design elements and specifying what their values should be in the composed result, you can specify default values for all elements of a particular type to be used only in the event of a conflict. For example, you can say that when there's a conflict in an attribute's visibility, then specify it as private, or that when there's a conflict in a class's visibility, then specify it as public, and so on. Figure 6-9 illustrates an example that captures the conflict in attribute a in ClassB.

Figure 6-9. Conflict resolution with default values.


In the resolve tag on the composition relationship, we state that in the event of a conflict in any attribute's visibility, then specify it as private. In this case, ClassB.a's visibility in the composed result is therefore private.

While you can, as with the explicit value specification, specify defaults for all properties of a construct, you are not likely to specify defaults for properties such as name or type, for example. Default values are useful only in the kinds of properties that don't identify a design element or otherwise describe the element in a material way. If you need to resolve a conflict in such properties, then explicit values (or theme precedence, coming up next) are the way to go.

Theme Precedence

The final means to resolve a conflict between elements is to say which theme's specification should have precedence. If one theme has precedence over another, then when a conflict arises between matching elements, the specification as defined in the theme with precedence is used in the result. Figure 6-10 illustrates an example.

Figure 6-10. Conflict resolution with theme precedence.


In the 1.prec tag on the composition relationship, we state that in the event of a conflict between the specifications of matching elements, the specification as defined in Theme2 should be used in the composed result. This makes ClassB.a's visibility private.

The number in the prec tag indicates an ordering for precedence. Where you are composing multiple themes, you can indicate which themes have higher precedence than others, with 1 being the highest. The specification from the theme with the highest precedence (that contains a specification for the matching element in conflict) will be used in the composed result.

Specify Binding to Aspect Themes

When you compose base themes with an aspect theme, the themes are composed with merge integration semantics. You have an additional task, though, when one of the themes is an aspect theme. An aspect theme is one where (some of) the behavior of the aspect is triggered by behavior in a base. When you are composing base themes with an aspect, you must identify what those triggers in the base are. You can achieve this with our final tag on Theme/UML's relationshipthe bind[] tag. With the bind[]tag, you essentially list all the triggers that match each of the templates in the aspect theme. Figure 6-11 illustrates a simple example.

Figure 6-11. Binding triggers to aspect templates.


Theme1 in Figure 6-11 has one piece of crosscutting behavior (op2()) that executes after any trigger. The triggers are represented in the design with a template operation called op1(). The bind attachment identifies two triggers in the Theme2 base themex() from ClassC and o() from ClassE. This design now specifies that when either ClassC.x() or ClassE.o() happens, op2() from the aspect theme should be executed afterwards.

Figure 6-12 illustrates how Theme/UML models this in the result. A sequence diagram is generated indicating the behavior that now occurs as a result of the base theme's triggers.

Figure 6-12. Base operations trigger aspect behavior.


There is another interesting point to note here. When you specify that an operation in a base theme matches a template operation in the aspect theme, you are implicitly matching the corresponding classes. As a result of this matching, the classes are merged and named from the base theme. From the example in Figures 6-11 and 6-12, ClassB has been merged with both ClassC and ClassE, separately. Because only elements within a class with templates can refer to other elements in the class (see Chapter 5), there is no confusion over which of the merged classes is intended by a reference. This means that from the example aspect, because only methods in ClassB can call methods in ClassB and refer to attributes in ClassB, then all references map to ClassC and ClassE appropriately in the result. Methods in ClassB can, of course, execute other methods in other classes in the aspect, provided that the other classes are not themselves potentially merged with multiple other classes.

Finally, you don't always have to explicitly list all the triggers in the base theme. Theme/UML provides the following means (see Table 6-1) to specify multiple replacing elements without explicit naming, including some compound operators.

Table 6-1. Multiple Element Specification

Construct

Resolution

*

All elements of this construct resolve as a replacing element. For example, ClassName.*() resolves to all operations in ClassName. Using *.* (to replace a template operation) resolves to every operation in every class in the base theme.

cc*

Similar to *, only the first characters of the replacing element must be the characters specified before the *. For example, Player.set* (to replace a template operation) resolves to every operation that starts with set in the Player class.

*cc

Similar to cc*, only the last characters of the replacing element must be the characters specified after the *.

meta:property=value

Using the metatag, you can query the values of metaproperties of the construct to determine the replacing elements. For example, meta:visibility=public resolves to every public operation.

( ) AND ( )

All elements resolved in the operands replace the template.

( ) AND NOT ( )

The AND NOT operator includes the set of operations that are resolved in the first operand and excludes the set of operations that are resolved in the second operand.




Aspect-Oriented Analysis and Design(c) The Theme Approach
Aspect-Oriented Analysis and Design: The Theme Approach
ISBN: 0321246748
EAN: 2147483647
Year: 2006
Pages: 109

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net