Principles of Designing the Interface Segregation in software development

Tram Ho

In the previous article I have introduced you to the Open / Closed design principle, one of the most fundamental and important principles in software design, at least from my own point of view. You can follow up here . In this article I will continue on the topic of design principles that is Interface Segregation Principles .

The Principle of Interface Segregation is one of the design principles defined by Rebert C. Martin. They are born many years ago but still very important as when the author originally published them. You would probably assume that the microservices architecture has raised their importance because you can apply these principles to microservices.

Definition of the principle of Interface Segregation

Principle ** Interface Segregation ** was defined by Rebert C. Martin while advising the company Xerox to assist them in building software for new printing systems. His definition is as follows:

“Clients should not be forced to depend upon interfaces that they do not use.”.

Sounds clear right? I’ll show you in this article, it’s pretty easy to violate this rule, especially if your software gets bigger and you have to add lots and lots of new features at the same time.

Similar to the S ingle Responsibility principle, the purpose of the Interface Segregation is to reduce the effects of change requests by splitting software into separate parts.

I will also show you the examples below, this principle can only be achieved if you define interfaces that they respond to a specified client or task.

Violation of the Interface Segregation Principle

None of us are willing to ignore the common design principles of writing bad software. But it still happens quite often. It’s an application that has been around for many years and users are constantly asking for new features.

From a business point of view, it is a very normal situation. But from the technical standpoint, implementing any change presents potential dangers to the system. Adding a new method to existing interfaces is always easy to comfort the programmer even though it implements a different task and while if we separate a new interface it would be better. That was the beginning of a mess of interfaces and sooner or later resulted in interfaces that contained methods that the implementation class did not use.

Let’s see a simple example below where this happened.

Initially, the project used the BasicCoffeeMachine class to model a simple coffee machine. It uses ground coffee to make the delicious filter coffee.

At that time, it was quite nice to extend the CoffeeMachine interface with the addGroundCoffe and brewFilterCoffee . These two basic methods of a coffee machine should be deployed by all machines in the future.

Problems adding new methods

But then some decided that the application needed to support espresso machines as well. The development team modeled the new class, the EspressoMachine . It is quite similar to class BasicCoffeeMachine .

The programmer decided that an espresso is just another type of coffee machine. And so it must implement the CoffeeMachine interface.

The only difference is that the brewEspresso method and the EspressoMachine class will implement it instead of the brewFilterCoffee method. For now, let’s ignore the Interface Segregation principle and do the following three changes:

  1. The EspressoMachine class implements the CoffeeMachine interface and its brewFilterCoffee method.

  1. We add methods brewEspresso to interfce CoffeeMachine so the interface will allow you to espresso.

  1. You need to implement the brewEspresso method on the BasicCoffeeMachine class because it is defined in the CoffeeMachine interface. You can also provide an implementation similar to a default method on the CoffeeMachine interface

After you’ve made your changes, the class diagram should look like this:

We can see that the second and third changes to the CoffeeMachine interface CoffeeMachine not a good response for these two types of coffee machines. Method brewEspresso of class BasicCoffeeMachine and methods brewFilterCoffee of EspressoMachine throw an CoffeeException because these operations are not supported. You must implement them only because they are required by the CoffeeMachine interface.

But implementing these two methods is not a real problem. That problem is the interface CoffeeMachine will change if the methods brewFilterCoffee of class BasicCoffeeMachine change. That also requires a change of the EspressoMachine class and all the other classes that use EspressoMachine even though the brewFilterCoffee method brewFilterCoffee n’t provide any functionality and they don’t call it either.

The principle of Interface Segregation is applied

So how to fix the CoffeeMachine interface and its implementations BasicCoffeeMachine , EspressoMachine ?

You need to split the CoffeeMachine interface into multiple interfaces for different types of coffee machines. All known implementations of this interface will use the same addGroundCoffee method. As such, there is no reason to discard it.

We don’t keep the brewFilterCoffee and brewEspresso . You should create two separate interfaces for each type. And in this example, the two interfaces should extend the CoffeeMachine interface. That shouldn’t be the case in case you are refactoring the application. Please check it out carefully.

After doing so, the FilterCoffeeMachine interface extends the CoffeeMachine interface and defines the method brewFilterCoffee .

Similar to the interface EspressoCoffeeMachine :

Ok, now that you have divided interfaces so that the functions of the different coffee machines will be independent. As a result, the BasicCoffeeMachine and EspressoMachine classes need no longer provide empty implementations and will be independent of each other.

The BasicCoffeeMachine class now BasicCoffeeMachine the FilterCoffeeMachine method and also defines the methods addGroundCoffee and brewFilterCoffee .

Similarly, the EspressoMachine class implements the EspressoCoffeeMachine interface with its methods addGroundCoffee and brewEspresso .

Application expansion

After you have split interfaces so that you can upgrade the implementation of two separate coffee machines together, you may be wondering how you can add other types of coffee machines to your application. your. There are generally four options:

  1. The new coffee machine is a FilterCoffeeMachine or an EspressoMachine . In this case, you just need to implement the corresponding interface.
  2. The new coffee machine makes filter coffee and espresso. This situation is similar to the first. The only difference is that the class now implements both FilterCoffeeMachine and EspressoMachine interfaces.
  3. The new coffee machine is completely different from the two we mentioned above. Maybe a pad machine, the kind of machine you want to use to make tea or other hot drinks. In this case, you need to create a new interface and decide if you want to extend CoffeeMachine . In the pad machine example, we don’t do this because you cannot add ground coffee ( addGroundCoffee ) to the pad machine. Thus, the PadMachine class PadMachine not need to implement the addGroundCoffee method.
  4. The new coffee machine offers new functionality, but you can still use it to make filter coffees and espressso. In this case, we should define a new interface for the new function. Its class can implement new interface and one or more existing interfaces ( BasicCoffeeMachine , EspressoMachine ).

summary

Through this article, you can grasp the main idea of Interface Segregation design principles, at the same time you also know the common violations in practice, as well as examples of how to correctly apply this principle. The author of the article also points out 4 common cases when expanding the system and how to handle each case. Hope the article is useful for you.

The article is translated from the source:

https://stackify.com/interface-segregation-principle/

Share the news now

Source : Viblo