Sunday, February 9, 2014

Collaboration

Including the answer to: "What exactly is the difference between aggregation and composition?"

One facet of the principle of Single Responsibility is that each class is responsible for one thing. Specifically, Robert Martin defines this as each class should "have only one reason to change" (Hansel; Martin, Agile). When you apply the idea of Single Responsibility to classes in an object-oriented design then the classes must work with each other to accomplish more complex tasks, and you just forced collaboration. There are several types of relationships that classes use for collaboration. We are going to look four: dependency, association, aggregation, and composition.

Dependency is the basic form of collaboration: a class needs to do something that is not part of its responsibility so it delegates the work to an instance of another class with that responsibility. What the word delegate means here is obvious, but you need to be careful about using it. Delegation was co-opted by Henry Lieberman to describe the mechanism in a prototypical language to select a method in an object or a prototype for a message received, and that is the common use of the word (Lieberman). Delegation is a topic for another discussion!

A dependency is the relationship that is so obvious we never talk about it: uses-a. Everything depends on one class being able to use another, so it is an very important relationship. Dependency is shown in the Unified Modeling Language with a dashed line pointing from the dependent class to the dependency.


How we diagram the relationship in the UML is critical. Standardizing the way to diagram the different relationships allows everyone involved in a project to understand without hesitation exactly how the two classes will work together in the application. The key to a dependency is that the relationship is transient. The dependent class does not maintain a reference to the dependency, but it does remain dependent on it. Changes to the dependency can impact the dependent class, perhaps requiring changes in it.

So where does the reference to the dependency come from? Well, it could be passed to a method as a reference to use, or a method could locate an instance in needs at the time it is required, or a method could create a temporary instance whenever it is required.

These four relationships are progressive and build on the previous, so everything from this point on is still a dependency.

Association is a has-a relationship, and it is a dependency. Because of has-a we have an impulse to say that the association owns the other object, but that really isn't true. It's more like marriage: I have a wife, but in my culture I don't own her. So a basic association is a more permanent relationship, and a reference to the dependency is maintained in the dependent class and the class can always find the instance it is dependent on. This is sometimes referred to as a Basic Association and is shown in the UML with a solid line. By default an association is bi-directional (my wife also has me!) but directionality can be indicated with a an arrow on one end and an optional X blocking navigation to the other end. You also may add cardinality at each end (this example doesn't have that, but the next one does):


Now we get the fun part. For most folks it gets a little more confusing because we are now using three closely related concepts: association, aggregation, and composition. Aggregation is in the middle. What exactly is the difference between aggregation and composition? Or what is the difference between association and aggregation? Well, people have been arguing over this for a long time. Martin Fowler argues that aggregation does not have a standard meaning (Fowler). He gets that from the Unified Modeling Language Reference Manual where it is declared that aggregation was included in UML as a placebo, because many people had different ideas about what it means and a lot of people wanted a symbol (Rumbaugh). Robert Martin says that you can safely avoid the relationship altogether, but be careful: the reason he says this is not because the relationship is irrelevant, it is because the implementation is often the same (Martin, UML).

With all due respect to Jim Rumbaugh, Ivar Jacobson, Grady Booch, Martin Fowler, Uncle Bob Martin, and anyone else that I may have missed, I happen to think that there is a definable relationship, different from composition. My definition is based on what the UML standard declares and ideas that a lot of different people have stated, and I find my definition extremely useful to clarify my designs. I do think a lot of books either discount aggregation or fail to explain it very well, but I have no intention of getting into the argument about it because no one is ever going to win. You can accept my ideas or not, that is up to you :)

Aggregation is a dependency and a has-a relationship. The difference aggregation adds is that the parts together make a whole. Part of the confusion is that composition would be a great word to describe this! Right away this reveals the difference between a basic association and an aggregation; the basic association is not a whole made up of parts, it is just an object that uses another object. Early UML specifications define aggregation as "weak-ownership". Personally I like to think of it as parts and not ownership, because with aggregation the parts exist independently of the whole and if the whole is destroyed the parts are not usually destroyed at the same time. The UML adds a hollow (clear) diamond to the association to represent this relationship; note that the diamond goes on the end of the association that has the dependency.


So in our example an event must have a venue, the venue is part of the event. But the venue does not belong to the event; far from it: many events may share the same venue. Another way to describe it is that the event does not own the venue. In fact, since a venue should probably know about of all the events that it hosts, the relationship in this diagram is bi-directional! But be careful, while an event always has a venue, events are not really part of a venue so the relationship in the other direction is really just a basic association.

Sometimes folks misinterpret the diamond to mean that one class has a collection of other class instances. That happens because in many cases the aggregation really is made up of collection of objects. But not all the time, so don't fall into that trap!

So composition is the last relationship in our progression. Ah ha! So here is where that word gets used. My way of describing this is that composition adds ownership to the relationship. The UML represents this relationship with a filled diamond. So what is ownership? The dependent class must hold the instance of the dependency and it is responsible for it! That does not necessarily mean that it is responsible for creating it, but it is responsible for managing it through its lifetime. The dependency has no usefulness without the dependent object; if the dependent object is destroyed then the dependency will be destroyed as well.


About that object creation: in fact, through another principle named Dependency Inversion, most of the time something else is usually responsible for creating these class instances. We will talk more about that principle another day. Right now our focus has been on understanding these four collaborative relationships, recognizing when they occur in our designs, and diagramming them correctly so everyone involved can see them.

References

See the references page.

No comments:

Post a Comment