I Interface Segregation Principle ISP
2 min readInterface Segregation Principle (ISP)
TL;DR
The Interface Segregation Principle says clients should never be forced to depend on methods they don't use. Splitting a fat contract into focused, role-based interfaces keeps implementations honest, shrinks the surface that mocks and consumers must cover, and stops a change in one capability from rippling through every unrelated caller.
How it works
I — Interface Segregation Principle (ISP)
“Clients should not be forced to depend on methods they do not use.”
❌ Bad example:
public interface ITradingPlatform
{
void ExecuteOrder(Order order);
void StreamMarketData();
void SendNotification();
}
Each implementation is forced to implement everything, even if it doesn’t need to.
✅ Good example:
public interface ITradeExecutor { void ExecuteOrder(Order order); }
public interface IMarketDataFeed { void StreamMarketData(); }
public interface INotifier { void SendNotification(); }
💡 In trading:
IPriceFeedfor market dataITradeExecutorfor executionIRiskServicefor validation
You can plug each service independently into different workflows.
Quick recall Q&A
Narrow interfaces reduce the blast radius of changes. Updating ITradeExecutor doesn’t force unrelated services (like notifications) to recompile or implement dummy methods.
Clients implementing “not required” methods or throwing NotSupportedException. Interfaces with dozens of members or mixed responsibilities are prime candidates.
External contracts should expose purpose-built endpoints, not monolithic APIs. Clients consume only what they need, reducing coupling and versioning risks.
DI allows registering multiple interfaces per class. For example, a service implementing both ITradeExecutor and IRiskService can be resolved through whichever interface the consumer needs.
Segregate by cohesive responsibilities, not per method. Keep interfaces meaningful and group operations that change together.
Smaller interfaces mean simpler mocks/stubs. Tests focus on the behavior under test without faking unrelated members.
Adding methods to a fat interface forces consumers to adapt. With segregated interfaces, you can introduce new interfaces or extension methods without breaking existing ones.
Ask “which clients need each member?” and require justification for multi-purpose interfaces. NetArchTest or custom analyzers can flag interfaces exceeding size thresholds.
Publish separate events per concern instead of mega-events containing everything. Consumers subscribe only to relevant payloads, mirroring ISP.
Clients avoid referencing heavy dependencies they don't use (e.g., price feeds requiring streaming libs). This reduces memory footprint and simplifies deployment.