17.12. Low Coupling
Problem How to support low dependency, low change impact, and increased reuse?Coupling is a measure of how strongly one element is connected to, has knowledge of, or relies on other elements. An element with low (or weak) coupling is not dependent on too many other elements; "too many" is context dependent, but we examine it anyway. These elements include classes, subsystems, systems, and so on.A class with high (or strong) coupling relies on many other classes. Such classes may be undesirable; some suffer from the following problems:
- Forced local changes because of changes in related classes.
- Harder to understand in isolation.
- Harder to reuse because its use requires the additional presence of the classes on which it is dependent.
Solution Assign a responsibility so that coupling remains low. Use this principle to evaluate alternatives.Example Consider the following partial class diagram from a NextGen case study:Assume we need to create a Payment instance and associate it with the Sale . What class should be responsible for this? Since a Register "records" a Payment in the real-world domain, the Creator pattern suggests Register as a candidate for creating the Payment . The Register instance could then send an addPayment message to the Sale , passing along the new Payment as a parameter. A possible partial interaction diagram reflecting this is shown in Figure 17.18.
Figure 17.18. Register creates Payment.
Note that the Payment instance is explicitly named p so that in message 2 it can be referenced as a parameter.Figure 17.19 shows an alternative solution to creating the Payment and associating it with the Sale .
Figure 17.19. Sale creates Payment.
In practice, the level of coupling alone can't be considered in isolation from other principles such as Expert and High Cohesion. Nevertheless, it is one factor to consider in improving a design. |
- TypeX has an attribute (data member or instance variable) that refers to a TypeY instance, or TypeY itself.
- A TypeX object calls on services of a TypeY object.
- TypeX has a method that references an instance of TypeY , or TypeY itself, by any means. These typically include a parameter or local variable of type TypeY , or the object returned from a message being an instance of TypeY .
- TypeX is a direct or indirect subclass of TypeY .
- TypeY is an interface, and TypeX implements that interface.
Low Coupling encourages you to assign a responsibility so that its placement does not increase the coupling to a level that leads to the negative results that high coupling can produce.Low Coupling supports the design of classes that are more independent, which reduces the impact of change. It can't be considered in isolation from other patterns such as Expert and High Cohesion, but rather needs to be included as one of several design principles that influence a choice in assigning a responsibility.A subclass is strongly coupled to its superclass. Consider carefully any decision to derive from a superclass since it is such a strong form of coupling. For example, suppose that objects must be stored persistently in a relational or object database. In this case, you could follow the relatively common design practice of creating an abstract superclass called PersistentObject from which other classes derive. The disadvantage of this subclassing is that it highly couples domain objects to a particular technical service and mixes different architectural concerns, whereas the advantage is automatic inheritance of persistence behavior.You cannot obtain an absolute measure of when coupling is too high. What is important is that you can gauge the current degree of coupling and assess whether increasing it will lead to problems. In general, classes that are inherently generic in nature and with a high probability for reuse should have especially low coupling.The extreme case of Low Coupling is no coupling between classes. This case offends against a central metaphor of object technology: a system of connected objects that communicate via messages. Low Coupling taken to excess yields a poor designone with a few incohesive, bloated, and complex active objects that do all the work, and with many passive zero-coupled objects that act as simple data repositories. Some moderate degree of coupling between classes is normal and necessary for creating an object-oriented system in which tasks are fulfilled by a collaboration between connected objects.Contraindications High coupling to stable elements and to pervasive elements is seldom a problem. For example, a J2EE application can safely couple itself to the Java libraries (java.util, and so on), because they are stable and widespread.
Pick Your Battles
It is not high coupling per se that is the problem; it is high coupling to elements that are unstable in some dimension, such as their interface, implementation, or mere presence.This is an important point: As designers, we can add flexibility, encapsulate details and implementations, and in general design for lower coupling in many areas of the system. But, if we put effort into "future proofing" or lowering the coupling when we have no realistic motivation, this is not time well spent.You must pick your battles in lowering coupling and encapsulating things. Focus on the points of realistic high instability or evolution. For example, in the NextGen project, we know that different third-party tax calculators (with unique interfaces) need to be connected to the system. Therefore, designing for low coupling at this variation point is practical.Benefits
- not affected by changes in other components
- simple to understand in isolation
- convenient to reuse
Background Coupling and cohesion are truly fundamental principles in design, and should be appreciated and applied as such by all software developers. Larry Constantine, also a founder of structured design in the 1970s and a current advocate of more attention to usability engineering [CL99], was primarily responsible in the 1960s for identifying and communicating coupling and cohesion as critical principles [Constantine68, CMS74].Related Patterns
- Protected Variation