Hard Rocking With Interface Segregation Principle

Our systems seem safe when it comes to different requirement sources and adding new features. Privately, you’re safer than ever, as King Benedictus promised to protect you. Your life is so beautiful and so peaceful. At least until someone asks you about deploying some newly developed feature. Worry not, here comes the Interface Segregation Principle!

Tony Loves Hard Rock(s)

It’s a calm December morning. You come to the office, make yourself a coffee and sit by your desk. You turn on the computer..

“Ouch! What the DLL Hell is this?”

You got hit by a piece of rock. Someone’s having a crazy day.

“Ouch! Who is that? Ouch!”

You turn around..

“Ouch! Ouch! Tony, stop! What the Haskell is wrong with you?!”

“It’s not me. As you wrote in your last email: “It’s the monolith”. You’re going to suffer from pieces of mine, until you get done with yours. I don’t want to wait for my new reports until the whole system gets released, “because it’s a monolith”. I don’t give a damn, understood?!”

The Need For Dependency Management

There’s a lot things to consider, if we want to achieve a well-structured monolith with independently deployable modules. One of those, which is absolutely essential, is good dependency management. What I mean by this is not just using Maven, Gradle or some other tool that allows us to specify dependencies. I mean that we conciously decide what each part of the system can depend on.

One of the reasons why it’s so important, that is especially visible in large monolithic systems, is this simple truth:

If module A depends on module B then, if module B changes, then module A might need to be adjusted, rebuilt and redeployed.

Imagine that report generation is one of many things that depend on some “general purpose” services, that you might find in a lot of legacy applications:

Now, let’s say that when adding a new report, you have to modify that “general purpose” service, to provide data for the report that you want to generate. Consider the diagram above, do you see what’s happening? By changing the  CustomerService, you’re forcing a potential rebuild and redeployment of the remaining 5 modules! Likewise, change to the service introduced to satisfy one of the other modules will require rebuild and redeployment of report generation!

Interface Segregation Principle

This is the moment when Interface Segregation Principle comes in:

No client should be forced to depend on methods that it does not use.

What it tells us is that we should find a way to NOT depend on things that we’re not interested in, so that those other things can change independently. In our example, we’re interested in stuff necessary for report generation and we do not want to depend on stuff that is necessary for any of the other modules. Likewise, and maybe even more important in this case, we do not want the other modules to depend on stuff necessary for report generation, because we want to extend this independently!

Applying Interface Segregation

There are two ways in which we might apply interface segregation:

  1. splitting a class to smaller ones with segregated interfaces
  2. Extracting a segregated interface.

The first approach would be desirable in situations, where ISP violation is connected to an SRP violation – in our example, the  CustomerService most likely has more than one reason to change. In such case, we’d adhere to both of the rules with the same refactoring of extracting a dedicated class:

But sometimes, it’s not desirable or even possible to split a class. In such cases, we can apply ISP by extracting interfaces that contain only those methods that are used by a given module:

This might look a bit overwhelming and it certainly would be in the code, but it works. Our modules depend only on things that they really use and the only things that have to be rebuilt and redeployed in case of change are the affected modules and the  CustomerService implementation.

I think I don’t have to say the the first approach is simpler and favorable when possible. The second one does the job, but it might cause the  CustomerService to grow indifinitely. Also, the amount of interfaces created for the sole purpose of segragation, grows substantially.

Wrap Up

That’s it! Now, you’re at least one step closer to making your monoliths more manageable. For the time being, I recommend getting a helmet, because Tony is unlikely to give up! I also hope that there’s less people around thinking that ISP is about changing big interfaces into smaller ones, because “smaller is nicer to read”. Well, maybe it is, but the dependency management argument should be much more compelling. Thanks for reading, take care!

About the Author Grzegorz Ziemoński

King of Tidy Java, nerd that thinks about producing perfect software all the time and proud owner of 2 cats.

follow me on: