DEV Community

Gabrielle Eduarda
Gabrielle Eduarda

Posted on

Interface Segregation Principle: Why Less Is More When It Comes to Interfaces

“A good interface is like a good menu: it shows only what you need — nothing more, nothing less.”

If you’ve ever had to implement an interface just to throw NotImplementedException() in half the methods…
You’ve already violated the Interface Segregation Principle (ISP) — the "I" in SOLID.

What does ISP say?
“Clients should not be forced to depend on methods they do not use.”

In practice:

Avoid bloated, one-size-fits-all interfaces

Prefer small, focused contracts

Split responsibilities — one purpose per interface

The problem with fat interfaces
Here’s a common scenario:

public interface IEmployee {
void Work();
void ManageTeam();
void ApproveBudget();
}
Now you need to create a Developer:

public class Developer : IEmployee {
public void Work() { /* okay */ }
public void ManageTeam() { throw new NotImplementedException(); }
public void ApproveBudget() { throw new NotImplementedException(); }
}

This violates ISP:

The class is forced to depend on methods it doesn’t use

It makes testing and maintenance harder

It leads to awkward design choices and code smells

Applying ISP the right way (with C#)
The solution? Split the interface into role-specific contracts.

public interface IWorker {
void Work();
}

public interface IManager {
void ManageTeam();
void ApproveBudget();
}
Now:

public class Developer : IWorker {
public void Work() { /* code */ }
}

public class Manager : IWorker, IManager {
public void Work() { /* code / }
public void ManageTeam() { /
code / }
public void ApproveBudget() { /
code */ }
}

Each class depends only on what it actually needs.

A simple analogy: the remote control
A TV remote should give you exactly what you need: volume, channels, power.

Now imagine it also had buttons for:

Opening your garage

Launching Spotify

Turning on the coffee machine

Cool? Maybe.
Useful? Only if you need it.
For most users? Just noise.

That’s what happens when we design interfaces that try to do too much.

Signs you’re violating ISP
Your class throws NotImplementedException() in multiple methods

You’re mocking unrelated behavior in unit tests

You constantly comment: // TODO: implement later

You’ve reused an interface just because it’s “already there”

These are classic code smells that your interface is doing too much.

Tips to apply ISP in real projects
Split large interfaces into multiple role-based ones

Name them clearly: ISavable, IDownloadable, ISharable

Let each class implement only the capabilities it actually provides

Combine ISP with SRP (Single Responsibility Principle) for laser-focused design

Real-world example: file services

public interface IFileService {
void Upload();
void Download();
void ConvertToPdf();
void ShareViaEmail();
}
Now you need a ReadOnlyFile. It only needs Download().

Your options?

Implement the full interface and throw exceptions

Violate ISP

Refactor

Split the interface:

public interface IReadable {
void Download();
}

public interface IWritable {
void Upload();
void ConvertToPdf();
void ShareViaEmail();
}
Now:

public class ReadOnlyFile : IReadable { ... }
public class FullFile : IReadable, IWritable { ... }

  • Clean, flexible, and scalable.

Conclusion: Smaller interfaces make larger systems healthier
The Interface Segregation Principle seems small, but its impact is huge.

It helps you:

Reduce unnecessary dependencies

Improve testability

Make intentions explicit

Design modular, maintainable and adaptive software

“Great systems aren’t built from massive interfaces — they’re built from small, well-crafted pieces.”

Top comments (0)