← Back to Article List         
Interface Segregation Principle (ISP)

Interface Segregation Principle (ISP)

Published on 28 Sep 2026     11 min read SOLID Principles
SOLID Principles

Interface Segregation Principle (ISP)

1. What is Interface Segregation Principle?

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

It states:

Clients should not be forced to depend on methods they do not use.

In simple English:

Don't create one large interface with many unrelated methods. Create smaller, focused interfaces so a class implements only what it actually needs.

Easy way to remember:

Large interface → split into small, meaningful interfaces.


2. Why Do We Need ISP?

Suppose we are developing an employee management system.

We create:

public interface IEmployee
{
    void Work();
    void ApproveLeave();
    void ConductInterview();
}

Then we have:

  • Developer
  • Manager

A manager may perform:

Work()
ApproveLeave()
ConductInterview()

But a developer may only need:

Work()

If Developer implements IEmployee, C# forces it to implement all three methods.

So we may end up with:

public void ApproveLeave()
{
    throw new NotSupportedException();
}

and:

public void ConductInterview()
{
    throw new NotSupportedException();
}

That's a design problem.

The developer class is being forced to depend on functionality it doesn't need.


3. Before ISP — Bad Design

Here is a complete simple example.

using System;

public interface IEmployee
{
    void Work();

    void ApproveLeave();

    void ConductInterview();
}

public class Developer : IEmployee
{
    public void Work()
    {
        Console.WriteLine("Developer is coding.");
    }

    public void ApproveLeave()
    {
        throw new NotSupportedException(
            "Developer cannot approve leave.");
    }

    public void ConductInterview()
    {
        throw new NotSupportedException(
            "Developer does not conduct interviews.");
    }
}

public class Manager : IEmployee
{
    public void Work()
    {
        Console.WriteLine("Manager is working.");
    }

    public void ApproveLeave()
    {
        Console.WriteLine("Manager approved leave.");
    }

    public void ConductInterview()
    {
        Console.WriteLine("Manager is conducting interview.");
    }
}

public class Program
{
    public static void Main()
    {
        Developer developer = new Developer();

        developer.Work();

        Manager manager = new Manager();

        manager.Work();
        manager.ApproveLeave();
        manager.ConductInterview();
    }
}

Output

Developer is coding.
Manager is working.
Manager approved leave.
Manager is conducting interview.

The program works as long as we don't call unsupported methods on Developer.

But the design has a problem.


4. What is the Problem?

Our interface contains:

IEmployee
    │
    ├── Work()
    ├── ApproveLeave()
    └── ConductInterview()

Manager needs everything:

Manager
   │
   ├── Work()             ✓
   ├── ApproveLeave()     ✓
   └── ConductInterview() ✓

But Developer only needs:

Developer
   │
   ├── Work()             ✓
   ├── ApproveLeave()     ✗
   └── ConductInterview() ✗

Because Developer implements:

IEmployee

C# forces it to implement all methods.

This is called a fat interface or polluted interface.


5. What is a Fat Interface?

A fat interface contains too many methods covering different responsibilities or capabilities.

For example:

public interface IEmployee
{
    void Work();
    void ApproveLeave();
    void ConductInterview();
    void GeneratePayroll();
    void GenerateReport();
    void ManageProject();
    void HireEmployee();
}

Now every implementation is potentially forced to implement all of these.

                     IEmployee
                         │
      ┌──────────────────┼──────────────────┐
      ↓                  ↓                  ↓
 Developer            Manager              HR
      │                  │                  │
 forced to            forced to          forced to
 implement             implement           implement
 everything            everything          everything

Most employee types probably don't need every operation.

ISP says:

Split the interface based on actual capabilities.


6. Apply Interface Segregation Principle

Instead of one large interface:

IEmployee
 ├── Work()
 ├── ApproveLeave()
 └── ConductInterview()

split it into:

IWorker
   └── Work()

ILeaveApprover
   └── ApproveLeave()

IInterviewer
   └── ConductInterview()

Now each class implements only what it needs.


7. Full Simple Program Using ISP

using System;


// Responsibility:
// Represents someone who can work
public interface IWorker
{
    void Work();
}


