Skip to main content

SOLID Principles - Interface Segregation Principle (ISP) Real-Time Example in C#

The SOLID Principles are the design principles that enable us to manage several software design problems. These principles provide us with ways to move from tightly coupled code to loosely coupled and encapsulated real business needs properly. Also readable, adaptable, and scalable code.

The SOLID Principles guide developers as they write readable, adaptable, and scalable code or design an application.

The SOLID Principles can be applied to any OOP program.

The SOLID Principles were developed by computer science instructor and author Robert C. Martin. Now, SOLID principles have also been adopted in both agile development and adaptive software development.

The 5 principles of SOLID are:

1.      Single Responsibility Principle (SRP)

2.      Open Closed Principle (OCP)

3.      Liskov Substitution Principle (LSP)

4.      Interface Segregation Principle (ISP)

5.      Dependency Inversion Principle (DIP)

 

SOLID Principle: (4) Interface Segregation Principle (ISP)

The Interface Segregation Principle (ISP) is one of the SOLID principles of object-oriented design.

By Robert C. Martin -

Interface Segregation Principle (ISP) states that clients should not be forced to implement interfaces they do not use.

Interface Segregation Principle (ISP) splits interfaces that are very large into smaller and more specific ones so that clients will only have to know about the methods they actually need.

 

Implementation:  Interface Segregation Principle (ISP) C# Live Example:

Let us consider an example to Explain the Interface Segregation Principle (ISP) in C#, suppose we have an IWorker interface that defines methods for various types of work, such as Work, Eat, and Sleep.

 

First, define an interface IWorker interface that has three methods Work (), Eat (), and Sleep ():

//IWorker interface

public interface IWorker

{

    void Work();

    void Eat();

    void Sleep();

}

Now, imagine we have two classes, HumanWorker and RobotWorker, that implement to IWorker interface.


Second, define a HumanWorker class that implements the IWorker interface:

//HumanWorker class that implements to IWorker interface

public class HumanWorker: IWorker

{

    public void Work() { /*...*/ }

    public void Eat() { /*...*/ }

    public void Sleep() { /*...*/ }

}


Third, define a RobotWorker class that also implements the IWorker interface. The Robot cannot Eat and Sleep but is forced to Eat () and Sleep () methods (violates the ISP):

//RobotWorker class that implements to IWorker interface

public class RobotWorker : IWorker

{

    public void Work() { /*...*/ }

 

    /* Not needed for robots worker because they not eat food. */

    public void Eat() { /*...*/ }

 

    /* Not needed for robots worker because they not eat sleep. */

    public void Sleep() { /*...*/ }

}

Here IWorker interface violates the Interface Segregation Principle (ISP) and it's forcing the RobotWorker class to implement the Eat () and Sleep () methods that are irrelevant to the robot’s class.

To fix the issue of violating the Interface Segregation Principle (ISP), we need to break down the large interface into smaller ones.

Let's break down the IWorker interface into smaller, See the C# code,

//IWorkable interface

public interface IWorkable

{

    void Work();

}

 

//IEatable interface

public interface IEatable

{

    void Eat();

}

 

//ISleepable interface

public interface ISleepable

{

    void Sleep();

}

 

Now, the HumanWorker class will implement all three interfaces (IWorkable, IEatable, ISleepable), while the RobotWorker class only needs to implement the (IWorkable) interface. See the C# code,

//HumanWorker class and inherited to IWorkable, IEatable, ISleepable interfaces

public class HumanWorker: IWorkable, IEatable, ISleepable

{

    public void Work() { /*...*/ }

    public void Eat() { /*...*/ }

    public void Sleep() { /*...*/ }

}

 

//RobotWorker class and inherited only IWorkable interface

public class RobotWorker: IWorkable

{

    public void Work() { /*...*/ }

}

 

Now we have ensured that clients only implement the methods they actually need.


Put it all together to follow the Interface Segregation Principle (ISP) in C#,

 

namespace ISP;

 

public interface IWorkable

{

    void Work();

}

public interface IEatable

{

    void Eat();

}

public interface ISleepable

{

    void Sleep();

}

public class HumanWorker: IWorkable, IEatable, ISleepable

{

    public void Work () {/*...*/}

    public void Eat () {/*...*/}

    public void Sleep () {/*...*/}

}

 

public class RobotWorker: IWorkable

{

    public void Work () {/*...*/}

}

public class Program

{

    public static void Main(string[] args)

    {

        // HumanWorker

        var homenWorker = new HumanWorker();

        homenWorker.Work();

        homenWorker.Eat();

        homenWorker.Sleep();

 

        // RobotWorker

        var robotWorker = new RobotWorker();

        robotWorker.Work();

    }

}


What Are the Advantages of Interface Segregation Principle (ISP) in C#?

1.     Reduced Dependencies: Breaking interfaces into smaller, more specific ones reduces the number of methods each class is required to implement.

2.     Improved Code Maintainability: With smaller, more focused interfaces, it becomes easier to understand and maintain the code.

3.     Flexibility and Extensibility: Classes developed by the ISP are more flexible and extensible.

4.     Easier Testing: Smaller interfaces make it easier to create and perform unit tests.

5.     Avoiding Fat Interfaces: ISP prevents the creation of "fat interfaces". Fat interfaces violate the single responsibility principle. Breaking down interfaces helps avoid this issue.

