Previous Section  < Free Open Study >  Next Section

5.18 The Implementation of Optional Parts of Objects

While dogs with their tails cut off can be described as dogs with bad state, they bring up an interesting design point. How do we handle optional components of a class? The tail of a dog is optional, the cocktail sauce on a shrimp cocktail is optional, etc. There are two main proposals for the design of optional components: inheritance and containment by reference. These designs are demonstrated in Figure 5.45 for both of the example domains.

Figure 5.45. Designs for optional components.


At first glance, some C++ programmers would choose inheritance as a better model because C++ would use a NULL pointer to implement dogs without their optional tail (see Figure 5.46). This would imply that the wag_tail method would need to perform a conditional test on the pointer before sending a message. Since we try to eliminate explicit case analysis, inheritance seems to be a better choice. As any SmallTalk programmer would point out, the problem is not in the design but in the choice of a multiparadigm language. In a pure language, the NULL pointer could be an object that would be sent the necessary message without a conditional test. In addition, the inheritance solution introduces an extra class (i.e., it is more complex). This type of trade-off will take up incredible amounts of time in a design critique. Neither camp can get enough of an advantage to justify one design over another.

Figure 5.46. Missing optional tails as objects.


While the trade-offs between these two methods are minimal when there is only one optional component, this is not the case when there are two or more optional components. Consider a House class, which has a heating system, a cooling system, a plumbing system, and an electrical system. All four systems are optional components of a house. Using inheritance to model this design, we end up with 17 classes: 16 derived classes and the base class House. The beauty of this design is that every time we add an optional symbol to our House class, the number of derived classes doubles (approximately). Add an optional alarm system, and we end up with 33 classes instead of 17. Add an automatic sprinkler system, and we get 65 classes. This leads to an exponential, and obvious, proliferation of classes (see Figure 5.47).

Figure 5.47. Class proliferation and optional components.


The solution is to use containment by reference whenever there are two or more optional components (see Figure 5.48). In order to be consistent, most designers will use this choice when there is only one optional component.

Figure 5.48. Nonproliferation through containment by reference.


Heuristic 5.18

Do not confuse optional containment with the need for inheritance. Modeling optional containment with inheritance will lead to a proliferation of classes.

    Previous Section  < Free Open Study >  Next Section