To Meta or Not to Meta—That Is the Question
Metamodels and metamodeling have long been regarded as the exclusive preserve of tool vendors and academics rather than as a part of mainstream software development. End users were rarely expected to understand, let alone manipulate, metamodels and could use data-oriented technologies (e.g., CASE tools) perfectly well without knowledge of the underlying metamodel.
However, this situation is changing with the growth in the popularity of general-purpose, visual modeling languages such as the UML1 and its variant, OML.2 Because these languages are general-purpose, users are encouraged to tailor them to their own needs by effectively extending the language metamodel in some way. Moreover, the UML is just one piece of the OMG's bigger picture of standards and has its metamodel defined using the same "meta-metamodel" (the MOF in OMG terminology) as other standards, such as those for the DataWareHouse.
In all the excitement surrounding metamodeling, however, people have started to use it in ways for which it is not well-suited and where more traditional concepts of object modeling would be better employed. The inheritance mechanism, in particular, has been overlooked as a mechanism that can more appropriately support many cases where metamodeling is currently being used. In this column, we compare and contrast the mechanisms of inheritance and metamodeling, and provide some guidelines for choosing between them. We also discuss how light metamodeling mechanisms (e.g., stereotypes) fit into the picture.
CLASSES AND OBJECTS
The core concepts of object-based modeling are the class and the object. An object is viewed as being an instance-of a class, and is automatically created with the properties defined by its class. Thus, a class serves as a template from which multiple structurally identical objects can be instantiated.
As illustrated in Figure 1a, properties generally associated with a class are its attributes and operations, which, following OMG terminology, we will collectively refer to as features. Thus, the class in Figure 1a defines the features of Employee objects, each of which has a birthDate attribute, a startDate attribute, a salary attribute, and the operations age() and yearsService(). Each instance of the Employee class has values for each of these attributes, as illustrated in Figure 1b, which we read as "Bill Bloggs is an employee."
Figure 1. UML model of class Employee and one instance.
This UML model captures the fact that the object BillBloggs is an instance-of the class Employee, and has specific values for its attributes. Note: In this and the following examples, our focus is not on providing the optimal representation of every logical concept—for example, whether age should be an attribute or a method, or whether role modeling should be used in place of inheritance3—but rather on illustrating the different effects of the metamodeling and inheritance mechanisms on model elements.
The inheritance mechanism forms one of the foundations of object technology, and is the primary feature that, at the language level, distinguishes object-oriented development from object-based development. From a modeling perspective, inheritance is used to capture the situation in which one type of abstraction is "like" another type of abstraction, but with some additional properties. Thus, instead of defining all features of Employee objects directly in the class Employee, it is also possible to use inheritance to define some of them in a superclass of Employee, as illustrated in Figure 2a. We might then say in describing Figure 2a, "an employee is a person."
Figure 2. Employee class with inherited features.
The class Employee in Figure 2a has exactly the same set of features as that in Figure 1a; the only difference is that some are inherited. Employee is said to be a subclass of Person. An object BillBloggs created from the class Employee in Figure 2a is identical to one created from the class Employee in Figure 1a.
Establishing an inheritance relationship between two classes also establishes a subset relationship between instances of the classes. Thus, as illustrated in Figure 2b, instances of the subclass Employee are assumed to form a subset of the instances of the superclass Person. In other words, the object BillBloggs can be regarded as an instance of class Person as well as of class Employee.4 Hence, it is possible to interpret an instance as being of a type somewhere along an inheritance chain between the class that generated it and the root (ultimate ancestor) of that chain (often Object).
In most OO languages, inheritance has additional semantics associated with the typing and operation-binding mechanisms of the system. Establishing a subclass relationship between two classes may also establish a subtype relationship between them (as long as specialization inheritance, not implementation inheritance, is being used), allowing instances of the subclass to assume the role of instances of the supertype (inclusion polymorphism). If subclasses are allowed to override method realizations, as is usually the case, this substitutability also gives rise to a dynamic binding mechanism in which the operation realization chosen to fulfill a service is determined by the exact type of the objects fulfilling the role at runtime.
The basic idea behind OO metamodeling is to model the elements of an object model in a higher-level object model. The elements of an object model can then be viewed as instances-of the elements in the higher-level model (the metamodel). In short, the model is an instance of the metamodel, and the elements of that model are instances of the corresponding elements in the metamodel. In principle, this hierarchy could be carried on indefinitely; i.e., the metamodel is regarded as an instance of a meta-metamodel, and so on. In practice, only four levels are commonly used.
To apply this concept to the example in the previous section, we postulate Person to be at the metamodel (M2) level rather than at the model (M1) level. For the purpose of this discussion, the absolute level of Person is actually not important, only its relative level with respect to Employee. Moreover, it is irrelevant that the standard metamodel does not contain a class Person but instead contains metaclasses such as Class and Association. We are just assuming that the metamodel has been extended with a metaclass Person (e.g., through a so-called heavyweight extension or by the introduction and application of a > stereotype—see the Lightweight Extension Mechanisms section). So, assuming we now have, by whatever means, a metaclass Person in the M2 model, an Employee class is then created at the model level by instantiating the metaclass Person instead of metaclass Class (Figure 3a). We might read Figure 3a as "an employee is a person."
Figure 3. Various meanings of Is-a.
However, there is a problem here, in that the attributes of the metaclass Person (here birthDate and age()) become class-level attributes of Employee—all employees would have the same birth dates! Thus, all attributes that need to be instance specific (the usual case) must be declared in the Employee class and cannot be obtained from Person through the instance-of relationship.
THE MANY MEANINGS OF IS-A
Superficially, Figure 2a and Figure 3a would appear to be very similar (both could be read as "an employee is a person"), and if they are only given superficial consideration, then important differences may go unnoticed. This is because people have a tendency to broadly associate the phrase is-a to both metamodeling (Figure 3a) and specialization inheritance (Figure 2a) or subtyping.5,6 If one thinks about the real-life entities that the modeling elements represent, it would be perfectly reasonable, though not very precise, to say that BillBloggs is-a Employee and that Employee is-a Person. This is really knowledge representation, not subtyping, and is known as specification inheritance.5 Moreover, people would state that Employee is-a class, which is also a reasonable, though imprecise, statement, if one assumes that metaclass Person inherits from metaclass Class (subtyping again). The subtyping, knowledge representation, and instance-of relationships, therefore, may all—through a process of careless generalization—be referred to as is-a relationships.
Unfortunately, the use of sloppy language (i.e., the use of the is-a phrase) is entirely unjustified in the context of comparing inheritance to metamodeling. There are in fact quite significant differences between the inheritance and instantiation mechanisms (i.e., between Figure 2a and Figure 3a), but in certain circumstances, which we describe later, these differences are all too easily overlooked. The basic difference between the two stems from the presence or absence of transitivity. More specifically:
- The inheritance relationship is transitive.
- The instance-of relationship is not transitive.
Figure 3b illustrates the essence of the difference. Here, SalesPerson is defined as a subclass of Employee, which in turn is a subclass of Person. Since inheritance is used, this means that SalesPerson inherits all the properties of the class Employee and all the properties of the class Person—the relationship is transitive. Furthermore, a SalesPerson instance can also be regarded as both an Employee and a Person instance.
However, if the inheritance relationships in Figure 3b were replaced by instance-of relationships, so that SalesPerson was an instance-of Employee and Employee an instance-of Person, this would not be the case. Note, again, we are assuming that SalesPerson is a class, and hence, Employee would be a metaclass and Person a meta-metaclass. The fact that this has nothing to do with metaclasses and predefined meta-metaclasses in the UML is again irrelevant, as we are only discussing the principle of instantiation. In this hypothetical—and, if taken literally, absurd—example, the class SalesPerson would not receive the features of the meta-metaclass Person (at least not in the normal way in which instances of class SalesPerson would receive their individual copy of SalesPerson attributes).
The reason for this is, as we have noted, that when a metaclass is instantiated, its attributes become class-level attributes of the class (its instance). In other words, they become attributes of the class (viewed as an instance of the metaclass, i.e., from an object perspective), rather than attributes that instances of the class would receive. In C++ and Java, features with a similar quality are referred to as static.* However, there are important differences between static features in a programming language and class-level features in modeling:
- Static features are not created by instantiating a class from a metaclass but are defined and owned by a single class.
- Static features are visible from ordinary features. This is not necessarily the case with class-level features.
- When creating an instance of a class, its static features are still available to the instances, but class-level features may or may not be.
Another way to express this phenomenon is to characterize inheritance as cumulative. In other words, features are accumulated down the inheritance hierarchy, whereas instantiation transforms features into class-level features, which are thereby eliminated in further instantiation steps.
It is important to note that the nontransitivity of instantiation applies to a class's associations as well as to its features. If, in Figure 3b, the class Person had an association, the class SalesPerson would also have such an association thanks to the transitive properties of inheritance. However, if the same situation were to occur in the metamodeling analogue, that is, if the meta-metaclass Person, in Figure 3a, had an association, an assumed SalesPerson class would not have such an association. This is because this association would have become a link at the level of the metaclass Employee. On instantiating metaclass Employee to a SalesPerson class, this link becomes a class attribute of SalesPerson and is, hence, lost for instances of SalesPerson.
When made explicit in this form, the differences between the instance-of and subclass-of relationship are fairly clear. The problem that arises in practical modeling work, however, is that the instance-of relationship is rarely made explicit; instead UML encourages users to perform their metamodeling work using a third mechanism based on the concept of stereotypes.
LIGHTWEIGHT EXTENSION MECHANISMS
The idea behind the so-called built-in extension mechanism of the UML is to allow users to achieve the effects of metamodeling without having to directly manipulate the metamodel. It achieves this by means of stereotypes, which can be used to "further classify modeling elements," through the use of tagged values, which can be used to attach descriptive information to classes, and with constraints, which can be used to define rules on the use of model elements.
Unfortunately, the nature of the built-in UML extension mechanism complicates the problem of distinguishing and choosing between inheritance and metamodeling in practical development work. The first problem is that the semantics of the mechanism are rather vague and do not faithfully reproduce the full effects of direct metamodeling.7 While it is possible to define class-level attributes (and their values) in the form of tagged values, there is no way of describing class-level methods or links (i.e., instances of associations between metaclasses).
The second problem is that the notation for stereotypes bears no resemblance to the notation for either inheritance or instance-of (although it is intended to convey the meaning of the latter). As illustrated in Figure 3c, therefore, there is no visual clue to users of the intended semantics of the notation. Because the semantics are vague in any case, and the stereotype concept relatively new to the developer community, the practical result is that many users apply the stereotype mechanism without fully understanding the implications with respect to the inheritance/metamodeling distinction identified here. In particular, many users assume that the stereotype mechanism has the transitive property of inheritance, and thus expect an instance of the class Employee in Figure 3c to automatically gain the features defined for the (virtual) metaclass Person. This is compounded in many cases, as here, by the ease with which it is possible to forget that the stereotype (>) is in fact at the metalevel and does not refer to the model of a Person in the business world. In effect, the stereotype mechanism essentially represents a third opportunity to misuse the is-a phrase.
PREDEFINED MODELING ELEMENTS
An important example of the confusion between inheritance and metamodeling that can arise in the application of the UML is in the definition of predefined modeling elements. The purpose of predefined modeling elements is to define the environment in which new model elements are defined by the user, and thus to define the predefined properties that these user-created elements can attain. In the current version of the UML, these predefined constructs are known as standard elements, and take the form of stereotyped model elements (mostly classes). However, if the only mechanism used to predefine modeling elements is (lightweight) metamodeling, then none of the properties defined for the predefined elements can be attained by instances of user-defined classes because of the lack of transitivity in the instance-of relationship. These properties are lost to user data.
If some of the standard modeling elements had been defined as normal classes, and the subclass relationship used, instead of instance-of, as the means for relating standard elements to user-defined elements, the latter could transitively inherit the properties of the former, and these properties would be attained by instances. Populating the M1 level with predefined entities rather than providing predefined metaentities is not a new invention but a common technique in OO programming languages. A predefined class Object is typically defined (at the M1 level) from which new user-defined classes explicitly or implicitly inherit.
The reason for this avoidance of inheritance in the current version of the UML seems to be an overreliance on stereotypes for the definition of standard elements. Even the proposed new extension mechanism (profiles)8 seems to still neglect the role of inheritance in the definition of predefined standard elements.
The important message for practical users of the UML from the preceding discussion is to be aware that one could carelessly utilize one phrase—is-a—to refer to relationships between elements established by three (instance-of, subclass-of, and stereotype) distinct mechanisms in the UML. One has, consequently, to be sure to select the phrase that provides the desired effects. As discussed, the essential difference is the presence or absence of transitivity in the derivation of properties. Inheritance-based approaches feature transitivity, whereas metamodeling approaches, whether explicit metamodeling at the M2 level or implicit metamodeling in terms of stereotypes, are not transitive. This means that properties defined for metaclasses, or for stereotyped classes in the form of tagged values, are not attained by their instances, but properties defined for classes are attained by their subclasses. This distinction is of particular importance in the definition of profiles, where it is likely that a mix of metaelements (either stereotypes or metaclasses) and regular M1-level elements to act as superclasses is likely to provide the optimal balance.
- OMG. OMG Unified Modeling Language Specification, Version 1.3, 1999.
- Henderson-Sellers, B., C. Atkinson, and D. G. Firesmith. "Viewing the OML as a Variant of the UML," >'99—The Unified Modeling Language: Beyond the Standard, R. France and B. Rumpe, Eds., Lecture Notes in Computer Science 1723, Springer–Verlag, Berlin, 1999.
- Henderson-Sellers, B. and D. G. Firesmith. "Upgrading OML to Version 1.1: Part 2—Additional Concepts and Notation," JOOP, 11(5): 61–67, Sept. 1998.
- Henderson-Sellers, B. and I. Graham. "Metalevel Relationship Cardinalities," JOOP, 12(1): 51–58, Mar./Apr. 1999.
- Yap, L. M. and B. Henderson-Sellers. "A Semantic Model for Inheritance in Object-Oriented Systems," Procs. ASWEC'93, IREE, Sydney, 28–35, 1993.
- LaLonde, W. and J. Pugh. "Subclassing Subtyping Is-a," JOOP, 3(5): 57–62, Jan. 1991.
- Atkinson, C. "Supporting and Applying the UML Conceptual Framework," in The Unified Modeling Language: >'98: Beyond the Notation, J. Bézivin and P. A. Muller, Eds., LNCS 1618, Springer–Verlag, 21–36, 1999.
- Desfray, P., Ed. White Paper on the profile mechanism, OMG Document, 1999.
* In Java and C++, instances of a class with a static feature can access this feature. All instances share one copy of this class feature. However, this does not have to be so. From a modeling perspective, the class-level features of a class need not have any relationship to the instance-level features.