# Coupling and Cohesion

## Coupling

**Coupling** in simple words, is how much one component knows about the inner workings or inner components of another one, i.e. how much knowledge it has of the other components.

Components should be as independent as possible from other components, so that changes to component don’t heavily impact other components.

### **Tight coupling**

**Tight coupling** is where components are so *tied to one another*, that you cannot possibly change the one without changing the other.

Tight coupling would mean that your module knows the way too much about the inner workings of other modules. Modules that know too much about other modules make changes hard to coordinate and make modules brittle. If Module A knows too much about Module B, changes to the internals of Module B may break functionality in Module A.

{% hint style="danger" %}

```java
public class Foo {

    private int numberOfFoo = 0;

    public int count() {
        if (numberOfFoo == 0) {
            return new Bar().numberOfBars; // tightly coupled
        }
        return numberOfFoo;
    }
    
    public void doSomething1() {
        new Bar().firstCall(); // tightly coupled
    }
}

public class Bar {

    public int numberOfBars;

    public void firstCall() {
    }
}
```

{% endhint %}

{% hint style="danger" %}

<pre class="language-java"><code class="lang-java"><strong>public class Car  {
</strong></code></pre>

<pre class="language-java"><code class="lang-java">    public void move() {
         System.out.println("Moving by car");
    }
}

<strong>// Traveler class is tightly coupled with Car class
</strong>public class Traveler {
    private Car c = new Car(); 
    
    public void startJourney() {
         c.move();
    }
}

public static void main(String[] args) {
    Traveler traveler = new Traveler();
    traveler.move(); // Moving by car
}
</code></pre>

{% endhint %}

### **Loose coupling**

**Loose coupling** is a method of interconnecting the components in a system or network so that those *components* *depend on each other to the least extent practically possible*.

By aiming for loose coupling, you can easily make changes to the internals of modules without worrying about their impact on other modules in the system. Low coupling also makes it easier to design, write, and test code since our modules are not interdependent on each other. We also get the benefit of easy to reuse and compose-able modules. Problems are also isolated to small, self-contained units of code.

Solutions:&#x20;

