Design Principle: Interface Segregation Principle(ISP)

Summary

Principle NameInterface Segregation Principle
AcronymISP
Principle Type SOLID
TaglineCreate fine-grained interfaces, instead of big fat interfaces.
Implementing
Design Patterns
Adapter Pattern
Decorator Pattern
Facade Pattern
Observer Pattern
Proxy Pattern
Related Principles Single Responsibility Principle(SRP)
Open/Closed Principle(OCP)
Liskov Substitution Principle(LSP)
Dependency Inversion Principle(DIP)

Definition

Interface Segregation Principle(ISP) is the fourth principle of the SOLID Principles.

While coding over time we might create big bloating interfaces, with many methods. Then when a class tries to implement those interfaces, it has to deal with a lot of those unnecessary methods, which we do not need for the class.

These fat interfaces include unnecessary methods, which are not required for most of the classes. This ISP gives us guidelines deal with these fat interfaces.

The Interface Segregation Principle says-

We should create smaller and more specific interfaces, instead of having large monolithic interface with many methods.

Each interface should only contain methods that are relevant to the purpose of the interface. Then classes can implement one or more of those interfaces are required. Also, a class should only implement the interface(s) which are required.

The purpose of this principle is that- the client should not be forced to depend on methods, it does not use. Also, a client should not be forced to implement/depend on interfaces, that it does not use.

By avoiding those big fat interfaces, and instead creating multiple smaller interfaces, we ensure flexibility and frictionless changes in the future.

Implementation

Let’s first see what a fat interface looks like. Check the interface below where we are managing operations by user.

But it includes all types of operations for the user, like sending notifications, and reports.

If some class just needs to implement the CRUD operations for a user, and it implements the interface, then it has to also implement(probably leave blank) those notification and report-related methods.

// UserManager.java
public interface UserManager {
    void createUser(String username, String password);
    void deleteUser(int userId);
    void updateUser(int userId, String username, String password);
    void sendEmailNotification(int userId, String subject, String body);
    void sendSmsNotification(int userId, String message);
    void generateUserReport(int userId);
}
Java
from abc import ABC, abstractmethod

class UserManager(ABC):
    @abstractmethod
    def create_user(self, username: str, password: str):
        pass

    @abstractmethod
    def delete_user(self, user_id: int):
        pass

    @abstractmethod
    def update_user(self, user_id: int, username: str, password: str):
        pass

    @abstractmethod
    def send_email_notification(self, user_id: int, subject: str, body: str):
        pass

    @abstractmethod
    def send_sms_notification(self, user_id: int, message: str):
        pass

    @abstractmethod
    def generate_user_report(self, user_id: int):
        pass
Python
package main

// UserManager interface
type UserManager interface {
    CreateUser(username string, password string)
    DeleteUser(userId int)
    UpdateUser(userId int, username string, password string)
    SendEmailNotification(userId int, subject string, body string)
    SendSmsNotification(userId int, message string)
    GenerateUserReport(userId int)
}
Go
<?php

// UserManager.php
interface UserManager {
    public function createUser(string $username, string $password);
    public function deleteUser(int $userId);
    public function updateUser(int $userId, string $username, string $password);
    public function sendEmailNotification(int $userId, string $subject, string $body);
    public function sendSmsNotification(int $userId, string $message);
    public function generateUserReport(int $userId);
}
PHP
// UserManager.ts
interface UserManager {
    createUser(username: string, password: string): void;
    deleteUser(userId: number): void;
    updateUser(userId: number, username: string, password: string): void;
    sendEmailNotification(userId: number, subject: string, body: string): void;
    sendSmsNotification(userId: number, message: string): void;
    generateUserReport(userId: number): void;
}
TypeScript

We should break down the interface into multiple fine-grained, smaller interfaces. Here we have broken this fat into 3 small interfaces.

Check the code below-

// User.java
public interface User {
    void createUser(String username, String password);
    void deleteUser(int userId);
    void updateUser(int userId, String username, String password);
}

// UserNotification.java
public interface UserNotification {
    void sendEmailNotification(int userId, String subject, String body);
    void sendSmsNotification(int userId, String message);
}

// UserReporting.java
public interface UserReporting {
    void generateUserReport(int userId);
}
Java
from abc import ABC, abstractmethod

class User(ABC):
    @abstractmethod
    def create_user(self, username: str, password: str):
        pass

    @abstractmethod
    def delete_user(self, user_id: int):
        pass

    @abstractmethod
    def update_user(self, user_id: int, username: str, password: str):
        pass


class UserNotification(ABC):
    @abstractmethod
    def send_email_notification(self, user_id: int, subject: str, body: str):
        pass

    @abstractmethod
    def send_sms_notification(self, user_id: int, message: str):
        pass


class UserReporting(ABC):
    @abstractmethod
    def generate_user_report(self, user_id: int):
        pass
Python
package main

// User interface
type User interface {
    CreateUser(username string, password string)
    DeleteUser(userId int)
    UpdateUser(userId int, username string, password string)
}

// UserNotification interface
type UserNotification interface {
    SendEmailNotification(userId int, subject string, body string)
    SendSmsNotification(userId int, message string)
}

// UserReporting interface
type UserReporting interface {
    GenerateUserReport(userId int)
}
Go
<?php

// User.php
interface User {
    public function createUser(string $username, string $password);
    public function deleteUser(int $userId);
    public function updateUser(int $userId, string $username, string $password);
}

// UserNotification.php
interface UserNotification {
    public function sendEmailNotification(int $userId, string $subject, string $body);
    public function sendSmsNotification(int $userId, string $message);
}

// UserReporting.php
interface UserReporting {
    public function generateUserReport(int $userId);
}
PHP
// User.ts
interface User {
    createUser(username: string, password: string): void;
    deleteUser(userId: number): void;
    updateUser(userId: number, username: string, password: string): void;
}

// UserNotification.ts
interface UserNotification {
    sendEmailNotification(userId: number, subject: string, body: string): void;
    sendSmsNotification(userId: number, message: string): void;
}

// UserReporting.ts
interface UserReporting {
    generateUserReport(userId: number): void;
}
TypeScript

Leave a Comment


The reCAPTCHA verification period has expired. Please reload the page.