Clients should not be forced to depend upon interfaces that they do not use. (Robert C. Martin)
That is the definition of the interface segregation principle (ISP). This needs some explanation like other SOLID principles has had in this series. I will explain this first with an example of violating it.
Example of Violating ISP When Adding New Method
Suppose we have an ICar
interface with few methods:
public interface ICar { void StartEngine(); void StopEngine(); int GetSpeed(); }
Some time passes and we make some classes that implement ICar
interface. Then comes a day when we implement Ferrari and Porche classes with a turbo. Because we have two classes with turbo, we decide to add new Turbo
method to the ICar
interface:
public interface ICar { void StartEngine(); void StopEngine(); int GetSpeed(); void Turbo(); // ISP violation! }
But that forces us to implement Turbo
method to slower cars also. Slow cars are now forced to implement Turbo
method that they do not use. And that violates ISP.
ISP Equals Small Interfaces
Let’s try to fix the ICar
interface to apply ISP. The easiest way is to extract Turbo
method to its own ISportsCar
interface:
public interface ISportsCar { // moved from ICar void Turbo(); } public interface ICar { void StartEngine(); void StopEngine(); int GetSpeed(); // Turbo moved to ISportsCar }
Now our slower cars don’t have to implement the Turbo
method but sports cars, like Ferrari and Porche, can implement ISportsCar
interface and Turbo
method. This doesn’t violate ISP because no car isn’t forced to implement Turbo
method. But still, they can implement it via ISportsCar
if they want. In this example we followed a rule for ISP:
Many client specific interfaces are better than one general interface.
Practically ISP means that use small interfaces with even only one method rather than one fat interface with many methods. Then clients of interfaces are free to choose what interface(s) they want to use and not forced to implement methods they don’t even need (like Turbo
method for a regular car).
In his Encapsulation and SOLID Pluralsight course, Mark Seemann called these fat interfaces header interfaces because they look like C++ header files. And small interfaces with just few methods he calls role interfaces. Role interface name comes from because the interface has a specific role which could be just that one method.
How to Create ISP Friendly Interfaces? The answer to this question is little tricky: don’t create them, let clients who will use the interface, define it. In this way, there won’t be methods in the interface that the client doesn’t use.
Make fine grained interfaces that are client specific. (Robert C. Martin)
Helps With Liskov Substitution Principle
If we follow ISP it also helps us to follow the Liskov substitution principle (LSP). Because if we follow ISP, then we won’t have any classes that can’t implement some method of the interface. And if we always implement all methods of interface it will help also to follow LSP.
More clearly it is in vice versa. If we violate ISP and have some method in the interface that all clients won’t use, then we are forced to for example just throw NotSupportedException
in those subclasses. And as we saw in the previous LSP blog post it will violate also LSP.
Helps Also With Single Responsibility Principle
If we define thin interfaces as ISP suggests, each interface will have only one role. That reduces changes to those interfaces, and probably also to classes that implement it because there is now only one reason to change them. Doesn’t this sound familiar? Yes, it is the single responsibility principle (SRP) that I wrote a blog post earlier in this series. ISP reduces modifying multiple files like SRP.
Similar to the Single Responsibility Principle, the goal of the Interface Segregation Principle is to reduce the side effects and frequency of required changes by splitting the software into multiple, independent parts. (Thorben Janssen)
Conclusion
ISP is quite powerful SOLID principle because it helps to follow even two other SOLID principles: SRP and LSP. In my opinion, especially the relationship with SRP makes it a principle worth to follow.
In one way ISP is just like following clean code: create small interfaces/classes. Even if I really like clean code, I have had my suspicion about one method interfaces. After writing this blog post I understand the reason for them better.
But I have doubt if I am able to follow it by thinking from client’s perspective and let client define the interface it uses. Next time when creating an interface, I will read this blog post and make it apply ISP and “finalize” my learning about ISP.
Sources and Influences
- Encapsulation and SOLID by Mark Seemann in Pluralsight course.
- RoleInterface by Martin Fowler in martinfowler.com.
- SOLID Design Principles Explained: Interface Segregation with Code Examples by Thorben Janssen in stackify.com.
- The Principles of OOD by Robert C. Martin in butunclebob.com.
5 thoughts on “Interface Segregation Principle (SOLID 4/6)”