The UML Profile for Framework Architectures

4.1 Unification principle adaptation by inheritance

Hook methods can be viewed as placeholders that are invoked by more complex methods, usually called template methods[1] (Wirfs-Brock and Johnson, 1990; Gamma et al., 1995; Pree, 1995;Fayad et al., 1999a, b, c). The simple idea behind hook methods is that overriding hooks allows changes of the corresponding template method's behavior without having to alter the source code of the class to which the template method belongs.

[1] Template methods must not be confused with C++ template construct this has a completely different meaning.

The essential set of framework construction principles can be derived from considering all the possible combinations of template and hook methods within one class or in two classes. The reason why this becomes feasible is that the abstract concepts of templates and hooks fade out domain-specific semantics to show clearly the means of achieving extensibility in object-oriented technology. The rest of this chapter explores the flexibility afforded by the various template hook combinations and presents the corresponding UML-F tags. We use two case studies[2] to illustrate this construction principle.

[2] The Java source code of most of the case studies in this book is available on the Web at www.UML-F.net this, and the following chapters, assume a working knowledge of the Java programming language.

Case study: Keeping the rounding of numbers flexible

Consider the convert() method in the Java class CurrencyConverter. It is a template method which invokes the hook method round() every time it has to round numbers (see Example 4.1). This hook method provides a four digit rounding after the comma as a default implementation. If the rounding policy of CurrencyConverter was to be changed without touching the existing source code, one would do so by defining a subclass that simply overrides the round() method. This elegantly changes the behavior of the convert() method without duplicating any source code. The convert() method actually calls back to the round() method. Overriding the round() method in a subclass redefines it, providing a different call-back routine to the convert() method. Note that we chose very simple rounding behavior to focus on the fundamentals of framework construction and adaptation.

Example 4.1 Currency conversion with rounding hook

public class CurrencyConverter { public void convert(...) { double result, value; switch (...) { case ... : result= round(value); break; case ... : result= round(value); } } public double round(double val) { } }

Figure 4.1 shows a standard UML diagram that expresses the subclass relationship between CurrencyConverter and a sample subclass MyCurrConv. Class MyCurrConv overrides the hook method round().

Figure 4.1. Adaptating CurrencyConverter by inheritance

Figure 4.2 illustrates schematically the basic object-oriented concept of overriding the hook method in MyCurrConv. This modification mechanism is supported directly by all object-oriented languages except C++.[3] Note that Figures4.2 (a) and (b) are not UML diagrams.

[3] In C++, methods have to be explicitly marked as dynamically bound so that overridden hooks indeed modify their template method.

Figure 4.2. (a) Template method calling its hook method, (b) hook overriding, and (c) the corresponding UML class diagram

Case study: Keeping object creation flexible

Classes that rely on currency conversion have to create the appropriate instance, either of CurrencyConverter or one of its subclasses. Example 4.2 shows a class Account that creates a CurrencyConverter object in method sampleM().

Example 4.2 Fixed creation of a currency converter

public class Account ... { public void sampleM(...) { CurrencyConverter currConv= new CurrencyConverter(); } }

If an Account object wanted to perform the currency conversion differently, (i.e. by means of another currency converter), the whole method sampleM() would have to be overridden or, even worse, the source code of sampleM() would be changed directly. To avoid this, Example 4.3 introduces the hook method createCurrConv(). The default implementation of createCurrConv() still creates an instance of CurrencyConverter. Nevertheless, the creation of a currency converter becomes flexible, as a subclass of Account just has to override the hook method to create a specific currency converter.

Example 4.3 Currency conversion with rounding hook

public class Account ... { public void sampleM(...) { CurrencyConverter currConv= createCurrConv(); } public CurrencyConverter createCurrConv() { return new CurrencyConverter (...); } }

Note that both case studies apply the same basic design principle, though the semantics of what is kept flexible differ. In case of the CurrencyConverter class, the hook method is round(). In case of Account, the hook method's name is createCurrConv(). In both cases, template and hook methods reside in one class. The fact that template and hook methods are in one class means that the behavior can only be modified by defining a subclass. So runtime adaptations are not feasible.