// Responsibility:
// Represents someone who can approve leave
public interface ILeaveApprover
{
    void ApproveLeave();
}


// Responsibility:
// Represents someone who can conduct interviews
public interface IInterviewer
{
    void ConductInterview();
}


// Developer only needs working capability
public class Developer : IWorker
{
    public void Work()
    {
        Console.WriteLine(
            "Developer is coding.");
    }
}


// Manager needs all three capabilities
public class Manager :
    IWorker,
    ILeaveApprover,
    IInterviewer
{
    public void Work()
    {
        Console.WriteLine(
            "Manager is working.");
    }

    public void ApproveLeave()
    {
        Console.WriteLine(
            "Manager approved leave.");
    }

    public void ConductInterview()
    {
        Console.WriteLine(
            "Manager is conducting interview.");
    }
}


public class Program
{
    public static void Main()
    {
        Developer developer =
            new Developer();

        developer.Work();


        Manager manager =
            new Manager();

        manager.Work();
        manager.ApproveLeave();
        manager.ConductInterview();
    }
}

Output

Developer is coding.
Manager is working.
Manager approved leave.
Manager is conducting interview.

8. Program Explanation

Let's understand each part.

IWorker

public interface IWorker
{
    void Work();
}

This interface represents only one capability:

Can perform work.

Both:

Developer
Manager

can work.

Therefore both can implement:

IWorker

9. ILeaveApprover

public interface ILeaveApprover
{
    void ApproveLeave();
}

This interface represents:

Can approve leave.

In our example, only the manager needs this capability.

Therefore:

ILeaveApprover
       ↑
       │
    Manager

The developer doesn't implement it.


10. IInterviewer

public interface IInterviewer
{
    void ConductInterview();
}

This represents:

Can conduct interviews.

Again, only the manager needs it in our example.

IInterviewer
      ↑
      │
   Manager

11. Developer Class

Now look at Developer:

public class Developer : IWorker
{
    public void Work()
    {
        Console.WriteLine(
            "Developer is coding.");
    }
}

Developer only implements:

IWorker

Therefore it only needs:

Work()

We no longer need ugly methods like:

public void ApproveLeave()
{
    throw new NotSupportedException();
}

That's the major benefit of ISP.


12. Manager Class

Manager requires multiple capabilities.

So it can implement multiple small interfaces:

public class Manager :
    IWorker,
    ILeaveApprover,
    IInterviewer

This means:

Manager
   │
   ├── IWorker
   │      └── Work()
   │
   ├── ILeaveApprover
   │      └── ApproveLeave()
   │
   └── IInterviewer
          └── ConductInterview()

This is perfectly fine.

ISP does not say:

A class should implement only one interface.

A class can implement many interfaces.

The important point is:

Each interface should be focused, and the class should depend only on the capabilities it needs.


13. Before ISP vs After ISP

Before ISP

                    IEmployee
                        │
        ┌───────────────┼───────────────┐
        │               │               │
      Work()      ApproveLeave()   ConductInterview()
        │               │               │
        └───────────────┬───────────────┘
                        │
              ┌─────────┴─────────┐
              ↓                   ↓
          Developer             Manager
              │                   │
         Only Work()          Needs all
          is needed            methods

Developer is forced to implement unnecessary methods.


After ISP

 IWorker          ILeaveApprover       IInterviewer
    │                   │                   │
    │                   │                   │
    ↓                   ↓                   ↓
Developer             Manager             Manager
    ↑                   ↑
    │                   │
    └──── Manager ──────┘

More clearly:

Developer
    ↓
IWorker


Manager
    ├── IWorker
    ├── ILeaveApprover
    └── IInterviewer

Each class implements only the contracts relevant to it.


14. Does ISP Mean One Method Per Interface?

No.

This is an important misunderstanding.

You don't need to create:

IAddEmployee
IUpdateEmployee
IDeleteEmployee
IGetEmployee

just because ISP says interfaces should be small.

For example:

public interface IEmployeeRepository
{
    void Add();
    void Update();
    void Delete();
    void GetById();
}

