A Student is enrolled in a Course.
A Professor teaches a Course.
A Degree Program requires a Course.
Whereas an association refers to a relationship between classes, the term link is used to refer to a structural relationship that exists between two specific objects (instances). Given the association "A Student is enrolled in a Course," we might have the following links:
Joe Blow (a particular Student object) is enrolled in Math 101 (a particular Course object).
Fred Schnurd (a particular Student object) is enrolled in Basketweaving 972 (a particular Course object).
Mary Smith (a particular Student object) is enrolled in Basketweaving 972 (a particular Course object; as it turns out, the same Course object that Fred Schnurd is linked to).
In the same way that an object is a specific instance of a class with its attribute values filled in, a link is a specific instance of an association with its member objects filled in, as illustrated in Figure 5-1.
Another way to think of the difference between an association and a link is that
An association is a potential relationship between objects of a certain type/class.
A link is an actual relationship between objects of those particular types.
Given any Student object X and any Course object Y, there is the potential for a link of type "is enrolled in" to exist between those two objects precisely because there is an is enrolled in association defined between the two classes that those objects belong to. In other words, associations enable links.
Most of the time, we define associations between two different classes; such associations are known as binary associations. The is enrolled in association, for example, is a binary association, because it interrelates two different classes—Student and Course. A unary, or reflexive, association, on the other hand, is between two instances of the same class; for example:
A Course is a prerequisite for (another) Course.
A Professor supervises (other) Professor(s).
Even though the two classes at either end of a reflexive association are the same, the objects are typically different instances of that class:
Math 101 (a Course object) is a prerequisite for Math 202 (a different Course object).
Professor Smith (a Professor object) supervises Professors Jones and Green (other Professor objects).
and so forth. However, although somewhat rare, there can be situations in which the same object can serve in both roles of a reflexive relationship.
Higher-order associations are possible, but rare. A ternary association, for example, involves three classes; for example, a Student takes a Course from a particular Professor, as shown in Figure 5-2.
When describing associations, however, we usually decompose higher-order associations into an appropriate number of binary associations. We can, for example, represent the preceding three-way association as three binary associations instead (see Figure 5-3):
Within a given association, each participant class is said to have a role. In the advises association (a Professor advises a Student), the role of the Professor might be said to be "advisor," and the role of the Student might be said to be "advisee." We only bother to assign names to the roles at either end of an association if it helps to clarify the model. In the is enrolled in association (a Student is enrolled in a Course), there is probably no need to invent role names for the Student and Course ends of the association, because they wouldn't add significantly to the clarity of the abstraction of which this association is a part.
For a given association type X between classes A and B, the term multiplicity refers to the number of objects of type A that may be associated with a given instance of type B. For example, a Student attends multiple Courses, but a Student has only one Professor in the role of advisor.
There are three basic categories of multiplicity, which we'll take a closer look at next: one-to-one, one-to-many, and many-to-many.
Exactly one instance of class A is related to exactly one instance of class B, no fewer, no more, and vice versa. For example:
A Professor chairs exactly one Department, and a Department has exactly one Professor in the role of chairperson.
We can further constrain an association by stating whether the participation of the class at either end is optional or mandatory. For example, we can change the preceding association to read as follows:
A Professor optionally chairs exactly one Department, but it's mandatory that a Department have exactly one Professor in the role of chairperson.
This revised version of the association is a more realistic portrayal of real-world circumstances than the previous version because, while every department in a university typically does indeed have a chairperson, not every professor is a chairperson of a department—there aren't enough departments to go around! However, it's typically true that, if a professor happens to be a chairperson of a department, then they are chairperson of only one department.
For a given single instance of class A, there can be many instances of class B related to it in a particular fashion; but, from the perspective of an object of type B, there can only be one instance of class A that is so related. For example:
A Department employs many Professors, but a Professor (usually) works for exactly one Department.
A Professor advises many Students, but a given Student has exactly one Professor as an advisor.
Note that "many" in this case can be interpreted as either "zero or more (optional)" or as "one or more (mandatory)." To be a bit more specific, we can refine the previous one-to-many associations as follows:
A Department employs one or more ("many"; mandatory) Professors, but a Professor (usually) works for exactly one Department.
A Professor advises zero or more ("many"; optional) Students, but a given Student has exactly one Professor as an advisor.
The "one" end of a one-to-many association may also be designated as either mandatory or optional. We may, for example, wish to "fine-tune" the previous association as follows if we're modeling a university setting in which students aren't required to select an advisor:
A Professor advises many (zero or more; optional) students, and a given Student may optionally have at most one advisor.
For a given single instance of class A, there can be many instances of class B related to it, and vice versa. For example:
A Student enrolls in many Courses, and a Course has many Students enrolled in it.
A given Course can have many prerequisite Courses, and a given Course can in turn be a prerequisite for many other Courses. (This is an example of a many-to-many reflexive association.)
As with one-to-many associations, "many" can be interpreted as zero or more (optional) or as one or more (mandatory); for example:
A Student enrolls in zero or more ("many"; optional) Courses, and a Course has one or more ("many"; mandatory) Students enrolled in it.
Of course, the validity of a particular association—the classes that are involved, its multiplicity, and the optional or mandatory nature of participation in the association—is wholly dependent on the real-world circumstances being modeled. If you were modeling a university in which departments could have more than one chairperson, or where students could have more than one advisor, your choice of multiplicities would differ from those used in our preceding examples.
Note that the concept of multiplicity pertains to associations, but not to links. Links always exist in pairwise fashion between two objects (or, in rare cases, between an object and itself). Therefore, multiplicity in essence defines how many links of a certain association type can originate from a given object. This is best illustrated with an example.
A Student enrolls in zero or more Courses, and a Course has one or more Students enrolled in it.
A specific Student object X can have zero, one, or more links to Course objects, but any one of those links is between exactly two objects—Student X and a single Course object. In Figure 5-4, for example:
Student X has one link (to Course A).
Student Y has four links (to Courses A, B, C, and D).
Student Z has no links to any Course objects whatsoever. (Z is taking the semester off!)
Conversely, a specific Course object A must have one or more links to Student objects to satisfy the mandatory nature and multiplicity of the association, but again, any one of those links is between exactly two objects—Course A and a single Student object. In Figure 5-4, for example:
Course A has two links (to Students X and Y).
Courses B, C, and D each have one link (to the same Student, Y).
Note, however, that once again every link is between precisely two objects: a Student and a Course. This example scenario does indeed uphold the many-to-many is enrolled in association between Student and Course; it's but one of a vast number of possible scenarios that may exist between objects belonging to the classes in question.
Just to make sure that this concept is clear, let's look at one more example, this time using the one-to-one association:
A Professor optionally chairs exactly one Department, and it's mandatory that a Department have exactly one Professor in the role of chairman. As illustrated in Figure 5-5
Professor objects 1 and 4 each have one link, to Department objects A and B, respectively.
Professor objects 2 and 3 have no such links.
Moreover, from the Department objects' perspective, each Department does indeed have exactly one link to a Professor. Therefore, this example upholds the one-to-one chairs association between Professor and Department, while further illustrating the optional nature of the Professor class's participation in such links. Again, it's but one of a vast number of possible scenarios that may exist between the classes in question.
Aggregation is a special form of association, alternatively referred to as the "consists of," "is composed of," or "has a" relationship. Like an association, an aggregation is used to represent a relationship between two classes A and B. But, with an aggregation, we're representing more than mere relationship: we're stating that an object belonging to a class A, known as an aggregate class, is composed of, or contains, component objects belonging to a class B.
For example, a car is composed of an engine, a transmission, four wheels, etc., so if Car, Engine, Transmission, and Wheel were all classes, then we could form the following aggregations:
A Car contains an Engine.
A Car contains a Transmission.
A Car is composed of many (in this case, four) Wheels.
Or, as an example related to the SRS, we can say that
A University is composed of many Schools (the School of Engineering; the School of Law; etc.).
A School is composed of many Departments.
One wouldn't typically say, however, that a Department is composed of many Professors; instead, we'd probably state that a Department employs many Professors.
Note that these aggregation statements appear awfully similar to associations, where the name of the association just so happens to be "is composed of" or "contains." That's because an aggregation is an association! So, why the fuss over trying to differentiate between aggregation and association? Do we even need to recognize that there is such a thing as an aggregation? It turns out that there are some subtle differences between aggregation and association that affect how an abstraction is rendered in code. Therefore, we'll defer
further discussion of aggregation for now, but will return to discuss these subtleties in Chapter 14.
For now, use this simple rule of thumb: when you detect a relationship between two classes A and B, and the name you're inclined to give that association implies containment—"contains," "is composed of," "is comprised of," "consists of," and so forth—then it's probably really an aggregation that you're dealing with.