A Foundation for Composition

Conrad Bock
James J. Odell


Reprinted from
Journal Of Object-Oriented Programming Vol 7, No 6. October 1994
Copyright © 1994 SIG Publications, Inc, New York, NY

Also available in Advanced Object-Oriented Analysis and Design Using UML
by James J. Odell, Cambridge University Press, 1998



This month's column describes a logical foundation for modeling those object types and relationships that have an internal part-whole, or compositional, structure. For example, a car is composed of its engine, wheels, and so on. Furthermore, the car's composition has an internal structure that defines the way its parts are connected. Expressing composition, then, implies specifying that objects can consist of other objects as well as specifying the interconnected structure of component objects.

A foundation for expressing the structure of composite objects is presented here. The computational services that can be derived from this foundation are also described. For example, instantiating the object type Car should create all parts of the Car and connect them according to the internal structure specified by the composite object type for Cars.

We propose a diagramming technique for composites based on these foundations-one which has better scaling properties than conventional representation techniques.


Foundation

Qua-types

Referring to a subtype that has been created solely because of a specialized relationship is often useful. For example, if a person is employed by an organization, the is employed by relationship can be expressed between the Person and Organization object types. However, a person who is employed by a company can also be specialized as a subtype of Person, called Employee. When an object type is subtyped solely due to such a relationship with another object type, the subtype can be referred to as a qua-type (or qua-class in KL-One terminology). It should be noted that qua-types are object types in their own right. The term qua-type is not a required term. Rather, it is a convenient way of referring to subtypes that are created solely due to a relationship with another object type.

Qua-types in Composition

The compositional relationship is one kind of relationship that can be used to create a qua-type. Composites sometimes require qua-types to use the same type of object in more than one role. For example, a car uses an engine to power the wheels; whereas, a submarine uses an engine to power the propeller. The object type Engine is subtyped into qua-types Car Engine and Submarine Engine to express more clearly how an engine is used in each situation. The powers relationship is restricted to relating Car Engine and Wheel (or Car Wheel) objects. Whereas, for Submarine Engine the restriction is Propeller. Without the qua-type, a sole connection to an Engine object type could cause confusion. In other words, an Engine would have relationships with both Wheels and Propellers-a situation which would probably not arise in the real world for a single instance of Engine.

In everyday language we frequently use the same word for both a type and its qua-type. For example, the qua-type is hidden when we say "a car has an engine," because there is a subtype of Engine that is peculiar to Cars. In other cases, the type is downplayed in favor of the qua-type. For example, "a company has employees" does not indicate that Employees are Persons. The distinction is drawn here so that there is no confusion in modeling. Compositional relationships are sometimes specialized, because two components are used differently within the same object type. For example, a car has four wheels, but only two receive power from the engine. The role Car Wheel is not fine grained enough to make this distinction, so the qua-type must apply to the specialized compositional relationships Front Wheel and Back Wheel. The qua-type derived from this relationship, Car Front Wheel, can be powered by Car Engine, while Car Back Wheel cannot. (Assume for the sake of simplicity that cars are front-wheel drive.)

Composite objects

Given the definitions above, a composite object type can be thought of as defining a collection of qua-types that are related to each other. For example, each Vehicle consists of such things as an Engine and Propelling Devices. Here an Engine has a Car Engine qua-type with a powers relationship to the Wheel qua-type, and a Submarine Engine qua-type with a powers relationship to the Propeller qua-type, and so on. The term qua-type relationship, then, refers to a relationship that connects two or more qua-types in a composite object. For instance, the powers relationship is a qua-type relationship between Submarine Engine and Propeller.

Composite relationships

Once we have composite objects we generally want to connect them together. For example, when one Vehicle is towed by another Vehicle, we want the appropriate part of one vehicle attached to the appropriate part of the other vehicle. In this way, the towed by relationship could be composed of various attached to relationships, such as a Towing Connector is attached to Towing Bar, and so on.


Services

Some services that can be provided for composites include the following:

Instantiating composites

