Coupling

Coupling

Coupling is the measure of interaction between modules and should be kept to the minimum possible.
One of the modern problems with dependency injection (or inversion of control) and all the libraries that can be used, is that a class has more than what it needs injected, as all it's dependencies are resolved, this tempts the programmer to use parts of the dependencies, this then accidentally increases the coupling.
With this in mind, lets proceed to the categories of coupling generally accepted and find a solution to all our development problems.
  1. Content coupling (worst)
  2. Common coupling
  3. External coupling
  4. Control coupling
  5. Stamp coupling
  6. Data coupling(best)

Content

Content coupling is when the code of a module uses the code of another module.
In C# the use of the dreaded static modifier makes this totally possible and I've seen this type of coupling, in a few notable tech companies and when I've pointed it out they've looked at me in disbelief that anything bad can happen with this type of coupling.
So lets show what happens with a simple example:
We mistakenly read the specs and produce this static method in our utilities class:
public static string Red(string colour) {
    if (colour == "red") return "Yes it's read";
    return "No never read";
}
The project continues full steam ahead and this static method is used all over the project, in hundreds of places!
One example is:
class TestContent {
    public void doSomething() {
    string testColour = "Blue";
    Console.WriteLine(utilities.Red(testColour));
    estColour = "red";
    Console.WriteLine(utilities.Red(testColour));
    }
}
Lets reiterate this has been used from our Common namespace in multiple solutions.
A developer looks closer at the code and realises it means, 'have you read it?' (read?).
Requiring this functionality, and reading the spec., he changes the class to ...static string Read(string book)....
The project compiles and works but when everyone else compiles they're code breaks and everyone starts shouting.
I know this convoluted example isn't perfect but even a subtle change could break everyones projects.
'Isn't it the same even if it was a class', yes, but even cleverer fixes have been done, and the essence really is to design code that has the very minimum coupling.

Common

Common coupling, so called because of the Common keyword in Fortran, is when functions have access to the same global data.
An example is:
class Common {
    public static string Colour;
}
Not much wrong with the code, it's not right, but it'll do, right?
So the same developer, with a love for globals, writes some more code:
class CommonTest {
    public string ProcessColour() {

        // simulate some calc with colour here
        Thread.Sleep(1000);

        return Common.Colour;
    }
}
So other parts of the project needs to use the ProcessColour method and wants the colour returned (for some obscure reason), here's the code:
static void Main(string[] args) {
    CommonTest commonTest = new CommonTest();
    Common.Colour = "Red";
    Task.Run(() => {
        Console.WriteLine("The first colour is {0} - should be Red!", commonTest.ProcessColour());
    });
    // another process runs elsewhere in the project
    Common.Colour = "Blue";
    Task.Run(() => {
        Console.WriteLine("The first colour is {0} - should be Blue", commonTest.ProcessColour());
    });
}
The output isn't correct as expected:
The first colour is Blue - should be Red!
The first colour is Blue - should be Blue

It can be seen that the results are incorrect and this is just a simple example imagine the complexities of a large project, then the resultant mess could be disasterous.

External

External coupling, which is missed in a few coupling lists, is highly similar to Common coupling and is when an interface to a device or network (or similar) is used.
I'm not going to give an example as it would be similar to Common coupling and infer the same characteristics and problems.

Control

Control coupling, is when flags are passed from one module to another to control the flow inside that function.
I gave an example of this in my article on Cohesion and it comes under Logical cohesion, which is pretty ugly!
Control coupling is non-desirable within two aspects, both it's has a low cohesion and a reasonably high coupling.

Stamp

Stamp coupling is when too much information is supplied to a function (I'm very guilty of doing this) and can be a trade off between practability and performance.
If we have the interface:
interface ITooMuchEntity {
    string Address { get; set; }
    List Connections { get; set; }
    int DBInfo { get; set; }
    DateTime DOB { get; set; }
    int Id { get; set; }
    string Username { get; set; }
}
The the following is stamp coupling:
public void UpdateName(ITooMuchEntity entity) {

    // only uses Id and Name
    // ...
}
Really the function (method) should only receive the information it requires, that is:
public void UpdateName(int userId, string userName) {

    // only uses Id and Name
    // ...
}
It's not too high on the coupling list and can be based on the developers judgement.
Strive for data coupling but if the amount of remapping is becoming tedious and error prone then stamp coupling is acceptable.

Data

Data coupling is when only relevant data is used between modules and is the ideal coupling.
In the stamp couple example above I gave the data coupled example:
public void UpdateName(int userId, string userName) {

    // only uses Id and Name
    // ...
}
Only the actual relevant data is transferred to the method ensuring that it has the very minimum coupling to 'do it's job and no more'.

Summary

I enjoyed writing this article and with all my articles it points out a number of things that I do wrong myself and eventhough the examples are a bit convoluted, so that I can fit them onto the page, it brings home to me the complexity of developing code and the real need to design for failure.
In other words expect the worse and ensure your modules can be changed without having to change the actual code - just by extension and/or addition of replacement modules by getting your coupling as low as possible.

References

wiki
Washington
Demeter
Myers
Chap 5, The Pragmatic Programmer