16.8. Low Coupling

Assign a responsibility so that coupling remains low.

Solution


How to support low dependency, low change impact, and increased reuse?

Problem


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 will be examined. 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:

  • Changes in related classes force local changes.

  • Harder to understand in isolation.

  • Harder to reuse because its use requires the additional presence of the classes on which it is dependent.

Consider the following partial class diagram from a NextGen case study:

Example


Assume we have a 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 16.9.

Figure 16.9. Register creates Payment.


This assignment of responsibilities couples the Register class to knowledge of the Payment class.

UML notation: Note that the Payment instance is explicitly named p so that in message 2 it can be referenced as a parameter.

An alternative solution to creating the Payment and associating it with the Sale is shown in Figure 16.10.

Figure 16.10. Sale creates Payment.


Which design, based on assignment of responsibilities, supports Low Coupling? In both cases we will assume the Sale must eventually be coupled to knowledge of a Payment. Design 1, in which the Register creates the Payment, adds coupling of Register to Payment, while Design 2, in which the Sale does the creation of a Payment, does not increase the coupling. Purely from the point of view of coupling, Design Two is preferable because overall lower coupling is maintained. This an example where two patterns—Low Coupling and Creator—may suggest different solutions.

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.


Low Coupling is a principle to keep in mind during all design decisions; it is an underlying goal to continually consider. It is an evaluative principle that a designer applies while evaluating all design decisions.

Discussion


In object-oriented languages such as C++, Java, and C#, common forms of coupling from TypeX to TypeY include:

  • 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 assigning a responsibility so that its placement does not increase the coupling to such a level that it 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. The decision to derive from a superclass needs to be carefully considered since it is such a strong form of coupling. For example, suppose that objects need to be stored persistently in a relational or object database. In this case it is a relatively common design to create 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.

There is no absolute measure of when coupling is too high. What is important is that a developer can gauge the current degree of coupling, and assess if increasing it will lead to problems. In general, classes that are inherently very generic in nature, and with a high probability for reuse, should have especially low coupling.

The extreme case of Low Coupling is when there is no coupling between classes. This is not desirable because a central metaphor of object technology is a system of connected objects that communicate via messages. If Low Coupling is taken to excess, it yields a poor design because it leads to a few incohesive, bloated, and complex active objects that do all the work, with many very passive zero-coupled objects that act as simple data repositories. Some moderate degree of coupling between classes is normal and necessary to create an object-oriented system in which tasks are fulfilled by a collaboration between connected objects.

High coupling to stable elements and to pervasive elements is seldom a problem. For example, a Java J2EE application can safely couple itself to the Java libraries (java.util, and so on), because they are stable and widespread.

Contraindications


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 at some point where in fact there is no realistic motivation, this is not time well spent.

Designers have to pick their battles in lowering coupling and encapsulating things. Focus on the points of realistic high instability or evolution. For example, in the NextGen project, it is known 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.

  • not affected by changes in other components

    Benefits


  • simple to understand in isolation

  • convenient to reuse

Coupling and cohesion (described next) 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].

Background


  • Protected Variation

Related Patterns


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.220.219