Question

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

My question is: how exactly can a client depend on something that it does not use? It looks like the existence, the state and even non-existence of something I don't use, I don't depend on. Perhaps, instead of depend, we should say know about the existence of. That is, ISP could state, no client should know about the existence of methods it does not use, but I am sure Uncle Bob used the word depend for a good reason. Any explanations?

Was it helpful?

Solution

The Client has a dependency on the Interface and the Interface declares the methods which must be implemented. So if you have:

IDependency 
{
    RequiredByClient();
    NotRequiredByClient();
}

and

Client(IDependency dependency)

Then the compiler ensures that any IDependency given to the client MUST implement both methods. If I write a new implementation of the dependency just for my client, I am forced to do something like:

MyDependency : IDependency 
{
    RequiredByClient()
    {
        dostuff();
    }

    NotRequiredByClient()
    {
        throw NotImplementedException();
    }
}

Which is going to cause problems if someone tries to use it in another scenario. eg

Client2WhichNeedsTheOtherMethod(IDependency dependency); //i hope this works!!

Really I want to be able to write

MyDependency : IDependencyForClient
{
    RequiredByClient()
    {
        dostuff();
    }
}

But in order to be able to do this I have to split the interface into two and define the client as

IDependencyForClient
{
    RequiredByClient();
}

IDependencyForClient2
{
    NotRequiredByClient();
}

Client(IDependencyForClient dependency)

OTHER TIPS

You have a point, in pure OO languages like Java you don't have stand-alone methods, so when we talk about dependency we talk about classes and interfaces, not between methods. So by concept the "depend on methods" phrase is wrong.

That said, let's try to clarify how non-segregated interfaces, i.e., interfaces that are too general and hence have too many mathods that are not client-specific can do harm. I'm sure you know this but it could help other readers.

Implementors:

When you implement an interface you are forced to implement all it's methods(*) even though you only leave stubs that do nothing or return null, you cannot simply ignore them.

Once you implement method of an interface you hace a dependency on that method. Should that method, for example, get to throw a new Exception in the interface declaration you will be forced to add that to your implementing classes.

Client classes:

This is the case when you could theoretically ignore the methods you don't use, and this is precisely what the principle mentions (clients). To understand this let's revise another principle, the DIP which states one should depend upon abstractions, not upon concretions. So interfaces make DIP possible. Well, when you depend on an interface you are depending on the whole of it, not just on methods A or B. What the principle means is that many client-specific interfacwes are better than one big, generic interface. Maybe the class, in a strict sense, is not depending on the non-used methods but you as a programmer do have to know about them. Just imaging programming a class that uses objects that implement giant inteface X which containts methods that you don't use... the IDE will keep up bringing you a very long list of methods that you don't use and also when reading the documentation of the interface you will have to go through all those methods' documentation.

(*) The exception of this are abstract classes that are not forced to implement anything but then any class extending it will have to implement all the methods.

Here is a good link that explains the dependency:

http://prasadhonrao.com/solid-principles-interface-segregation-principle-isp/

I want to summarize the problem. First of all we should understand the terms:

Client - The concrete derivative of the (fat) interface which might not be segregated, i.e. small enough Service - Some function that takes an object that implements the interface (in a a concrete Client) and does something for that client

So some services don't use some of the methods of the Interface that a Client must implement, and others use all of them. But as that Client is forced to implement all methods even if for some specific client instance and for some specific service instance that method is not relevant we say that the Client is dependent on the functions it does not use.

Licensed under: CC-BY-SA with attribution
scroll top