Interface Segregation Principle
Tags: codequality, agile, beginners, codenewbie
Published: 2021-05-24 21:46:35

The **Interface Segregation Principle** states that a client should never be forced to implement an interface that it does not use, or clients shouldn't be forced to depend on methods they do not use. 

>A client should never be forced to implement an interface that it does not use, or clients shouldn't be forced to depend on methods they do not use. 

The objective behind this principle is to remove unnecessary
code from Classes in order to reduce unexpected bugs when the Class does not have the ability to perform an action. We split actions into smaller sets so a Class only executes the actions it requires.

#Example

I'll be giving two examples, one with JavaScript since it's the programming language we've been using on the previous principles, and another general example on how to implement this principle on different programming languages.

Since JavaScript does not implement interfaces, we'll be demonstrating this principle through composition by adding pieces of functionality to the classes that need specific actions.

Imagine we have a streaming platform that has two types of user, a `FreeUser` and a `PremiumUser`, both extending from `User`. At first, the code looks something like this:

```js
class User {
  constructor(username) {
    this.username = username;
  }

  skipAd() {
    console.log(`I'm going to skip if I'm premium`);
  }

  startParty() {
    console.log(`I'm going to start a party if I'm premium`);
  }
}

class FreeUser extends User {
  constructor(username) {
    super(username);
  }

  skipAd() {
    return null;
  }

  startParty() {
    return null;
  }
}

class PremiumUser extends User {
  constructor(username) {
    super(username);
  }

  skipAd() {
    console.log(`Ad was skipped.`);
  }

  startParty() {
    console.log(`Party started, invite your friends!`);
  }
}

// The following code will execute
// and print the message
const premium = new PremiumUser(`premium_username`);
premium.skipAd();
premium.startParty();

// The following code will execute
// but return null
const free = new FreeUser(`free_username`);
free.skipAd();
free.startParty();
```

Taking into consideration that only a `PremiumUser` is able to skip ads and start parties, we are violating the **Interface Segregation Prinicple** by forcing both `User` and `FreeUser` to implement these actions. To apply the principle, we may use composition to only give these functionalities to `PremiumUser`. After applying the principle, the code would be the following.

```js
class User {
  constructor(username) {
    this.username = username;
  }
}

class FreeUser extends User {
  constructor(username) {
    super(username);
  }
}

class PremiumUser extends User {
  constructor(username) {
    super(username);
  }
}

const premiumBenefits = {
  skipAd() {
    console.log('Ad was skipped.');
  },
  startParty() {
    console.log('Party started, invite your friends!');
  },
};

Object.assign(PremiumUser.prototype, premiumBenefits);

// The following code will execute
// and print the message
const premium = new PremiumUser('premium_username');
premium.skipAd();
premium.startParty();

// The following code will throw an exception
// because a FreeUser does not implement these methods
const free = new FreeUser('free_username');
free.skipAd();
free.startParty();
```
Now every class is implementing only the functionalities that they need, adhering to the principle. 

To apply this principle to other programming languages, we may use something I like to call "cascading specialization" in which we start on the most general specialization and then, on each level of the inheritance, we add specific actions that the interface needs. The following diagram shows this idea.

![Interface Segregation Principle Diagram](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t106iwzm0mqhb55kjalm.png)

Following our `FreeUser` and `PremiumUser` example, we may have these inheritances, each one of them adding specific functioanlities depending on the subscription type.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3r9pisc3195l71r4vz3g.png)