Plumbee engineering

Taking advantage of interface segregation

| Comments

What is the Interface Segregation Principle?

The interface segregation principle states that no client should be forced to depend on methods that it does not use.

Following this principle makes you split fat interfaces into specific ones that will only show methods that are required for the clients.

This leads to a decoupled system that is easier to refactor, change and understand.

Using Interface Segregation to add functionality to the UI

When writing a UI many times similar functionality is shown in different views, like playing of an animation, playing a sound or handling a timer.

Usually, UI frameworks have a controller or mediator that handles the logic of the view. So if we don’t take care of this carefully we can end repeating the same logic in different mediators.

In our team we use Robotlegs as MVC framework and we already faced this problem, so lets show you a real example.

The problem

We needed a view that was going to play a sound, another view that was showing a timer, and another one that needed to play a sound, show a timer and present a collect button, so we came up with the following design:

The implementation of the DailyBonusNextDayMediator was:

Finally, this was the interface of its view:

This design had the following problems:

We were duplicating the play sound and the timer functionalities.

Every view that needed to play a sound had the following piece of code replicated:

And every view that needed a timer would have the following replicated:

The DailyBonusNextDayMediator was doing 3 completely different things:

  • Playing a sound.
  • Handling a timer.
  • Showing the collect button for that daily bonus if it was ready.

This was a problem because the name of the class does not really reflect what the class does, so someone who was not familiar with the codebase would not expect that, for example, the code of playing a sound or a timer is inside this particular class.

Also this is breaking the single responsability principle

If we wanted to add a new view with a sound or a timer, we had to replicate again the functionalities in its mediator.

If we wanted to change something in the behaviour of the timers for example, we had to find every replication and change it and its tests, a mechanical task prone to errors that could be avoided with a better design.

Another hazard of this was that if a developer was not familiar with the way we implemented the timer, they would just implement it again themselves in a different way, leading to have several pieces of code in different classes achieving similar results with different implementations.

Our solution

To solve these problems we created 3 different interfaces and 3 specialized mediators:

This is how the new implementation looks:

Now each mediator does one thing and they can be reused by other views. The behaviour will be already fully tested and the integration of a timer or a sound in a new view will be very quick.

The benefits of this are the following:

Several small classes allow for a better reusability.

Structuring a codebase like this will lead to a lot of different components already working and fully tested that can be used by the developers, speeding up the development of new views that contain common features such as the sound or the timer.

If in our project we have a lot of elements that share a functionality, this reduce significantly the amount of code and time needed to implement.

Less private methods allow for better test coverage.

By having less private methods, we can achieve better test coverage with smaller, readable and easy to write tests.

The code is simpler and easier to maintain: if you don’t want a timer you can just remove the interface and the implemented methods.

It eases a lot the process of configuration and customization. You can add or remove functionalities to a view in a very quick and safe way.

Also having the component implementation in a centralized place will allow us to modify its behaviour easily and the changes will be present in all the views using the component.

Do you want to read more?

If you like the topic here is a some more information: