Thursday 19 January 2012

UML Class Diagrams and Class Relationships

UML Class Diagrams display relationships between classes in a given model. Here is a list of various types of class relationships and statements that can describe them:
  • generalization ("A is a kind of B")
  • realization ("A implements B")
  • dependency ("A uses B and forgets about it", "A can send message to B")
  • association ("A uses B and keeps it", "A has B")
  • aggregation ("B can be a part of A (whole)", "B can outlive A", "B can be shared between many As")
  • composition ("B is a part of A (whole)", "A owns B", "B cannot outlive A", "B belongs only to one A")
It is usually easy to distinguish generalization from realization, aggregation from composition but the border line between dependency, association and aggregation is a bit blurry. All these relationships are actually some kinds of associations which differ in subtle details and which can be redefined depending on the context. Different books and articles on UML sometimes define these relationships in a very different way ("dependency is a type of association" vs. "association is a type of dependency", "aggregation is meaningless"...) and some are even advising (with a reason!) to give up differentiating them:

"Rule 145. Don't Worry About the Diamonds: When you are deciding whether to use aggregation or composition over association, Craig Larman (2002) says it best: "If in doubt, leave it out." The reality is that many modelers will agonize over when to use aggregation when the reality is that there is very little difference between association, aggregation, and composition at the coding level." [12]

I tried to find an algorithm which goes through a set of questions (based on aforementioned statements) about the relationship between class A and class B and which at the end yields the name of that relationship.

Here is the algorithm I came up with:

ClassRelationshipsAlgorithm

Here are some descriptions of class relationships I found in various UML-related books:

Dependency

The weakest relationship between classes is a dependency relationship. Dependency between classes means that one class uses, or has knowledge of, another class. It is typically a transient relationship, meaning a dependent class briefly interacts with the target class but typically doesn't retain a relationship with it for any real length of time. Dependencies are typically read as "...uses a...". For example, if you have a class named Window that sends out a class named WindowClosingEvent when it is about to be closed, you would say "Window uses a WindowClosingEvent." You show a dependency between classes using a dashed line with an arrow pointing from the dependent class to the class that is used. [1]

A dependency exists between two elements if changes to the definition of one element (the supplier) may cause changes to the other (the client). With classes, dependencies exist for various reasons: One class sends a message to another; one class has another as part of its data; one class mentions another as a parameter to an operation. If a class changes its interface, any message sent to that class may no longer be valid. (...) The UML allows you to depict dependencies between all sorts of elements. You use dependencies whenever you want to show how changes in one element might alter other elements. [2]

(...) Your general rule should be to minimize dependencies [2]

(... ) The most common case I use for dependencies with classes is when illustrating a transient relationship, such as when one object is passed to another as a parameter. [2]

...one class uses another. This is called a dependency. The most common usage of a dependency is to show that the signature of one class' operation uses another class. [3]

Dependency—the relationship between a component and an interface through which it accesses another component. (...) dependency is visualized as a dashed line with an arrowhead. [3]

You model interaction through an interface as a dependency. [3]

Sometimes the relationship between a two classes is very weak. They are not implemented with member variables at all. Rather they might be implemented as member function arguments. (...) This is the dependency relationship. In Booch94 this was called a ‘using’ relationship. This relationship simply means that A somehow depends upon B. In C++ this almost always results in a #include. [5]

A dependency is a "using" relationship within which a change in one thing (such as a class) may affect another thing (for instance, another class). The dependent element is called the client or source; the independent element is called the supplier or target. A dependency involving two classes appears as a dashed line with a feathered arrow pointing at the supplier. [8]

The UML includes a general dependency relationship, which indicates that one element (of any kind, including classes, use cases, and so on) has knowledge of another element. It is illustrated with a dashed arrow line. In class diagrams the dependency relationship is useful to depict non-attribute visibility between classes; in other words, parameter, global, or locally declared visibility. By contrast, plain attribute visibility is shown with a regular association line and a navigability arrow. For example, the Register software object receives a return object of type ProductSpecification from the specification message it sent to a ProductCatalog. Thus Register has a short-term locally declared visibility to ProductSpecifications. And Sale receives a ProductSpecification as a parameter in the makeLineItem message; it has parameter visibility to one. These non-attribute visibilities may be illustrated with the dashed arrow line indicating a dependency relationship. [9]

Dependency relationships are indicating non-attribute visibility. [9]

Association

Associations are stronger than dependencies and typically indicate that one class retains a relationship to another class over an extended period of time. The lifelines of two objects linked by associations are probably not tied together (meaning one can be destroyed without necessarily destroying the other). Associations are typically read as "...has a...". For example, if you have a class named Window that has a reference to the current mouse cursor, you would say "Window has a Cursor". Note that there is a fine line between "...has a..." and "...owns a..." (see "Aggregation" later in this section). In this case, Window doesn't own the Cursor; Cursor is shared between all applications in the system. However, Window has a reference to it so that the Window can hide it, change its shape, etc. You show an association using a solid line between the classes participating in the relationship.[1]

The other way to notate a property is as an association. Much of the same information that you can show on an attribute appears on an association. [2]

An association is a solid line between two classes, directed from the source class to the target class. The name of the property goes at the target end of the association, together with its multiplicity. The target end of the association links to the class that is the type of the property. [2]

As an alternative to labeling an association by a property, many people, particularly if they have a data-modeling background, like to label an association by using a verb phrase so that the relationship can be used in a sentence. This is legal and you can add an arrow to the association to avoid ambiguity. Most object modelers prefer to use a property name, as that corresponds better to responsibilities and operations. [2]

(...) Because you don't need an association to a class to send a message to it, you may also need to add a dependency arrow to show messages between classes that aren't associated. [2]

When classes are connected together conceptually, that connection is called an association. [3]

When one class associates with another, each one usually plays a role within that association. You can show each class’s role by writing it near the line next to the class. In the association between a player and a team, if the team is professional, it’s an employer and the player is an employee [3]

An association declares that there can be links between instances of the associated types. It has at least two ends represented by properties, each of which is connected to the type of the end. An association declares that there can be links between instances of the associated types. [4]

There are other forms of containment that do not have whole / part implications. For example, Each Window refers back to its parent Frame. This is not aggregation since it is not reasonable to consider a parent Frame to be part of a child Window. We use the association relationship to depict this. (...) An association is nothing but a line drawn between the participating classes. (...) Once again note the name on the role. This relationship will almost certainly be implemented with a pointer of some kind. [5]

What is the difference between an aggregation and an association? The difference is one of implication. Aggregation denotes whole/part relationships whereas associations do not. However, there is not likely to be much difference in the way that the two relationships are implemented. That is, it would be very difficult to look at the code and determine whether a particular relationship ought to be aggregation or association. For this reason, it is pretty safe to ignore the aggregation relationship altogether. As the amigos said in the UML 0.8 document: “...if you don’t understand [aggregation] don’t use it.” [5]

Aggregation and Association both correspond to the Has-by-reference relationship from the Booch-94 notation. [5]

There are other types of relationships that do not fit neatly into a generalization (a-kind-of) or aggregation (a-part-of) framework. Technically speaking, these relationships are usually a weaker form of the aggregation relationship. For example, a patient schedules an appointment. It could be argued that a patient is a-part-of an appointment. However, there is a clear semantic difference between this type of relationship and one that models the relationship between doors and cars or even workers and unions. As such, they are simply considered to be associations between instances of classes. [6]

Association: Objects of one class are associated with objects of another class. [7]

Association is a weak form of connection: the objects may be part of a group, or family, of objects but they’re not completely dependent on each other. For example, consider a car, a driver, a passenger and another passenger. When the driver and the two passengers are in the car, they’re associated: they all go in the same direction, they occupy the same volume in space, and so on. But the association is loose: the driver can drop off one of the passengers to go their separate way, so that the passenger is no longer associated with the other objects. [7]

According to the UML standard, all run-time relationships come under the umbrella term association. However, most people use the term ‘association’ to mean ‘an association that isn’t aggregation or composition’. Choosing between relationships can be tricky – you need to use intuition, experience and guesswork. During analysis, you should expect the frequency of these kinds of relationship to be: association > aggregation > inheritance > composition. As far as design and implementation are concerned, the differences between association, aggregation and composition can be difficult to spot. [7]

All relationships, except inheritance, can be given an association label, indicating the nature of the association. If it’s not obvious which way the association name should be read, a black arrowhead can be used. [7]

As well as association names, we can show roles. A role indicates the part played by an object in the association – the role is shown as a label near the object that plays the role. [7]

An association is a relationship between types (or more specifically, instances of those types) that indicates some meaningful and interesting connection. [9]

In the UML associations are defined as "the semantic relationship between two or more classifiers that involve connections among their instances." [9]

Associations worth noting usually imply knowledge of a relationship that needs to be preserved for some duration — it could be milliseconds or years, depending on context. In other words, between what objects do we need to have some memory of a relationship? (...) Associations for which knowledge of the relationship needs to be preserved for some duration ("need-to-know" associations). [9]

Focus on those associations for which knowledge of the relationship needs to be preserved for some duration ("need-to-know" associations). [9]

We should add those associations which the requirements (for example, use cases) suggest or imply a need to remember, or which otherwise are strongly suggested in our perception of the problem domain. [9]

An attribute is related to an association [9]

How to Discover Associations: During system use-case interviews, look out for statements of the form X [verb] Y, where X and Y represent business objects. They often reveal associations. For example, in “A Peace Committee supervises a Case,” Peace Committee is associated with Case; the association name is supervises. [10]

An association represents a relationship that has a precisely defined meaning. The association can be labeled with the name of the association. If you want to assign a direction to the association's name, you can insert a triangle that points to the direction in which the name is supposed to be read. (...) An association indicates that objects of one class have a relationship with objects of another class, in which this connection has a specifically defined meaning (for example, "is flown with"). [11]

 Aggregation

Aggregation is a stronger version of association. Unlike association, aggregation typically implies ownership and may imply a relationship between lifelines. Aggregations are usually read as "...owns a...". For example, if you had a classed named Window that stored its position and size in a Rectangle class, you would say the "Window owns a Rectangle." The rectangle may be shared with other classes, but the Window has an intimate relationship with the Rectangle. This is subtly different from a basic association; it has a stronger connotation. However, it's not the strongest relationship you can have between classes. If the relationship is more of a whole part (class A "...is part of..." class B), you should look at composition. [1]

You show an aggregation with a diamond shape next to the owning class and a solid line pointing to the owned class. [1]

Aggregation is the part-of relationship. It's like saying that a car has an engine and wheels as its parts. This sounds good, but the difficult thing is considering what the difference is between aggregation and association. [2]

(...) Aggregation is strictly meaningless; as a result, I recommend that you ignore it in your own diagrams. If you see it in other people's diagrams, you'll need to dig deeper to find out what they mean by it. Different authors and teams use it for very different purposes. [2]

Sometimes a class consists of a number of component classes. This is a special type of relationship called an aggregation. The components and the class they constitute are in a part-whole association. [3]

Aggregation is a type of association. An aggregate object consists of a set of component objects. [3]

Aggregation is transitive [3]

The weak form of aggregation is denoted with an open diamond. This relationship denotes that the aggregate class (the class with the white diamond touching it) is in some way the “whole”, and the other class in the relationship is somehow “part” of that whole. [5]

Many different types of aggregation or composition relationships have been proposed in data modeling, knowledge representation, and linguistics. For example, a-part-of (logically or physically), a-member-of (as in set membership), containedin, related-to, and associated-with. However, generally speaking, all aggregation relationships relate parts to wholes or parts to assemblies. For our purposes, we use the a-part-of or has-parts semantic relationship to represent the aggregation abstraction. For example, a door is a-partof a car, an employee is a-part-of a department, or a department is a-part-of an organization. [6]

Like the generalization relationship, aggregation relationships can be combined into aggregation hierarchies. For example, a piston is a-part-of an engine, while an engine is a-part-of a car. [6]

Aggregation means putting objects together to make a bigger object. Manufactured items usually form aggregations: for example, a microwave is made up of a cabinet, a door, an indicator panel, buttons, a motor, a glass plate, a magnetron, and so on. Aggregations usually form a part–whole hierarchy. Aggregation implies close dependency, at least of the whole to the part; for example, a magnetron is still a magnetron if you take it out of its microwave, but the microwave would be useless without the magnetron, because it wouldn’t be able to cook anything. [7]

As suggested, the distinction between association and aggregation can be subtle. The ‘What happens if you remove one of the objects?’ test can be helpful, but it doesn’t always solve the problem: hard thinking and experience are often needed. [7]

Aggregation: Strong association – an instance of one class is made up of instances of another class. [7]

An aggregation is a special kind of association — a "whole/part" relationship within which one or more classes are parts of a larger whole. A class can be aggregated to one or more other classes.

Using aggregation is an excellent way to establish a "pecking order" of complexity, with more complex classes aggregating less complex ones. For a system of any size, doing this can only help viewers of your models more easily understand the concepts that are important to them while enabling them to ignore concepts expressed at lower levels of detail.

An aggregation appears as a line with an open diamond at one end. The class next to the diamond is the whole class; the class at the other end of the line is the part class.
[8]

