Previous Section  < Free Open Study >  Next Section

7.2 Associations Implemented Through a Referential Attribute

Since each car is made by one and only one car manufacturer (we go back in time 30 years when car parts were not produced all over the world), the type of association is a one-to-one required association. It is best implemented as a referential attribute. This attribute could simply be the name of the car manufacturer, or for better efficiency we may want a pointer to our associated car manufacturer. In either case, it is a referential attribute, the particulars being uninteresting implementation details.

It is of particular interest to C++ programmers that the car does not "contain by reference" a car manufacturer simply because it has a pointer to it. We claim that the car is associated with its car manufacturer through a referential attribute. This indicates that C++ does not draw a distinction between two very different object-oriented relationships, containment by reference and association through a referential attribute. Is this a problem? Not for developers who design a system and then go off and implement it. It simply implies that two things in which a designer is very interested at design time are implemented as the same construct in C++. It is a major problem for authors of reverse-engineering case tools for C++. In fact, it demonstrates that it is impossible for a developer to produce a fully automated reverse-engineering case tool for C++. Since several vendors claim to offer such tools, I invite you to give them the following code and ask them how they extract a design from it.


class ATM {

    Bank* bank;

    CardReader* cardreader;

};

The ATM does not contain a bank by reference; it is associated with its bank through a referential attribute. However, the ATM is not simply associated with its card reader梚t contains it by reference. How do tools deal with this problem? The bad ones assume that since C++ does not distinguish the difference, the designer should not care about it. This is a serious deficiency. If a designer can say that a relationship is containment, then he or she can ignore the contained object at some level of design. If the relationship is only association, then he or she cannot ignore either class. In this example, we can focus on the relationship between the ATM and Bank, ignoring the CardReader (see Figure 7.1). If we assume no distinction in the two relationships, we are forced to consider all three classes at all levels of design. The better tools assume association (the simplest of the relationships) and allow a designer to update his or her picture to containment if necessary. The tool remembers the relationship once a designer assigns it by generating special comments in the code which the tool reads in when the code is reverse-engineered at a later time.

Figure 7.1. The association relationship between a car and its manufacturer.

graphics/07fig01.gif

If the car in Figure 7.1 does not use the car manufacturer, then what could be the possible use of the information stored by the referential attribute? It is true that most referential attributes are used to form uses relationships. This is a fifth variant on the implementation of the uses relationship, which we discussed in Section 4.3. In this case, we have assumed that the car is not using the car manufacturer, so of what possible use is the association information?

In all cases, the association relationship is used by some third-party class that performs an indirect uses relationship between the two classes involved in the relationship. Consider the Recall class shown in Figure 7.2. It uses the association between a car and its manufacturer in order to complete a recall operation for the car manufacturer.

Figure 7.2. A third-party class using an association relationship.

graphics/07fig02.gif

A key question might be, "Why doesn't the car manufacturer perform the recall behavior? Recalls are clearly the responsibility of the car manufacturer." While it is true that car manufacturers should be performing the necessary recall, what if the car manufacturer class is growing too complex? Our heuristic for distributing system intelligence uniformly across our top-level classes may dictate that we push some of our complexity onto a new, third-party, top-level class. The Recall class could be such a class. It exists only for better distribution of system intelligence. The ramification was the translation of a direct uses relationship between car and CarManufacturer to an indirect uses via the Recall class. These situations are fairly rare, which is why most associations are refined to uses or containment relationships.

    Previous Section  < Free Open Study >  Next Section