When a composite type is instantiated, it could be requested that all its components can also be instantiated-along with their appropriate relationships. For example, if a Car is instantiated, the Car Engine and Car Wheel can be instantiated as well. Furthermore, the powers relationship between Car Engine and Car Wheel can be established. In other words, a request to create a composite can also result in creating and relating all of the components. For composite relationships, the same situation exists. For example, when one Vehicle is declared to be towed by another Vehicle, the appropriate parts can also become attached to each other.

Propagating composite operations

One operation that is commonly propagated is deletion. When a composite instance is deleted, all part instances are also deleted. Other operations may also be propagated. For example, the rotate operation on a Car would be propagated to its parts. However, not every operation need be propagated. For instance, painting a Car does not necessitate painting all its parts-only the external ones.

Maintaining connections between parts

When a component is removed from a composite, it is no longer connected to the other parts either. For example, if you remove the engine from a car, it should no longer be connected to the wheels. Likewise, when you make the engine part of the car again, it should be connected to the wheels automatically.

Enforcing invariant compositions

Sometimes a composite can consist of components that may not change. For instance, the Partners that are part of a Marriage may not be changed. Furthermore, if one Partner leaves, the Marriage is terminated. Here, the termination of a part results in termination of the whole.

Adding components

When components are subtyped, additional types and qua-types can be created. For example, Race Car can be subtyped from Car, requiring additional parts such as Spoilers, etc. Furthermore, the Engine object type might be qua-typed as a Race Engine. [See html demo.]

Defining composites from existing instances

An easy way to define a composite is to start with an existing set of interconnected instances. This service lets you select a collection of instances and their connections and get a composite object type that mimics its structure. In other words, you can instantiate the new composite type and get a copy of the original set of instances.


Diagrams

If we try to diagram composites without using a shorthand for qua-types, the diagrams can become unwieldy. For example, Figure 1 shows a diagram using compositional relationships along with ordinary relationships. (The unmarked lines are ordinary relationships.) The user is forced to diagram the qua-types explicitly. Engine is qua-typed for its different uses in Cars and Submarines. Axles are subtyped because only the front receives power in a Car. Wheels are then subtyped according to the Axle. Submarines use different Engines and are also qua-typed. The complexity of the diagram in this small example grows each time a new composite is expressed.

One technique for simplifying the diagram in Figure 1 is illustrated in Figures 2 and 3, where the user relates the parts as necessary within the context of a Car or a Submarine. For example, Figure 2 depicts some of the basic parts required for a Car. The figure presents the qua-types not as rectangles, but in parentheses above their respective supertypes. For instance, while Engine is presented as a rectangle, its Car Engine qua-type is declared in parentheses above the Engine rectangle. In this context, the powers and drives relationships are assumed to associate the qua-types. Figure 3 employs this same technique for Submarine.


Extensions

Composition can be extended to include some other features.

Attribute propagation

If a certain part of the composite should have a particular attribute, such as Owner, the same attribute would probably apply as well to the components. The composite object type can record this information so that instantiating Car will instantiate Engine and propagate the owner property to the Engine. Propagation is similar to the inheritance implemented for subtypes. It should be noted that not every property of a composite is propagated to its components. It must be defined on a property-by-property basis.

Partial composite instantiation

Since components can themselves have components, it is possible to create a large number of instances when instantiating a composite. For example, if you have a composite of a factory, you probably do not want to instantiate the enterprise down to the nuts and bolts. You can specify the number of levels down that you want to instantiate. Perhaps this can be further extended to indicate this on a component-by-component basis.

Ports

When creating a composite object type, you may want to limit which qua-types are available to make a composite relationship. For example, when connecting an engine to the rest of a car, you do not want the pistons connected to anything outside the engine. You can declare some qua-types to be ports-making them available to other composite relationships. For example, the spark plugs could be declared ports. The other qua-types can be considered internal.

Implicit composite relationships

Frequently, the relationships between composite objects are idiosyncratic enough that they do not warrant a new relationship for each connection. For example, if you look at an electrical schematic, you will see ports on transistors connected directly to each other, rather than connections between entire transistors. The qua-types for the schematic are standardized (and therefore have a composite type for instantiation), but the relationships are not.



Return to Bock Online
If you have any comments on this page or problems, contact Conrad Bock (conrad dot bock at nist dot gov)