A part-whole association represents a relationship between a part type and a whole type. Its instances are part-whole relationships between two objects where one of them is a part of the other (the whole). The UML makes a distinction between two kinds of part-whole associations: aggregation and composition. While these two terms are defined in a pretty precise, albeit unsatisfactory, way in the UML, many software developers have a different interpretation following a terminological tradition of the C++ programming community where, unlike the parts of an 'aggregation', the parts of a 'composition' cannot exist independently of the composite that references them.
We follow the UML and improve their definition of composition by introducing a distinction between two kinds of compositions: those with separable parts and those with inseparable parts.
An aggregation is a special form of a part-whole association, where the parts of a whole can be shared with other wholes. For instance, we can model an aggregation between the classes DegreeProgram
and Course
, as shown in the following diagram, since a course is part of a degree program and a course can be shared among two or more degree programs (e.g. an engineering degree could share a C programming course with a computer science degree).
However, the concept of an aggregation with shareable parts doesn't mean much, really, so it does not have any implications on how to code the association and many developers therefore prefer not to use the white diamond in their class diagrams, but just model a plain association instead. The UML spec says: "Precise semantics of shared aggregation varies by application area and modeler".
The multiplicity of an aggregation's association end at the whole side may be any number (*) because a part may belong to, or shared among, any number of wholes.
It's amazing how much confusion exists about the distinction between the part-whole association concepts aggregation and composition. The main problem is the widespread misunderstanding (even among expert software developers and among the authors of UML) that the concept of composition implies a life-cycle dependency between the whole and its parts such that the parts cannot exist without the whole. But this view ignores the fact that there are also cases of part-whole associations with non-shareable parts where the parts can be detached from and survive the destruction of the whole.
In the UML specification document, the definition of the term "composition" has always implied non-shareable parts, but it has not been clear what is the defining characteristic of "composition", and what is merely an optional characteristic. Even in the UML version 2.5 (as of 2015), after an attempt to improve the definition of the term "composition", it remains still ambiguous and doesn't provide any guidance how to model part-whole associations with non-shareable parts where the parts can be detached from, and survive the destruction of, the whole as opposed to the case where the parts cannot be detached and are destroyed together with the whole. They say:
If a composite object is deleted, all of its part instances that are objects are deleted with it.
But at the same time they also say:
A part object may be removed from a composite object before the composite object is deleted, and thus not be deleted as part of the composite object.
This confusion points to an incompleteness of the UML definition, which does not account for life-cycle dependencies between components and composites. It's therefore important to understand how the UML definition can be enhanced, e.g. by introducing a UML stereotype for «inseparable» compositions, or by introducing a constraint keyword inseparable
for characterizing the association end at the component side.
As Martin Fowler has explained, the main issue for characterizing composition relationships is that "an object can only be the part of one composition relationship". This is also explained in the blog post UML Composition vs Aggregation vs Association by G. Bellekens. In addition to this defining characteristic of a composition (to have exclusive, or non-shareable, parts), a composition may also come with a life-cycle dependency between the composite and its components. In fact, there are two kinds of such dependencies:
Whenever a component must always be attached to a composite, or, in other words, when it has a mandatory composite, as expressed by the "exactly one" multiplicity at the composite side of the composition line, then it must either be re-used in (or re-attached to) another composite, or destroyed, when its current composite is destroyed. This is exemplified by the composition between Person
and Heart
, shown in the diagram below. A heart is either destroyed or transplanted to another person, when its owner has died.
Whenever a component must not be detached from its composite, or, in other words, when it is inseparable, then, and only then, the component has to be destroyed, when its composite is destroyed. An example of such a composition with inseparable parts is the composition between Person
and Brain
.
In summary, the life-cycle dependency created by inseparable parts only applies to specific cases of composition, but not in general. It is, therefore, not a defining characteristic. The UML spec states: "A part may be removed from a composite instance before the composite instance is deleted, and thus not be deleted as part of the composite instance."
When such a life-cycle dependency applies, it represents a special form of Existential Dependency, which implies the CASCADE deletion policy discussed in Section 2.
In the example of a Car
-Engine
composition, as shown in the following diagram, it's clearly the case that the engine can be detached from the car before the car is destroyed, in which case the engine is not destroyed and can be re-used. This is implied by the zero or one multiplicity at the composite side of the composition line.
The multiplicity of a composition's association end at the composite side is either 1 or 0..1, depending on the fact if components have a mandatory composite or not. Of course, the fact that a component is inseparable implies that it has a mandatory composite, and consequently the composite's multiplicity must be 1.
As an example of a part-whole association, we consider the association between textbooks and their chapters. Normally, a chapter of a textbook cannot be reused in another book without revisions (e.g., because it may reference other parts of the textbook). Also, it doesn't make sense to allow having textbook chapters that are not part of a textbook. We therefore model this association as an inseparable composition, as shown in the following diagram.
An object class representing an inseparable component type, like Chapter
, does not need to have a standard identifier attribute because there is no need for inseparable component objects to be referenced independently of their composite object. For referencing inseparable component objects, a composite key that is composed of the primary key of the composite type and a suitable (relatively unique) attribute of the component type is used For instance, a textbook chapter is referenced by a combination of the textbook's ISBN and the chapter's sequence number.
Since Chapter
objects, as inseparable components of Textbook
objects, cannot continue to exist when their Textbook
object ceases to exist, we need to use the CASCADE deletion policy, requiring to delete all associated chapters along with deleting a textbook, in the implementation of the Delete Textbook
operation.
An inseparable component type does not require its own CRUD data management user interfaces. Rather, all its CRUD operations are provided within the data management user interfaces of its composite type. For instance, creating, retrieving, updating and deleting textbook chapters is done within the user interfaces for managing textbook data.