An important property of aggregation is that the aggregated classes are still basically independent of the aggregating class. [8]

Shared aggregation means that the multiplicity at the composite end may be more than one, and is signified with a hollow diamond. It implies that the part may be simultaneously in many composite instances. (...) For instance, a UML package may be considered to aggregate its elements. But an element may be referenced in more than one package (it is owned by one, and referenced in others), which is an example of shared aggregation. [9]

In some cases, the presence of aggregation is obvious—usually in physical assemblies. But sometimes, it is not clear. On aggregation: If in doubt, leave it out. Here are some guidelines that suggest when to show aggregation:

Consider showing aggregation when:

• The lifetime of the part is bound within the lifetime of the composite — there is a create-delete dependency of the part on the whole.
• There is an obvious whole-part physical or logical assembly.
• Some properties of the composite propagate to the parts, such as the location.
• Operations applied to the composite propagate to the parts, such as destruction, movement, recording.

Other than something being an obvious assembly of parts, the next most useful clue is the presence of a create-delete dependency of the part on the whole.
[9]

Composition

Composition represents a very strong relationship between classes, to the point of containment. Composition is used to capture a whole-part relationship. The "part" piece of the relationship can be involved in only one composition relationship at any given time. The lifetime of instances involved in composition relationships is almost always linked; if the larger, owning instance is destroyed, it almost always destroys the part piece. UML does allow the part to be associated with a different owner before destruction, thus preserving its existence, but this is typically an exception rather than the rule. [1]

A composition relationship is usually read as "...is part of...", which means you need to read the composition from the part to the whole. For example, if you say that a window in your system must have a titlebar, you can represent this with a class named Titlebar that "...is part of..." a class named Window. [1]

You show a composition relationship using a filled diamond next to the owning class and a solid line pointing to the owned class. [1]

The general rule is that, although a class may be a component of many other classes, any instance must be a component of only one owner. The class diagram may show multiple classes of potential owners, but any instance has only a single object as its owner. [2]

The "no sharing" rule is the key to composition. Another assumption is that if you delete the "whole", it should automatically ensure that any owned parts also are deleted. [2]

Composition is a good way of showing properties that own by value, properties to value objects, or properties that have a strong and somewhat exclusive ownership of particular other components. [2]

One form of aggregation involves a strong relationship between an aggregate object and its component objects. This is called composition. The key to composition is that the component exists as a component only within the composite object. For example, a shirt is a composite of a body, a collar, sleeves, buttons, buttonholes, and cuffs. Do away with the shirt and the collar becomes useless. Sometimes a component in a composite doesn’t last as long as the composite itself. The leaves on a tree can die out before the tree does. If you destroy the tree, the leaves also die. [3]

A composition is a special kind of aggregation. In a composite object the components exist only as part of the composite. (...) A composite is a strong type of aggregation. Each component in a composite can belong to just one whole. The components of a coffee table—the tabletop and the legs—make up a composite. The symbol for a composite is the same as the symbol for an aggregation except the diamond is filled. [3]

Composition relationships are a strong form of containment or aggregation. Aggregation is a whole/part relationship. In this case, Circle is the whole, and Point is part of Circle. However, composition is more than just aggregation. Composition also indicates that the lifetime of Point is dependent upon Circle. This means that if Circle is destroyed, Point will be destroyed with it. For those of you who are familiar with the Booch-94 notation, this is the Hasby-value relationship. [5]

Composition is a strong aggregation where the composed object is inside a single composite; the composed object is usually created at the same time as the composite and can be deleted at the same time. In UML, in order to emphasize that composition is stronger than aggregation, we use a black diamond instead of a white one. [7]

Composition: Strong aggregation – the composed object can’t be shared by other objects and dies with its composer. [7]

The difference between aggregation and composition is subtle. The differences relate to object sharing and object lifetimes. Recall that a composed object can never be part of more than one composite and dies with the composite, while an aggregated object can be shared and can outlive its aggregator. Although a car trundles out of the factory with a brand new engine inside, the engine may later be replaced, because it’s worn out, so the engine doesn’t necessarily die with the car; in contrast, the body of the car is an intrinsic part of the car – it’s the soul of the car, if you like, you can’t destroy the car without destroying the body (but you could always take the engine out first). The issue of sharing is not important in this example: although the body could never be part of two cars (not legally, anyway), the engine couldn’t either. [7]