* Inversion Of Control (IoC) / Dependency Injection (DI)
* [Law of Demeter (LoD)](https://gpcoder.gitbook.io/clean-code/bonus/lod-principle)

Example of using DI to implement a loosely coupled class:

{% hint style="success" %}

```java
public class Foo {

    private int numberOfFoo = 0;
    
    /**
     * Using Dependency Injection (DI)
     */
    private Bar bar;
    
    public Foo(Bar bar) {
        this.bar = bar;
    }

    public int count() {
        if (numberOfFoo == 0) {
            return bar.count();
        }
        return numberOfFoo;
    }
    
    public void firstCall() {
        bar.doSomething();
    }
}

public interface Bar {
    int count();
    void doSomething();
}

public class BarImpl implments Bar {

    private int numberOfBars;
    
    @Override
    public int count() {
        return numberOfBars;
    }

    @Override
    public void doSomething() {
    }
}
```

{% endhint %}

{% hint style="success" %}

<pre class="language-java"><code class="lang-java">public interface Vehicle {
      void move();
}

public class Car implements Vehicle {

    @Override
    public void move() {
         System.out.println("Moving by car");
    }
}

<strong>public class Traveler {
</strong><strong>
</strong><strong>    /**
</strong><strong>     * Using Dependency Injection (DI)
</strong><strong>     */
</strong>    private Vehicle vehicle;
    
    public Traveler(Vehicle vehicle) {
     this.vehicle = vehicle;
    }

    public void startJourney() {
         vehicle.move();
    }
   
}

// Easy to add new vehicle like Bike
public class Bike implements Vehicle {
    @Override
    public void move() {
         System.out.println("Moving by bike");
    }
}

public static void main(String[] args) {
    Traveler traveler = new Traveler(new Car());
    traveler.move(); // Moving by car
    
    traveler = new Traveler(new Bike());
    traveler.move(); // Moving by bike
}
</code></pre>

{% endhint %}

## **Cohesion**

Cohesion often refers to how the elements of a components belong together. Related code should be close to each other to make it highly cohesive.

There are 2 types of Cohesions: Low Cohesion and High Cohesion.

### Low Cohesion

**Low cohesion** would mean that the code that makes up some functionality is spread out all over your code-base. Not only is it hard to discover what code is related to your module, it is difficult to jump between different modules and keep track of all the code in your head.

If a class has for example three private fields and three methods; when all three methods use just one of the three fields then the class is poorly cohesive.

{% hint style="danger" %}

```java
class FooBar {
  private SomeObject bla = new SomeObject();
  private SomeObject foo = new SomeObject();
  private SomeObject bar = new SomeObject();

  public void domeSomething1() {
    bla.call();
  }

  public void domeSomething2() {
    foo.call();
  }

  public void domeSomething3() {
    bar.call();
  }
}
```

{% endhint %}

Example when a class is designed to perform many different tasks instead of focusing on any specific task then that class is called “Low Cohesive class”. This kind of approach is the bad programming design approach. It required a lot of modifications for small change.

{% hint style="danger" %}

```java
public class User {
    private String name;
    private String email;

    public String getName() {
      return name;
    }

    public void setName(String name) {
      this.name = name;
    }

    public String getEmail() {
      return email;
    }

    public void setEmail(String email) {
      this.email = email;
    }

    public void showUserDetail() {
      System.out.println("Name=" + name + ", Email=" + email);
    }

    public boolean validateEmail(String email) {
      return Pattern.match("Email Pattern", email);
    }

    public void sendEmail(String subject, String content) {
      // ...
    }
  }
```

{% endhint %}

### **High Cohesion**

By keeping **high cohesion** within our code, we end up trying DRY code and reduce duplication of knowledge in our modules. We can easily design, write, and test our code since the code for a module is all located together and works together.

If a class has for example one private field and three methods; when all three methods use this field to perform an operation then the class is very cohesive.

{% hint style="success" %}

```java
class FooBar {
  private SomeObject foo = new SomeObject();

  public void doSomething1() {
    foo.firstCall();
  }

  public void doSomething2() {
    foo.secondCall();
  }

  public void doSomething3() {
    foo.thirdCall();
  }
}
```

{% endhint %}

Example when a class is designed to perform any specific task then that class is called as “High Cohesive class”. This kind of approach is good programming design approach. It can easily maintain and less modifiabl&#x65;**.**

{% hint style="success" %}

```java
public class User {
    private String name;
    private String email;

    public String getName() {
      return name;
    }

    public void setName(String name) {
      this.name = name;
    }

    public String getEmail() {
      return email;
    }

    public void setEmail(String email) {
      this.email = email;
    }

    public void showUserDetail() {
      System.out.println("Name=" + name + ", Email=" + email);
    }
  }
  
  public class EmailValidator {
  
    public boolean validateEmail(String email) {
      return Pattern.match("Email Pattern", email);
    }
  }
  
  public class EmailSender {
    public void sendEmail(String subject, String content) {
      // ...
    }
  }
```

{% endhint %}

## Cohesion vs Coupling

* Cohesion can represent relationships *within* a component. Coupling can represent links *between* components.
* Cohesion can represent the power of *linking* functions. Coupling can represent a system that *depends* on many components.
* Cohesion evaluates the quality with which a component/module focuses on a *unit of work*. Coupling is being evaluated to what extent a component/module is *associated* with other modules.

## Maintainable Code

Writing maintainable code helps increase productivity for developers. Having highly maintainable code makes it easier to design new features and write code. Modular, component-based, and layered code increases productivity and reduces risk when making changes.

By keeping code loosely coupled, we can write code within one module without impacting other modules. And by keeping code cohesive, we make it easier to write DRY code that is easy to work with.

While you are writing and working with your code base, ask yourself:

1. How many modules am I touching to fix this or create this functionality?
2. How many different places does this change need to take place?
3. How hard is it to test my code?
4. Can we improve this by making code more loosely coupled? Can this be improved by making our code more cohesive?