This can be perfectly reasonable because all methods belong to the same cohesive responsibility:

Employee persistence

ISP means:

Keep interfaces focused around what their consumers need.

It does not mean:

Every interface must contain exactly one method.


15. Another Simple Example — Printer

A classic example is a printer.

Suppose we create:

public interface IMachine
{
    void Print();
    void Scan();
    void Fax();
}

A modern multifunction printer can:

Print ✓
Scan  ✓
Fax   ✓

But a basic printer may only:

Print ✓
Scan  ✗
Fax   ✗

If BasicPrinter implements IMachine, it may be forced to create:

public void Scan()
{
    throw new NotSupportedException();
}

public void Fax()
{
    throw new NotSupportedException();
}

That's a warning sign.

ISP suggests:

IPrinter
   └── Print()

IScanner
   └── Scan()

IFax
   └── Fax()

Then:

BasicPrinter
     ↓
IPrinter

while:

MultiFunctionPrinter
     ├── IPrinter
     ├── IScanner
     └── IFax

This models the capabilities more accurately.


16. ISP and Dependency Injection

ISP becomes especially useful with Dependency Injection.

Suppose a report service only needs to read customer data.

But we inject:

ICustomerService

containing:

GetCustomer()
CreateCustomer()
UpdateCustomer()
DeleteCustomer()
ApproveCustomer()
BlockCustomer()
ExportCustomer()
SendCustomerEmail()

ReportService might only need:

GetCustomer()

Yet it depends on the entire large contract.

A more focused abstraction might be:

public interface ICustomerReader
{
    Customer GetCustomer(int id);
}

Then:

ReportService
      ↓
ICustomerReader

rather than depending on unrelated customer-management operations.

This is one practical way ISP can reduce coupling in enterprise applications.


17. ISP in ASP.NET Core

Imagine an application with:

IUserService

containing:

GetUser()
CreateUser()
UpdateUser()
DeleteUser()
ResetPassword()
SendEmail()
GenerateReport()
UploadProfileImage()

This interface is doing too much.

Different consumers may need very different subsets.

For example:

UserController
     ↓
User management


ReportService
     ↓
Read users only


PasswordService
     ↓
Password operations

Instead, depending on the application's needs, contracts could be separated:

IUserReader
   └── GetUser()


IUserWriter
   ├── CreateUser()
   ├── UpdateUser()
   └── DeleteUser()


IPasswordService
   └── ResetPassword()

Then consumers take only what they require.


18. ISP and LSP

Since you just covered Liskov Substitution Principle, these two principles are closely related.

Remember our LSP example:

Bird
 └── Fly()

Then:

Sparrow → Fly() ✓
Penguin → Fly() ✗

Penguin was forced to support behavior it couldn't provide.

We improved it by separating:

Bird
   └── Eat()

IFlyingBird
   └── Fly()

Now:

Sparrow
   ├── Bird
   └── IFlyingBird


Penguin
   └── Bird

Notice that this design also reflects the idea behind ISP:

Don't force Penguin to depend on a flying capability it doesn't need.

So the SOLID principles often support one another.


19. ISP vs SRP

These can look similar, but their focus is different.

SRP

Focuses mainly on the responsibility of a class/module.

Does this class have too many unrelated reasons to change?

ISP

Focuses on the contracts clients depend on.

Is this interface forcing a client to depend on operations it doesn't need?

Simple comparison:

SRP ISP
Focuses on responsibilities Focuses on interface dependencies
Often discussed about classes/modules Focuses primarily on interfaces/contracts
One cohesive reason to change Don't force unnecessary methods on clients
Split unrelated responsibilities Split overly broad interfaces

20. How to Identify an ISP Violation

Look for classes implementing methods like:

public void SomeMethod()
{
    throw new NotSupportedException();
}

or:

public void SomeMethod()
{
    // Not applicable
}

or:

public void SomeMethod()
{
    // Do nothing
}

These are warning signs.

For example:

IEmployee
    │
    ├── Work()
    ├── ApproveLeave()
    ├── ConductInterview()
    ├── GeneratePayroll()
    └── HireEmployee()

Then:

