A client should not be forced to depend on interfaces it does not use. In other words, a class should not implement interfaces that contain methods the class does not need. This helps to reduce the complexity of a class and makes it easier to understand and maintain. It also promotes code reuse because classes that implement specific interfaces can be used more flexibly in different contexts.
Explain it to a 10-year-old
Imagine that you have a toy box with lots of different toys in it, like action figures, dolls, puzzles, and games. Now, imagine that you have a friend who comes over to play with the toys. You don't want to give your friend the whole toy box to play with because it would be too confusing and overwhelming for them. Instead, you might give your friend a smaller selection of toys more suitable for their interests and abilities. This is kind of like the Interface Segregation Principle in computer programming. It means that we should only give other parts of our program the information and tools they need and not force them to use things they don't need or understand. This helps to keep our program organized and easier to use.
Violation
class ToyBox
{
public void addToy(Toy toy) { ... }
public void removeToy(Toy toy) { ... }
public List<Toy> getToys() { ... }
public void playMusic() { ... }
public void changeBattery() { ... }
}
In this example, the ToyBox class has methods for adding and removing toys and getting a list of all the toys. However, it also has methods for playing music and changing the battery. These additional methods may not be needed by every client that uses the ToyBox class, and they could make the class more difficult to understand and use. A better design would be to create separate interfaces for the different types of functionality so that clients can choose to depend only on the interfaces they need.
Fix
We could define two separate interfaces,
interface ToyContainer
{
void addToy(Toy toy);
void removeToy(Toy toy);
List<Toy> getToys();
}
interface MusicPlayer
{
void playMusic();
void changeBattery();
}
Then, we could update the ToyBox class to implement only the ToyContainer interface.
class ToyBox implements ToyContainer
{
public void addToy(Toy toy) { ... }
public void removeToy(Toy toy) { ... }
public List<Toy> getToys() { ... }
}
This way, clients that only need to add, remove, and get toys can depend on the ToyContainer interface. At the same time, clients needing music playback functionality can depend on the MusicPlayer interface. This helps reduce the ToyBox class's complexity and makes it easier to understand and use.
Why ISP
Here are some key points about why the Interface Segregation Principle is important
It helps reduce code complexity by ensuring that classes do not implement too many methods or interfaces.
It makes code more flexible and easier to maintain because it allows building more modular classes and can be easily adapted to different contexts.
It helps us create more robust and maintainable software by allowing us to design classes more modular and cohesively.
How to check if ISP is violated?
Here are some ways you can check if the Interface Segregation Principle is being violated in your code:
Look at the interfaces in your codebase and consider whether they are specific and focused enough. If an interface contains many methods not used by all of its clients, it may violate the Interface Segregation Principle.
Look at the classes in your codebase and consider whether they implement interfaces containing methods they do not need. If a class is implementing an interface with many methods but only uses a few of them, it may be violating the Interface Segregation Principle.
When designing your interfaces and classes, think about how other parts of the program will use them. If you find that a client is being forced to depend on methods that it does not use, it may be a sign that the Interface Segregation Principle is being violated.
By following these steps, you can help ensure that your code follows the Interface Segregation Principle and is easy to understand, maintain, and reuse.