19.5. MAP TO HYPER/JThe previous section illustrated the output resulting from the integration of crosscutting themes with base design models. Of course, each output demonstrates the tangling properties aspects are designed to avoid. While composition at the design level is useful to validate the design of a crosscutting theme and its impact on a base design, it is also possible to maintain the separation to the code phase, using an appropriate implementation model. Conceptually, Theme/UML evolved from the work on subject-oriented programming [10,18]. Subject-oriented programming evolved into the concept of multi-dimensional separation of concerns (MDSOC) [24], a modelling and implementation paradigm that supports the separation of overlapping concerns along multiple dimensions of composition and decomposition. Hyper/J[1] [23] is a prototype programming environment to realize the MDSOC paradigm. It facilitates the adaptation, composition, integration, improved modularization, and non-invasive remodularization of Java software components [28]. This section gives a brief introduction to the concepts of and inputs to Hyper/J and demonstrates how Theme/UML constructs map to Hyper/J constructs.
19.5.1. Hyper/J Programming ElementsHyper/J works with Java .class files, supporting sophisticated reasoning about their modularization (and remodularization) and composition. In other words, you may describe the internals of Java. class files and describe how you would like this code to be integrated differently. Hyper/J produces new Java .class files, where structure and behavior of (parts of) input .class files are integrated as defined by the programmer. The developer provides three main inputs when using Hyper/J: hyperspace files, concern mapping files, and hypermodule files. Each hypermodule specifies a set of composition relationships between concerns. Table 19-2 describes these elements and maps them to corresponding design elements in Theme/UML.
In our attempt to map themes to Hyper/J, we have chosen to consider Hyper/J in terms of the full specification of its potential as defined in [23], and not its more limited implementation in the currently available version of the Hyper/J tool. 19.5.2. Observer in Hyper/JThe internals of the Observer theme and the Library base design may be described using hyperspace and concern mapping files, while the bind[] specification of the composition relationship may be mapped to the hypermodule file. However, at a more detailed level, mapping becomes more difficult, as we shall see. First, we look at the Java source code implementing the classes defined in the Observer composition pattern. Subject and Observer classes are defined in an Observer package as follows. (This is a code skeleton that could be generated strictly from the information provided in the crosscutting theme of Figure 19-10. Additional information would be required for a full implementation.) class Subject { Vector observers; void addObserver(Observer observer) {} void removeObserver(Observer observer) {} void aStateChange() { notify(); } void notify() { // All observers in observers are // sent update() event } } class Observer { void update() {} void start(Subject subject) { subject.addObserver(this); } void stop(Subject subject) { subject.removeObserver(this); } } Code supporting the Library design model is not illustrated here, although we assume it to be defined within a Library package. Each of these packages is considered to be in the space within which we are working; thus, we can define an appropriate hyperspace file as: hyperspace ObservedLibrary composable class Observer.*; composable class Library.*; Concern mappings may be defined as: package Observer : Feature Observer package Library : Feature Library However, this mapping of the reusable Observer composition pattern to code is not as straightforward as it may appear. Hyper/J imposes a restriction that operations to be merged must have the same signature. Theme/UML supports a mechanism for specifying considerable flexibility in the signatures of operations that are allowed to replace template operations. For our Observer example, the template operations start(.., Subject, ..) and stop(.., Subject, ..) specify that one of the parameters must be an object of type Subject but that there may be any other, arbitrary parameters. This flexibility does not map to Hyper/J. The Observer class illustrated here has defined a single Subject parameter for both the start() and stop() methods. This mapping could only occur after examining the signatures of the replacing operations, as defined in the bind[] attachment to the composition relationship. The signatures of the template operations in the Observer class were then defined appropriately. Therefore, the Observer package is not reusable as currently defined. Prior to being merged with any other package, the signatures of all methods with which start() and stop() are to be merged must be examined, with overloaded methods defined for any methods with differing signatures.[2]
We now consider the hypermodule file, which specifies how the packages should be integrated.[3] The concern mapping identified two features, Library and Observer, to be composed. A nonCorrespondingMerge relationship is defined between the two features, indicating that any elements with the same name in the different features do not correspond and are not to be merged. This is chosen because the correspondences between the Observer pattern and elements within any potential hyperslice with which it is to be merged are explicitly defined, and any name matching otherwise is coincidental.
The replacement of the Observer and Subject pattern classes with BookManager and BookCopy, respectively, can be mapped directly to equate relationships. An override relationship may be used to map the replacement of update() with the updateStatus() method. Each of the methods that are replacements for operations supplemented by crosscutting behavior has a bracket relationship defined to specify the invocation of the appropriate methods before or after its own execution. This interactive behavior is gleaned from the interactions within the composition pattern itself, not the composition relationship. One point of note: the bind[] attachment to the composition relationship supports reasoning about the meta-properties of operationsin this example, any operations whose isQuery property is false replaces the aStateChange() template operation (refer to Figure 19-11). Since there is no equivalent specification in Hyper/J, the mapping process must examine each of the operations in BookCopy and add a bracket relationship for any operation that passes the isQuery testborrow() and return() in this case. Here is the resulting hypermodule specification: hypermodule ObserverLibrary hyperslices: Feature.Library, Feature.Observer; relationships: nonCorrespondingMerge; equate class Feature.Library.BookManager Feature.Observer.Observer; equate class Feature.Library.BookCopy, Feature.Observer.Subject; override action Feature.Observer.Observer.update with Feature.Library.BookManager.updateStatus; bracket "addView" with (after Feature.Observer.Observer.start, "BookManager"); bracket "removeView" with (before Feature.Observer.Observer.stop, "BookManager"); bracket "borrow" with (after Feature.Observer.Subject.aStateChange, "BookCopy"); bracket "return" with (after Feature.Observer.Subject.aStateChange, "BookCopy"); end hypermodule As we can see, the hypermodule specifying how to integrate the Library and Observer features has the potential to provide a clean mapping from Theme/UML with simple interactions specified. However, though not illustrated with the Observer example, limitations with the bracket relationship, as currently defined, may present difficulties for more complicated interactions in the design. |