You are on page 1of 2

Loose coupling, tight coupling, decoupling – what is that

all about?
Given that the *coupling family of keywords stands firmly in every software architect/designer
vocabulary for over 20 years, it’s amazingly surprising how few people can tell the difference
between tightly coupled and loosely coupled pieces of code.
If you ask a coder who comes from a Java-like universe to make an assessment of the degree of
coupling of an example of code, they will start putting words interface and implementation in
every single sentence. No doubt. But is that really the essence of the problem?

I propose a very simple Test of Coupling:

1. Piece A of code is tightly coupled to Piece B of code if there exists any possible
modification to the Piece B that would force changes in Piece A in order to keep
correctness.
2. Piece A of code is not tightly coupled to Piece B of code if there is no possible
modification to the Piece B that would make a change to Piece A necessary.

Consider following example:

1
2 public class PieceB {
3 private Dependency aDependency;
4 public int countRelatedPiecesByColor(Color color) {
System.out.println("Some text");
5 return aDependency.call();
6 }
7 }
8
9 ...
10
public static void main(String[] args) {
11 PieceB myDependency = new PieceB();
12 int count = myDependency.countRelatedPiecesByColor(RED);
13}
14...
15

Line 12 with myDependency.countRelatedPiecesByColor(RED) is NOT tightly coupled to the


body of the countRelatedPiecesByColor because there is no modification that can be made to it
that would force us to change this line of code.

On the other hand the same line of code is tightly coupled to the signature of the
countRelatedPiecesByColor method as for example the change of the name of this method would
force a change to the line 12. Also, note that because of the latter line 12 is also tightly coupled
to the type defined by PieceB, and let’s assume that without any formalisms.
Let’s consider also:

1
2 public interface UserRepository {
3
User find(String email);
4
5 }
6
7
8
9 public class UserHibernateRepository implements UserRepository {
10
11 @Override
12 public User find(String email) {
return find(email, ANYWHERE);
13 }
14
15 //code omitted for conciseness
16
17}
18
19public static void main(String[] args) {
20 UserRepository repository =
MyApplicationContext.getActiveUserRepository();
21 User marek = repository.find("marek.dec@example.com");
22}
23

Here the repository.find(“marek.dec@example.com”) method call is once again tightly coupled


to the signature of the invoked method and indirectly it is also tightly coupled to the type that
defines the find method signature (i.e. UserInterface). Tight coupling can be also observed
between the UserRepository interface and UserHibernateRepository class as any change to the
find method signature will make a corresponding modification necessary.

There is no tight coupling between the find method body and the repository.find call – there is
no modification you can make to the find method body that would force you to change the call.
But what about the relation between the find method signature in the UserHibernateRepository
and line 22 in the example? Well, it turns out if you want make a modification to it, you will
have to change the implemented interface first and that would require a change to the
repository.find call too.

So, does the extra interface, an extra level of abstraction buy you anything? Surely it does. Note
that in the first example PieceB the line PieceB myDependency = new PieceB(); couples you
tightly to the type named PieceB. You won’t be allowed to take advantage of the fact the
methods are virtual and you will not be able to choose the implementations at runtime (do you
have what to choose from?). But you are equally coupled to the methods bodies in both cases,
and equally coupled to their signatures, not less and not more.

You might also like