The ISP was “invented” by Robert C. Martin while consulting for Xerox: “The interface-segregation principle (ISP) states that no client should be forced to depend on methods it does not use.”*
I’ll explain this with an example, let’s assume we have an Interface SensorDevice that provides a lot of functions:
So what’s the problem with fat interfaces like in the example coding?
If clients use interface with methods they don’t need, they know details that they don’t care about.
In the sensor device example you will have code that controls maybe hundreds of different sensors and on the other hand there’ll be code that reads and handles the readings.
Device State, control and reading methods are tightly coupled togehter. If there’s a change in a method signature for example, all “clients” are eventually affected by the change – which is unnecessary.
Applying the interface segregation principle
To understand the ISP you must understand the difference between the (class-)interface and the object interface. Depending on the language a class can inherit from one or more classes and implement multiple interfaces
An object that implements multiple interfaces exposes all methods. But you also can access the object with the interface it implement, like IDisposable.
This allows a very specific access to a subset of the object interface, so that it can be treated in different ways without caring about its details.
Especially on higher levels of abstraction you will have objects with many methods, but you can group them using interfaces:
Now you can access the different methods by client-concern using the interfaces:
06.03.2016 07:17:37 ConsoleLogFakeSensor: enable()
06.03.2016 07:17:37 ConsoleLogFakeSensor: isEnabledSince()
06.03.2016 07:17:37 ConsoleLogFakeSensor: disable()
06.03.2016 07:17:37 ConsoleLogFakeSensor: powerOff()
Press any key to continue…
This will also be very handy if you want to disable dozens of different devices of different types using the generic interface “DeviceState” – without knowing which type of Device it is.
The example project is in this GitHub repository.
Splitting fat interfaces by client concerns is a powerful tool to build cohesive interfaces. Due to the reduced dependencies the scope of changes is minimised and the loose coupling will payoff in the long term when it comes to extending and maintaining the project. Smaller specific interfaces may also help to communication your intentions.