The Unification construction principle might be summarized as follows: generic behavior (that is, control flow that should be kept extensible) is packed into a hook method. The corresponding template and hook methods are in one class. The hook methods in the two examples above just differ in their names. Hook methods should be named according to the semantic aspects they keep flexible.

4.1.1 UML-F template and hook tags

The UML-F tags for marking template and hooks explicitly are template and hook . In the currency converter example, method convert() in class CurrencyConverter is a template method invoking round() as its hook. Figure 4.3 shows the class CurrencyConverter with these UML-F tags annotating its methods convert() and round().

Figure 4.3. UML-F tags annotating template and hook methods

These UML-F tags can be used not only to mark methods but also to mark classes and interfaces. Attaching the hook tag to a class or interface means that it contains a hook method. The template tag has an analogous meaning, though it only makes sense to attach it to classes and not to interfaces as interfaces cannot provide implementations of methods. Figure 4.4 attaches both tags to class CurrencyConverter applying the UML-F tag rule that allows the listing of several tags within one set of enclosing guillemets.

Figure 4.4. UML-F tags attached to the class name and methods

Note that the context determines what is a template or what is a hook. Figure 4.5 shows class CurrencyConverter in the context of class Account. Here, method convert() is a hook method of the calcBalance() template method in class Account. Thus, method convert() is a template method in one context and a hook method in another context. Method calcBalance() can itself also become the hook method in the context of other classes.

Figure 4.5. The context determines what is a template or hook method

Figure 4.6 attaches the name Rounding to the template and hook tags that form one logical group within one context. An explicit name for the tags provides the advantage of clear identification of related tags. Therefore the hook and template tags are of type String to allow the identification of the context they are used in.

Figure 4.6. Attaching a name to a group of related tags

Figure 4.7 shows the two tag groups Rounding and Conversion associated with the classes Account and CurrencyConverter, and some of their methods. The template tag serves as a hint for the application developer to leave the code untouched, whereas the hook tag serves as hint to adapt the code for application-specific needs. Chapter 5 describes how these UML-F annotations support framework adaptation. Tagging method convert() with both tags indicates that it depends on the context and the adaptation requirements whether it suffices to adapt only round() or the more complex convert() method instead.

Figure 4.7. Textual marking of two tag groups

The textual representation of several tag groups might get confusing quickly. To cope with numerous tag groups, a tool should allow the management of tag groups for example, by offering a menu to select a group by name. Figure 4.8 shows how the user would interact with such a tool to highlight the group of tags labeled Conversion. The diagram proposes one possible visualization of the textual representation of the UML-F tags in the previous figures, relying on UML comments.

Figure 4.8. Selecting a tag group in a UML-F based tool

Definition of the UML-F template and hook tags

The Tables 4.1 and 4.2 summarize the UML-F template and hook tags according to the UML-F tag introduction mechanism (see Chapter 3). This completes the presentation of the template and hook tags above.

Table 4.1. Definition of the UML-F hook tag

Tag hook .
Applies to class, interface, method:
Type String.
Motivation and purpose The tag makes it explicit that a method is a hook method, or that a class/interface contains a hook method. Framework adaptations often require the overriding of hook methods in subclasses. Thus the explicit marking helps to identify these framework variation points.
Informal explanation of effect If the tag is attached to a class/interface it means that the class/interface contains at least one hook method. A string such as 'groupName' in hook: groupName is optional and can be used to mark templates and hooks that belong together. The string gives the template hook group a name.
If the tag is attached to a method it means that the method can be overridden in subclasses in order to add/modify application-specific code. If the hook method is part of an interface, a class that implements the interface provides the specific method implementation. A method with a hook tag can not only be called from the associated template method but from any method.
Expansion The UML-F hook tag expands to the more basic UML-F tags adapt static or adapt dynamic . These tags only indicate that an adaptation can take place. As a hook tag always comes with a corresponding template tag, the hook tag expresses more about a variation point than the basic tags.
Discussion The hook tag is closely related to the template tag (see Table 4.2) and should never be used without a corresponding template tag. The explicit marking of framework classes/ interfaces/methods with the hook tag documents a framework's variation points.