6.     Clearer Intent: Specific interfaces convey the intent and responsibilities of implementing classes more clearly. This makes the codebase more self-documenting and easier to understand.

 What Are the Disadvantages of Interface Segregation Principle (ISP) in C#?

1.     Increased Number of Interfaces: More interfaces will create the challenge to manage and understand the relationships between various interfaces.

2.     Increased Development Time: Creating and managing a large number of small interfaces might increase the time and effort required during the development phase.

How to use the Interface Segregation Principle effectively in C#?

1.     Identify Client Needs: To identify the client needs and split fat interfaces into smaller ones.

2.     Refactor Existing Interfaces

3.     Avoid Fat Interfaces

4.     Apply Dependency Injection

 

By Anil Singh | Rating of this article (*****)

Popular posts from this blog

React | Encryption and Decryption Data/Text using CryptoJs

To encrypt and decrypt data, simply use encrypt () and decrypt () function from an instance of crypto-js. Node.js (Install) Requirements: 1.       Node.js 2.       npm (Node.js package manager) 3.       npm install crypto-js npm   install   crypto - js Usage - Step 1 - Import var   CryptoJS  =  require ( "crypto-js" ); Step 2 - Encrypt    // Encrypt    var   ciphertext  =  CryptoJS . AES . encrypt ( JSON . stringify ( data ),  'my-secret-key@123' ). toString (); Step 3 -Decrypt    // Decrypt    var   bytes  =  CryptoJS . AES . decrypt ( ciphertext ,  'my-secret-key@123' );    var   decryptedData  =  JSON . parse ( bytes . toString ( CryptoJS . enc . Utf8 )); As an Example,   import   React   from   'react' ; import   './App.css' ; //Including all libraries, for access to extra methods. var   CryptoJS  =  require ( "crypto-js" ); function   App () {    var   data

List of Countries, Nationalities and their Code In Excel File

Download JSON file for this List - Click on JSON file    Countries List, Nationalities and Code Excel ID Country Country Code Nationality Person 1 UNITED KINGDOM GB British a Briton 2 ARGENTINA AR Argentinian an Argentinian 3 AUSTRALIA AU Australian an Australian 4 BAHAMAS BS Bahamian a Bahamian 5 BELGIUM BE Belgian a Belgian 6 BRAZIL BR Brazilian a Brazilian 7 CANADA CA Canadian a Canadian 8 CHINA CN Chinese a Chinese 9 COLOMBIA CO Colombian a Colombian 10 CUBA CU Cuban a Cuban 11 DOMINICAN REPUBLIC DO Dominican a Dominican 12 ECUADOR EC Ecuadorean an Ecuadorean 13 EL SALVADOR

23 Best Key Features of MVC 6 and MVC 5

What’s new In MVC 6? The Added Key Features as following as, 1. The Microsoft makes a bundle of MVC, Web API, WebPages, SignalR, that bundle we called  MVC6 . 2. The MVC 6   added new cloud computing optimization system of MVC, web API, SignalR and entity framework. 3. In MVC 6, Microsoft removed the dependency of system.web.dll from MVC 6 because it's so expensive. Typically it consumes 30K memory per request/response. 4. Right now, in MVC 6 consume 2K memory per request response. It's too small memory consume. 5. Most of the problem solved using the  Roslyn Compiler . 6 . It’s added a  Start-up  class that replaces to  global.asax  file. 7. The Session state and caching adjusts our behavior depending on your hosting environment. 8. Host agnostic and its true side-by-side deployment 9. The vNext is a cross platform and open source and it's also supported to Mac, Linux, etc. 10. It’s also added to TagHeaplers use to creating an

Angular 7 and 8 Validate Two Dates - Start Date & End Date

In this example, I am sharing “ How to compare or validate two dates in Angular? ” using custom validation function in Angular 7 and Angular 8 . Here, I’m validating the two dates  - a start date and end date. The end date should be greater than the Start date”. Let’s see the example :- import { Component , OnInit } from '@angular/core' ; import { UserRequest } from '../model/user' ; @ Component ({   selector: 'User_Cal' ,   templateUrl: './usercal.component.html' ,   styleUrls: [ './usercal.component.css' ] }) export class UserCalComponent implements OnInit {   constructor ( private EncrDecr : EncrDecrService , private   http :  HttpClient ,               private datePipe : DatePipe ) {                            }   //model class   model = new UserRequest ( null , null , null , null , null );   //Error Display   error : any ={ isError: false , errorMessage: '' };   isValid

Encryption and Decryption Data/Password in Angular

You can use crypto.js to encrypt data. We have used 'crypto-js'.   Follow the below steps, Steps 1 –  Install CryptoJS using below NPM commands in your project directory npm install crypto-js --save npm install @types/crypto-js –save After installing both above commands it looks like  – NPM Command  1 ->   npm install crypto-js --save NPM Command  2 ->   npm install @types/crypto-js --save Steps 2  - Add the script path in “ angular.json ” file. "scripts" : [                "../node_modules/crypto-js/crypto-js.js"               ] Steps 3 –  Create a service class “ EncrDecrService ” for  encrypts and decrypts get/set methods . Import “ CryptoJS ” in the service for using  encrypt and decrypt get/set methods . import  {  Injectable  }  from   '@angular/core' ; import   *   as   CryptoJS   from   'crypto-js' ; @ Injectable ({    providedIn:   'root' }) export   class   EncrDecrS