The Interface Segregation Principle was introduced by Robert C. Martin. It states that clients should not be forced to depend on interfaces they do not use. This means that a class should not have to implement methods it doesn’t use. Instead of one big interface, numerous smaller interfaces are preferred based on groups of methods, each one serving one submodule. This principle is about reducing the side effects and frequency of required changes by dividing the software into multiple, independent parts.
let’s consider an example of a system that manages a coffee shop.
Let’s say we have a Worker
interface:
interface Worker {
void makeCoffee();
void cleanFloor();
void manageAccounts();
}
In the coffee shop, we have different types of workers like Barista
, Cleaner
, and Manager
. Not all workers perform all tasks. A Barista
makes coffee but doesn't manage accounts. A Cleaner
cleans the floor but doesn't make coffee or manage accounts. A Manager
manages accounts but doesn't make coffee or clean the floor.
If we force all worker types to implement the Worker
interface, we end up forcing some types of workers to have methods that they don't use. This is where the Interface Segregation Principle comes in.
Instead of having one large Worker
interface, we should segregate the interface into smaller, more specific interfaces:
interface CoffeeMaker {
void makeCoffee();
}
interface FloorCleaner {
void cleanFloor();
}
interface AccountManager {
void manageAccounts();
}
Now, Barista
can implement CoffeeMaker
, Cleaner
can implement FloorCleaner
, and Manager
can implement AccountManager
. This way, each worker only needs to know about the methods that are relevant to their own duties.
class Barista implements CoffeeMaker {
void makeCoffee() {
// implementation
}
}
class Cleaner implements FloorCleaner {
void cleanFloor() {
// implementation
}
}
class Manager implements AccountManager {
void manageAccounts() {
// implementation
}
}
This is a simple example of how the Interface Segregation Principle can be used to create cleaner, more maintainable code.
Without ISP: Suppose we only have the Worker
interface. If a new law is passed that requires all coffee shops to provide nutritional information for their drinks, we would have to add a new method provideNutritionalInfo()
to our Worker
interface.
interface Worker {
void makeCoffee();
void cleanFloor();
void manageAccounts();
void provideNutritionalInfo();
}
Now, every class that implements Worker
will have to implement this new method, even if it doesn't make sense for them to do so. The Cleaner
and Manager
classes will have to implement provideNutritionalInfo()
, even though this is clearly a task for the Barista
. This leads to bloated, confusing code.
With ISP: If we have segregated interfaces, we can simply add the new method to the CoffeeMaker
interface.
interface CoffeeMaker {
void makeCoffee();
void provideNutritionalInfo();
}
Only the Barista
class implements CoffeeMaker
, so only the Barista
class needs to implement the new method. The Cleaner
and Manager
classes remain unchanged. This makes our code cleaner, easier to maintain, and less prone to errors.
This example illustrates how ISP can make your code more flexible and easier to modify. It allows you to make changes in one area of your code without affecting others. It also helps to ensure that each class only contains the methods that it actually needs, making your code easier to understand and maintain.
Interface Segregation Principle (ISP) is an important concept in object-oriented design for several reasons:
- Avoiding Unused Methods: If a class is forced to implement an interface it doesn’t use, then it will have to contain methods that remain unused or throw exceptions. This can lead to confusion and bloated code. ISP encourages creating smaller, more specific interfaces so that a class only needs to know about the methods it actually uses.
- Reducing Side Effects: By minimizing unnecessary dependencies between classes, you reduce the risk that changes in one class will affect others. This makes the system easier to maintain and less prone to bugs.
- Improving Code Organization: By breaking down interfaces into smaller, more focused parts, your code becomes more organized and easier to understand. It’s clearer what each part of your system is responsible for.
- Increasing Flexibility and Reusability: Smaller, more specific interfaces are more flexible and easier to reuse in different parts of your system. This can make it easier to expand or modify your system in the future.
- Easier Testing and Validation: Smaller interfaces are easier to mock and test, which can improve the reliability of your software.
In summary, the Interface Segregation Principle helps to create a system that is more robust, maintainable, flexible, and less prone to errors.