Interface Segregation Principle (ISP)
The Interface Segregation Principle (ISP) is the “I” in SOLID. It states:
“Clients should not be forced to depend on methods they do not use.”
This principle is about reducing the coupling between a class and its dependencies by making interfaces as specific as possible.
The Problem: Fat Interfaces
A “Fat” or “Polluted” interface is one that contains too many methods. When a class implements a fat interface, it often ends up with “dummy” implementations for methods it doesn’t need.
Example: Multi-Function Printer
The Violation (C++)
class IMachine {
public:
virtual void print() = 0;
virtual void scan() = 0;
virtual void fax() = 0;
};
// A high-end printer can do everything
class AllInOnePrinter : public IMachine {
void print() override { /* ... */ }
void scan() override { /* ... */ }
void fax() override { /* ... */ }
};
// An old printer can only print
class OldPrinter : public IMachine {
void print() override { /* printing */ }
void scan() override { /* ERROR: I can't scan! */ }
void fax() override { /* ERROR: I can't fax! */ }
};
OldPrinter is forced to depend on scan() and fax(), even though it doesn’t support them.
Applying ISP
We split the fat interface into smaller, more focused ones.
class IPrinter {
public:
virtual void print() = 0;
};
class IScanner {
public:
virtual void scan() = 0;
};
class IFax {
public:
virtual void fax() = 0;
};
// Now we can compose them
class AllInOnePrinter : public IPrinter, public IScanner, public IFax {
void print() override { ... }
void scan() override { ... }
void fax() override { ... }
};
class OldPrinter : public IPrinter {
void print() override { ... }
};
ISP in Java: Role Interfaces
Java’s standard library is a great example of ISP. Instead of a BigObjectInterface, we have interfaces like Serializable, Cloneable, Iterable, and Comparable. Each defines a very specific role.
Implementation Example
public interface Document {
void open();
void save();
}
public interface Encryptable {
void encrypt();
}
public class SecureDocument implements Document, Encryptable {
public void open() { ... }
public void save() { ... }
public void encrypt() { ... }
}
public class BasicDocument implements Document {
public void open() { ... }
public void save() { ... }
}
Signs of ISP Violation
- Large interfaces with many methods.
- Methods that throw
NotImplementedExceptionor are left empty. - Clients that only use a small subset of an interface’s methods.
- Frequent changes to an interface that force unrelated clients to recompile.
Benefits of ISP
- Better Decoupling: Systems are easier to refactor, change, and redeploy.
- Clarity: Interfaces clearly define specific capabilities (roles).
- Efficiency: In some compiled languages, it reduces the amount of recompilation needed when an interface changes.
Summary
ISP teaches us to design for the client. By providing small, purpose-built interfaces, we ensure that our components only interact with the parts of the system they actually need.