Developer
    │
    ├── Work()             ✓
    ├── ApproveLeave()     ✗
    ├── ConductInterview() ✗
    ├── GeneratePayroll()  ✗
    └── HireEmployee()     ✗

This strongly suggests that IEmployee is too broad for that client.


21. Important: NotSupportedException Does Not Automatically Mean ISP Violation

It is only a warning sign.

Whether the design violates ISP depends on the contract and how it is intended to be used.

The real question is:

Is this class being forced to depend on operations that are irrelevant to it?

If yes, ISP should be considered.


22. Advantages of Interface Segregation Principle

1. Smaller and Focused Interfaces

Instead of:

IEmployee
 ├── Work
 ├── Interview
 ├── Payroll
 ├── Leave
 ├── Reporting
 └── Recruitment

we have focused contracts:

IWorker
IInterviewer
ILeaveApprover

2. Less Unnecessary Coupling

A class depends only on the operations it actually needs.


3. No Unnecessary Implementations

We avoid methods like:

throw new NotSupportedException();

simply because an interface forced the class to implement them.


4. Easier Maintenance

Changes to one focused interface are less likely to affect unrelated consumers.


5. Easier Testing

Smaller interfaces are often easier to mock or fake.

For example, if a class needs only:

ICustomerReader

your test double only needs to support customer-reading behavior.


6. Better Flexibility

Classes can combine capabilities:

Manager
   ├── IWorker
   ├── IInterviewer
   └── ILeaveApprover

while another class may implement only:

Developer
   └── IWorker

7. Better Design Clarity

When you see:

public class Manager :
    IWorker,
    ILeaveApprover,
    IInterviewer

you immediately understand the capabilities of the class.


23. Can ISP Be Overused?

Yes.

Don't blindly convert:

public interface IEmployeeRepository
{
    void Add();
    void Update();
    void Delete();
    Employee GetById();
}

into:

IEmployeeAdder
IEmployeeUpdater
IEmployeeDeleter
IEmployeeGetter

unless your architecture and consumers actually benefit from that separation.

Too many tiny interfaces can make an application harder to understand and navigate.

The goal is:

Focused, cohesive interfaces — not the maximum possible number of interfaces.


24. Easy Way to Remember ISP

Think about a restaurant.

A customer wants:

Food

You shouldn't force them to also purchase:

Food
+
Hotel Room
+
Taxi
+
Gym Membership
+
Movie Ticket

They should depend only on what they need.

Similarly:

Developer
      ↓
Needs Work()

Don't force:

Developer
      ↓
Work()
ApproveLeave()
ConductInterview()
GeneratePayroll()

So remember:

Don't force clients to depend on methods they don't need.


25. SOLID Progress So Far

You can now connect the principles:

S — Single Responsibility
    One cohesive responsibility


O — Open/Closed
    Extend behavior without repeatedly
    modifying stable code


L — Liskov Substitution
    Child/subtype must safely
    replace parent/abstraction


I — Interface Segregation
    Don't force clients to depend
    on methods they don't need


D — Dependency Inversion
    Depend on abstractions,
    not concrete implementation details

26. Key Points

  • ISP = Interface Segregation Principle.
  • It is the I in SOLID.
  • Clients should not be forced to depend on methods they don't use.
  • Prefer small, focused, cohesive interfaces over one large "fat" interface.
  • A class can implement multiple interfaces.
  • ISP does not mean one method per interface.
  • Methods that throw NotSupportedException because they are irrelevant to the implementation can indicate an overly broad interface.
  • ISP reduces unnecessary coupling.
  • It improves maintainability, testability, flexibility, and clarity.
  • ISP works very well with Dependency Injection because consumers can request narrow contracts.
  • ISP and LSP often complement each other.
  • Don't overuse ISP by creating unnecessary one-method interfaces everywhere.

Interview Answer

Interface Segregation Principle states that clients should not be forced to depend on methods they do not use. In simple terms, instead of creating one large interface containing many unrelated methods, we should create smaller and focused interfaces. Each class then implements only the capabilities it actually needs. This reduces unnecessary coupling and makes the application easier to maintain, test, and extend.