DEV Community

loading...
Cover image for Interface Segregation Principle

Interface Segregation Principle

Josué Rodríguez (He/Him)
A Honduran systems engineer trying to improve himself everyday.
・3 min read

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:

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();
Enter fullscreen mode Exit fullscreen mode

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.

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();
Enter fullscreen mode Exit fullscreen mode

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

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

Discussion (0)