The Concept of Coupling

The Concept of Coupling

Exordium

In software development, coupling refers to the degree to which modules are connected. The word's etymology goes back to Latin and means 'the joining of one thing to another' or 'fastening together.' So, when thinking about coupling, think about how objects are connected to one another.

Along with some other concepts, coupling was invented in 1968 as part of Larry Constantine's 'structured design.' Structured design focuses on mapping out 'good' programming practices aimed at maintainability and adaptability.

Tight and Loose Coupling

Coupling can either be tight or loose - sometimes referred to as high or low. Modules are considered tightly coupled when they depend highly on each other. In other words, they have high interdependence. Tightly coupled modules tend to have a tightly connected flow of information, leading to development issues down the road as objects become more and more reliant on each other. One way to avoid tight coupling is through dependency injection.

To maintain a 'structured design,' aim to design modules that are loosely coupled. This ensures that applications are being built to scale, and the objects can be reused without relying on each other. Here's a list of the different types of coupling) - ranked from tightest to loosest coupling.

Tight Coupling Example in Swift

One example of tight coupling is seen here:

class Colony {
    var queen: Bee

    init() {
        queen = QueenBee()
    }

    func formColony() {
        queen.startMating()
    }
}

Here, the Colony class is reliant on the QueenBee class. It's reliant on the QueenBee class because it is directly connected to it within the initializer. Because of the way these two objects interact, they are considered tightly coupled. If the inner-workings of the QueenBee class changed, it would then change the way that the Colony class operates. Coupling objects like this is inefficient because they should be able to be used independently.

The tight coupling situation seen above can be fixed by adding an initializer to the Colony class, passing a Bee object in as a parameter, and assigning the Queen variable from within the initializer.

class Colony {
    var queen: Bee

    init(queen: Bee) {
        self.queen = queen
    }

    func formColony() {
        queen.startMating()
    }
}

The above code separates the interdependence of the objects. Enabling them to be used independently and not be affected by each other. When code is designed as described here, it adds to the software application's structural design. When thinking in terms of structural design, programmers are intentionally building software in an efficient, scalable manner.

Coupling is inevitable in software development. It's the type and level of coupling that matters. In the above example, we see content coupling - which means one object is capable of modifying the data of another object. The 'other object' being reliant on the first object. (To dive further into the types of coupling, head over to this GeeksForGeeks article on the subject).

Conclusion

When designing modules in software applications, it's very important to think about how they are connected. Unless modules are designed intelligently and efficiently, the application will be full of spaghetti code and fail to scale.

And, what's the point in building software that doesn't scale?

(Read the original article here).