Table 4.2 defines the template tag according to the UML-F tag introduction mechanism note the symmetry between the two tags.

Table 4.2. Definition of the UML-F template tag

Tag template .
Applies to class, method:
Type String.
Motivation and purpose The tag makes it explicit that a method is a template method or that a class contains a template method. The overriding of hook methods adapts the corresponding template method. Such template and hook methods form a logical group. Thus the explicit marking helps to identify these framework variation points.
Informal explanation of effect If the tag is attached to a class it means that the class contains at least one template method. A string such as 'groupName' in template: groupName is optional and can be used to mark template and hooks that belong together. The string gives the template hook group a name.
If the tag is attached to a method it means that the method is open for adaptations through the corresponding hook, but should not be overridden itself. If a method has both a template and a hook tag attached, then that method could possibly be overridden in the context in which it is a hook method.
Expansion The UML-F template tag expands roughly to the more basic UML-F tag fixed . The latter indicates that overriding the method is not an option. As a template tag always comes with a corresponding hook tag, the template tag expresses more about a variation point than the basic tag.
A weaker form is relevant if class T also contains a hook method, because in this case only the template method is fixed, but subclasses are required to define hook methods:
Discussion The template tag is closely related to the hook tag and should never be used without a corresponding hook tag. The explicit marking of framework classes/methods with the template tag documents a framework's variation points.

4.1.2 UML-F tags for the Unification construction principle

In the static structure of the Unification construction principle, the template method and its corresponding hook method reside in the same class that we call TH (see Figure 4.9). The procedure for deriving a tag name is to concatenate the construction principle name with each of the elements of the general structure of the construction principle. Thus, three UML-F tags annotate the Unification construction principle in a framework:

Figure 4.9. Static structure of the Unification construction principle

As a short cut we suggest using the tags Unif TH , Unif t , and Unif h . Compared to the bare-bone template and hook tags, stating explicitly that the Unification construction principle underlies a certain aspect of the framework provides more semantic information. In particular, a person who is familiar with the Unification construction principle might, for example, infer the degree of flexibility associated with that construction principle adaptations have to be accomplished in subclasses and thus require an application restart. This semantic aspect cannot be formally defined within UML-F.

Figure 4.10 applies the Unification tags to annotate class CurrencyConverter. As with the template and hook tags, any name can be defined for a group of tags. We chose the name Rounding for the Unification construction principle in this case.

Figure 4.10. UML-F annotation of a sample application of the Unification construction principle

Conceptually, UML-F tags that correspond to the static structure of a framework construction principle provide a means of pinpointing the methods and classes in a framework that apply a particular design. Figure 4.11 illustrates this aspect. The arrows express the mapping of the structural components of the Unification construction principle to their manifestation in a certain part of a framework.

Figure 4.11. Rationale behind the Unification UML-F tags

Definition of the UML-F Unification tags

Table 4.3 summarizes the UML-F Unification tags. The table documents all three tags that form a logical unit.

Table 4.3. Definition of the UML-F Unification tags

Tags Unification TH , Unification t , Unification h ; or their abbreviations Unif TH , Unif t , Unif h .
Apply to class ( Unification TH ), method ( Unification t , Unification h ); see Figure 4.9.
Type String.
Motivation and purpose The tags highlight the application of the Unification construction principle in a framework by marking the corresponding template and hook methods as well as the class to which these methods belong.
Informal explanation of effect The Unification construction principle implies that the adaptation of the framework variation point requires the overriding of the hook method.
Expansion The Unification tags Unification t and Unification h expand to the UML-F template and hook tags (see Figure 4.11).
Discussion The three UML-F Unification tags must always be used together. Several instances of the Unification h tags are possible if the Unification t method calls them all.

Категории