Generalization Style
2.3.1 Overview
The generalization style of the module viewtype comes about when the is-a relation is specialized to generalization. This style comes in handy when an architect wants to support extension and evolution of architectures and individual elements. Modules in this style are defined in such a way that they capture commonalities and variations. When modules have a generalization relationship, the parent module is a more general version of the children modules. (Even though this style shares the terms parent and child with the decomposition style, they are used differently. In decomposition, a parent consists of its children. In generalization, parents and children have things in common.) The parent module owns the commonalities, and the variations are manifested in the children. Extensions can be made by adding, removing, or changing children; a change to the parent will automatically change all the children that inherit from it, which would support evolution.
Generalization implies inheritance of both interface and implementation. The child inherits structure, behavior, and constraints from its parent. Within an architectural description, the emphasis is on sharing and reusing interfaces and not so much on implementations.
2.3.2 Elements, Relations, and Properties
Table 2.3 summarizes the discussion of the characteristics of the generalization style. The element of the module generalization style is the module as defined by the module viewtype. We define a specialization of the is-a relation to be the generalization relation, whereby one module is a specialization of another module, and the second is a generalization of the first.
Elements | Module, as defined by the module viewtype. |
Relations | Generalization, which is the is-a relation as in the module viewtype. |
Properties of elements | Besides the properties defined for a module in the module viewtype, a module can have the "abstract" property, which defines a module with interfaces but no implementation. |
Properties of relations | The generalization relation can have a property that distinguishes between interface and implementation inheritance. If a module is defined as an abstract modulethe abstract propertyrestricting the generalization relation to implementation inheritance is not meaningful. |
Topology |
|
A module can be an abstract module. Such a module defines its interfaces but does not have an implementation, at least not an implementation that is executable on its own. Child modules that comply with the parent's interface provide the necessary implementations.
In the transitive closure of the generalization relation, a module that inherits information is referred to as a descendant; the module providing the information is an ancestor. Cycles are not allowed. That is, a module can not be an ancestor or a descendant of itself.
The generalization relation can be used in several ways to implement various strategies. The fact that module A inherits from module B using interface inheritance is a promise that module A complies to at least the public interface from B. Module A may also inherit and use behavior implemented by module B, but this is not defined by this type of inheritance. This strategy is useful when variants of a module with different implementations are needed and one implementation of the module can substitute for another implementation with little or no effect on other modules.
DEFINITION
Interface inheritance the definition of a new interface based on one or more previously defined interfaces. The new interface is usually a subset of the ancestors' interface(s). |
With implementation inheritance, a module inherits behavior from its ancestors and modifies it to achieve its specialized behavior. The use of the generalization relation for implementation inheritance does not guarantee that the child module complies with the interfaces of the parent module; therefore, substitutability may be violated.
2.3.3 What the Generalization Style Is For and What It's Not For
The generalization style can be used to support
- Object-oriented designs. The generalization style is the predominant means for expressing an inheritance-based object-oriented design for a system.
- Extension and evolution. It is often easier to understand how one module differs from another, well-known module rather than to try to understand a new module from scratch. Thus, generalization is a mechanism for producing incremental descriptions to form a full description of a module.
- Local change or variation. One purpose of architecture is to provide a stable global structure that accommodates local change or variation. Generalization is one approach to define commonalities on a higher level and to define variations as children of a module.
- Reuse. Finding reusable modules is a by-product of the other purposes. Suitable abstractions can be reused at the interface level alone, or the implementation can be included as well. The definition of abstract modules creates an opportunity for reuse.
2.3.4 Notations for the Generalization Style
UML
Expressing generalization lies at the heart of UML. Modules are shown as classes, although they may also be shown as subsystems, as discussed in the decomposition style. Figure 2.5 shows the basic notation available in UML. Figure 2.6 shows how UML expresses interface and implementation inheritance. Figure 2.7 shows how UML represents multiple inheritance.
Figure 2.5. UML provides two line styles to show generalization. These two diagrams are semantically identical. UML allows an ellipsis ( . . . ) in place of a submodule, indicating that a module can have more children than shown and that additional ones are likely. Module Shape is the parent of modules Polygon, Circle, and Spline, each of which is in turn a subclass, child, or descendant of Shape. Shape is more general; its children are specialized versions. Therefore, the arrow points toward the more general entity.
Figure 2.6. UML shows interface and implementation inheritance in different ways. As this figure shows, the graphics must be enhanced with textual annotations to indicate whether it is the interface or implementation that is inherited. The graphical expression of UML is not powerful enough to differentiate. For example, in diagram (a) the generalization relation with properties shown on the left side usually means what is indicated on the right side; module A inherits the implementation of module B and realizes the same interface as module B. Whereas in diagram (b), generalization using interface inheritance indicated by the «interface» textual annotation usually means what is indicated on the right side: module A realizes the same interface as module B. Finally, in diagram (c), generalization using implementation inheritance indicated by the «implementation» textual annotation usually means module A inherits the implementation of module B but realizes its own interface.
Figure 2.7. Showing multiple inheritance graphically in UML is cumbersome. As with single interface and implementation inheritance, UML's graphical notation lacks expressive power to adequately describe what is inherited. So without additional textual annotations the graphic may be ambiguous. In this figure, module C is supposed to be a subclass/child/descendant of modules D and E, which means modules D and E are parents of module C.
2.3.5 Relation to Other Styles
Inheritance relationships complement the other module viewtype relations. For complex designs, it is useful to show inheritance relationships in a diagram separate from other types of relationships, such as decomposition.
2.3.6 Examples of the Generalization Style
Figure 2.8 shows part of the module generalization view from the ECS system of Appendix A.
Figure 2.8. The primary presentation for part of an ECS module generalization view. The Ingest Data subsystem is shown as a class that is a generalization of a number of classes and provides a number of services.