A module should not interact with too many other modules. Furthermore if a module A interacts with another module B, this interaction should be loose, which means that A should not make too many assumptions about B.
Coupling is a measure of dependency between modules. The more dependencies there are, the stronger the dependencies are, and the more assumptions are made upon other modules, the higher is the coupling.
There are different forms of couplings which can be rated according to their strength1):
The forms ranging from no coupling to stamp coupling can be considered “good” couplings. The others are rather strong.
There are also some additional forms of undesirable couplings:
If a module A interacts with a module B, there is a certain dependency between these modules. When for example A uses a certain functionality of B, then A depends on B. A makes the assumption that B provides a certain service, and moreover it makes assumptions on how this service can be used (by which mechanism, which parameters, etc.). If one of these assumptions is not true anymore because B has changed for some reason, A also has to change. So the fewer dependencies there are, the less likely it is that A stops working and has to be changed.
Furthermore if A makes many and detailed assumptions about B, there is also a high probability that A has to change despite only relying on one other module. This is because in such a case A also needs to change when only a certain detail of B changes.
But if coupling is low, there are only few assumptions between the modules which can be violated. This reduces the chance of ripple effects.
Coupling can be reduced by several technical measures (see strategies). But while these measures reduce the coupling technically, they do not necessarily reduce the logical coupling. In such a case two modules A and B may seem decoupled, but ripple effects may occur anyway because of the logical coupling. In such a case it is better to make the coupling explicit by not applying a decoupling strategy. It may also be possible to find a better suitable strategy or a better way of applying the strategy to also get rid of the logical coupling.
Furthermore note that coupling to a stable module is often no problem. The problematic cases are couplings to unstable modules. This means that applying decoupling strategies is beneficial when a coupling to an unstable module is reduced. But it may not be beneficial in the other cases.
See also section contrary principles.
Craig Larman describes how to assign responsibilities to classes using the following principles and patterns:
He calls GRASP “patterns of general principles in assigning responsibilities”4). Some of these are really patterns but others are principles. The latter are links in the above list.
|Principles In "The Pragmatic Programmer"|
|Don't Repeat Yourself||Make It Easy To Reuse||Eliminate Effects Between Unrelated Things||Program Close To The Problem Domain||Keep Knowledge in Plain Text||Write Code That Writes Code|
|Crash Early||Use Assertions to Prevent the Impossible||Use Exceptions for Exceptional Problems||Finish What You Start||Minimize Coupling Between Modules||Configure, Don't Integrate|
|Put Abstractions In Code, Details In Metadata||Always Design for Concurrency||Separate Views From Models||Abstractions Live Longer than Details|
Discuss this wiki article and the principle on the corresponding talk page.