Composition is a "strong" form of aggregation. There are two differences between composition and regular aggregation, as follows: Within a composition relationship, the whole and the parts have coincident lifetimes. This means that if a particular instance of the whole is destroyed, so are the instances of the parts. A class can only belong to one composition relationship at a time as a part. [8]

Composite aggregation, or composition, means that the part is a member of only one composite object, and that there is an existence and disposition dependency of the part on the composite. [9]

Composition is signified with a filled diamond. It implies that the composite solely owns the part. [9]

Generalization 

A generalization relationship conveys that the target of the relationship is a general, or less specific, version of the source class or interface. Generalization relationships are often used to pull out commonality between difference classifiers. For example, if you had a class named Cat and a class named Dog, you can create a generalization of both of those classes called Animal. A full discussion of how and when to use generalization (especially versus interface realization) is the subject for an object-oriented analysis and design book and isn't covered here. [1]

Generalizations are usually read as "...is a...", starting from the more specific class and reading toward the general class. Going back to the Cat and Dog example, you would say "a Cat...is a...Animal" (grammar aside).[1]

You show a generalization relationship with a solid line with a closed arrow, pointing from the specific class to the general class. [1]

One class (the child class or subclass) can inherit attributes and operations from another (the parent class or superclass). The parent class is more general than the child class. (...) Object-orientation refers to this as inheritance. The UML also refers to this as generalization. (...) In the UML, you represent inheritance with a line that connects the parent class to the child class. On the part of the line that connects to the parent class, you put an open triangle that points to the parent class. This type of connection stands for the phrase "is a kind of". [3]

The generalization abstraction enables the analyst to create classes that inherit attributes and operations of other classes. The analyst creates a superclass that contains the basic attributes and operations that will be used in several subclasses. The subclasses inherit the attributes and operations of their superclass and can also contain attributes and operations that are unique just to them. For example, a customer class and an employee class can be generalized into a person class by extracting the attributes and operations they have in common and placing them into the new superclass, Person. In this way, the analyst can reduce the redundancy in the class definitions so that the common elements are defined once and then reused in the subclasses. Generalization is represented with the a-kind-of relationship, so that we say that an employee is a-kind-of person. [6]

Inheritance: A subclass inherits all of the attributes and behavior of its superclass(es). [7]

Generalization refers to a relationship between a general class (the superclass or parent) and a more specific version of that class (the subclass or child). You can think of the subclass as being a "kind of" the superclass. A generalization appears as a line with an open triangle at one end. The class next to the triangle is the parent/superclass; the class at the other end of the line is the child/subclass. [8]

Realization 

A realization is an association between a class and an interface, a collection of operations that a number of classes can use. An interface is represented as a class with no attributes. To distinguish it from a class whose attributes have been elided from the diagram, the keyword «interface» appears above the interface’s name or an uppercase “I” precedes the interface’s name. Realization is represented in the UML as a dashed line that connects the class to the interface, with an open triangle adjoining the interface and pointing to it. [3]

References:

[1] Dan Pilone, Neil Pitman, UML 2.0 in a Nutshell, O'Reilly, 2005
[2] Martin Fowler, UML Distilled: A brief guide to the standard object modeling language, 3rd edition, Addison-Wesley Professional, 2004
[3] Joseph Schmuller, Teach Yourself UML in 24 Hours, Sams Publishing, 2004
[4] OMG UML Superstructure Version 2.4.1, OMG, 2011
[5] Robert C. Martin, UML Tutorial
[6] Alan Dennis, Barbara Haley Wixom and David Tegarden, System Analysis and Design with UML Version 2.0 - An Object-Oriented Approach, John Wiley & Sons Ltd, 2005
[7] Mike O’Docherty, Object-Oriented Analysis and Design  - Understanding System Development with UML 2.0, John Wiley & Sons Ltd, 2005
[8] Kendall Scott, Fast Track UML 2.0, Apress, 2004
[9] Craig Larman, Applying UML and Patterns - An Introduction to Object-Oriented Analysis and Design and the Unified Process 2nd ed, Prentice Hall, 2001
[10] Howard Podeswa, UML for the IT Business Analyst: A Practical Guide to Object-Oriented Requirements Gathering, Thomson Course Technology PTR, 2005
[11] Patrick Grässle, Henriette Baumann, Philippe Baumann, UML 2.0 in Action - A Project-Based Tutorial, Packt Publishing Ltd, 2005
[12] Scott W. Ambler, The Elements of UML 2.0 Style, Cambridge University Press, 2005

UML Association vs Aggregation vs Composition

No comments: