0% completed
Coupling and its Relation to the Single Responsibility Principle (SRP)
On This Page
What is Coupling?
General Example: Tightly Connected Devices vs. Independent Devices
Where We Start: One Class Doing Two Jobs
Step 1: Move the Database Work Into Its Own Class
Step 2: Depend on an Interface Instead of a Class
Coupling and SRP
What is Coupling?
Coupling is how much one class depends on another class.
Notice that coupling is a relationship between two things. A single class on its own is neither tightly nor loosely coupled. It has nothing to be coupled to. Keep that in mind for the example below. The first version of the code has one class only, so its problem is not yet a coupling problem.
We aim for low coupling, which means a class can be changed, replaced, or tested without forcing changes to other classes. High coupling means the opposite: a change to one class forces a change to the other.
General Example: Tightly Connected Devices vs. Independent Devices
Imagine a TV and a remote that only work together. The remote controls this one TV, and the TV accepts no other remote. This is high coupling. You cannot replace one without replacing the other.
Now, imagine a universal remote that works with many devices, and a TV that accepts any remote. This is low coupling. Each device can be swapped on its own.
Where We Start: One Class Doing Two Jobs
Here is a Student class that holds student data and also knows how to write
that data to a database.
This class has two jobs. It represents a student, and it talks to a database. That is the cohesion problem from the previous lesson, not a coupling problem. There is only one class here, so there is nothing for it to be coupled to yet.
Splitting the two jobs apart is still the right first move.
Step 1: Move the Database Work Into Its Own Class
We give the database work its own class and let Student call it.
Each class now has one job, so cohesion is better. But look at what we created. There are two classes now, so we can finally talk about coupling, and the coupling we have is tight.
Student names MySqlDatabase directly. That has three costs:
- You cannot store students anywhere else without editing
Student. - You cannot test
Studentwithout a real MySQL server running. - A change to how
MySqlDatabaseis constructed forces a change inStudent.
Extracting a class moved the database work out of Student. It did not make
Student independent of it.
Step 2: Depend on an Interface Instead of a Class
We describe what Student needs as an interface, and let Student accept any
class that satisfies it. The caller decides which one to hand over.
Now Student names no database at all. It names StudentRepository, which is a
short list of methods rather than a working class. Swapping MySQL for Postgres
means writing a new repository class and passing it in. Student does not change.
Testing gets easier for the same reason. The in-memory repository above is all a unit test needs.
This move has a name, and it is the last of the five principles: depend on abstractions, not on concrete classes. Coupling is the problem that principle solves.
Coupling and SRP
The two ideas are related but they are not the same, and this example shows the difference clearly:
- Splitting responsibilities is what SRP asks for. It fixed cohesion. On its own
it left
Studenttightly coupled toMySqlDatabase. - Pointing the dependency at an abstraction is what fixed coupling. SRP does not ask for this by itself.
So SRP tends to lower coupling, because a class with one job needs fewer collaborators. It does not guarantee it. After you split a class, check what the two new classes depend on. Extracting a class can leave you with two tightly coupled classes where you had one messy class.
Rohit Bhanot
· 14 days ago
As others commented, while conceptually its trying to decouple two classes but because Student class hardcoded the database backend it created a high coupling. I think the right model would be to provide the database backend as input to Student class and use that backend to get a db_manager instance and then just call self.db_manager.save()
vkvikaskmr
· a month ago
Sounds confusing to me. In the first example one class is doing everything so there is no other class to depend on. In the second example Student depends on DatabaseManager class (not an interface) and hence there is tight coupling between them
necas.radek
· 2 years ago
Hi, I like this course and how are different principles linked together in this part. I wanted to discuss the part where implementing SRP leads to low coupling. I think it can when it is doing well, but sometimes it might have an opposite effect. For example you have legacy code with class A with many responsibilities. You separate some responsibilities into new class B. But now class B can easily become tightly coupled with A because it was created (extracted) based on requirements of A. It can happen also when junior developers try to implement SRP blindly to their design. They have bigger functionality or use case. To implement it with SRP in mind they need to create classes with different responsibilities. But each class is then tightly coupled to the rest because it was created for th
Reading Progress
0%
On This Page
What is Coupling?
General Example: Tightly Connected Devices vs. Independent Devices
Where We Start: One Class Doing Two Jobs
Step 1: Move the Database Work Into Its Own Class
Step 2: Depend on an Interface Instead of a Class
Coupling and SRP