Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

When reading articles on ISP, there seem to be two contradicting definitions of ISP:

According to first definition ( see 1, 2, 3), ISP states that classes implementing the interface shouldn't be forced to implement functionalities which they don't need. Thus, fat interface IFat

interface IFat
{
     void A();
     void B();
     void C();
     void D();
}

class MyClass: IFat
{ ... }

should be split into smaller interfaces ISmall_1 and ISmall_2

interface ISmall_1
{
     void A();
     void B();
}

interface ISmall_2
{
     void C();
     void D();
}

class MyClass:ISmall_2
{ ... }

since this way my MyClass is able to implement only the methods it needs ( D() and C() ), without being forced to also provide dummy implementations for A(), B() and C():

But according to the second definition ( see 1 , 2, answer by Nazar Merza), ISP states that MyClient calling methods on MyService shouldn't be aware of methods on MyService that it doesn't need. In other words, if MyClient only needs the functionality of C() and D(), then instead of

class MyService 
{
    public void A();
    public void B();
    public void C();
    public void D();
}

/*client code*/      
MyService service = ...;
service.C(); 
service.D();

we should segregate MyService's methods into client-specific interfaces:

public interface ISmall_1
{
     void A();
     void B();
}

public interface ISmall_2
{
     void C();
     void D();
}

class MyService:ISmall_1, ISmall_2 
{ ... }

/*client code*/
ISmall_2 service = ...;
service.C(); 
service.D();

Thus with the former definition, the goal of ISP is to "make the life of classes implementing IFat interface easier", while with the latter the goal of ISP is to "make the life of clients calling methods of MyService easier".

Which of the two different definitions of ISP is actually correct?

@MARJAN VENEMA

1.

So when you are going to split IFat into smaller interface, which methods end up in which ISmallinterface should be decided based on how cohesive the members are.

While it makes sense to put cohesive methods within the same interface, I thought with ISP pattern the needs of the client take precedence over the "cohesiveness" of an interface. In other words, I thought with ISP we should lump within the same interface those methods needed by particular clients, even if that means leaving out of that interface those methods that should, for the sake of cohesiveness, also be put inside that same interface?

Thus, if there were lots of clients that will only ever needed to call CutGreens, but not also GrillMeat, then to adhere to ISP pattern we should only put CutGreens inside ICook, but not also GrillMeat, even though the two methods are highly cohesive?!

2.

I think that your confusion stems from the a hidden assumption in the first definition: that the implementing classes are already following the single responsibility principle.

By "implementing classes not following SRP" are you referring to those classes that implement IFat or to classes that implement ISmall_1 / ISmall_2? I assume you're referring to classes that implement IFat? If so, why do you assume they don't already follow SRP?

thanks

share|improve this question
4  
Why can't there be multiple definitions that are both served by the same principle? –  Bobson Jun 21 '13 at 17:01
5  
These definitions do not contradict one another. –  Mike Partridge Jun 21 '13 at 17:04
1  
No of course the client's need don't take precedence over the cohesiveness of an interface. You can take this "rule" way to far and end up with single method interfaces all over the place that make absolutely no sense whatsoever. Stop following rules and start thinking of the goals for which these rules were created. With "classes not following SRP" I wasn't talking about any specific classes in your example or that they were not already following SRP. Read again. The first definition only leads to splitting an interface if the interface isn't following ISP and the class is following SRP. –  Marjan Venema Jun 22 '13 at 9:36
1  
Btw: it is not considered "playing nice" to extend your question in this way. I understand in this case because you have fairly long text, but these should really have been comments to my answer. –  Marjan Venema Jun 22 '13 at 9:39
2  
The second definition doesn't care about the implementers. It defines interfaces from the perspective of the callers and doesn't make any assumptions about whether implementers already exist or not. It probably assumes that when you follow ISP and come to implement those interfaces, you would, of course, follow SRP when creating them. –  Marjan Venema Jun 22 '13 at 12:03

3 Answers 3

up vote 2 down vote accepted

Both are correct

The way I read it, the purpose of ISP (Interface Segregation Principle) is to keep interfaces small and focused: all interface members should have very high cohesion. Both definitions are intended to avoid "jack-of-all-trades-master-of-none" interfaces.

Interface segregation and SRP (Single Responsibility Principle) have the same goal: ensuring small, highly cohesive software components. They complement each other. Interface segregation ensures that interfaces are small, focused and highly cohesive. Following the single responsibility principle ensures that classes are small, focused and highly cohesive.

The first definition you mention focuses on implementers, the second on clients. Which, contrary to @user61852, I take to be the users/callers of the interface, not the implementers.

I think that your confusion stems from the a hidden assumption in the first definition: that the implementing classes are already following the single responsibility principle.

To me the second definition, with the clients as the callers of the interface, is a better way of getting to the intended goal.

Segregating

In your question you state:

since this way my MyClass is able to implement only the methods it needs ( D() and C() ), without being forced to also provide dummy implementations for A(), B() and C():

But that is turning the world upside down.

  • A class implementing an interface does not dictate what it needs in the interface it is implementing.
  • The interfaces dictate what methods an implementing class should provide.
  • The callers of an interface really are the ones that dictate what functionality they need the interface to provide for them and thus what an implementer should provide.

So when you are going to split IFat into smaller interface, which methods end up in which ISmall interface should be decided based on how cohesive the members are.

Consider this interface:

interface IEverythingButTheKitchenSink
{
     void DoDishes();
     void CleanSink();
     void CutGreens();
     void GrillMeat();
}

Which methods would you put in ICook and why? Would you put CleanSink together with GrillMeat just because you happen to have a class that does just that and a couple of other things but nothing like any of the other methods? Or would you split it into two more cohesive interfaces, such as:

interface IClean
{
     void DoDishes();
     void CleanSink();
}

interface ICook
{
     void CutGreens();
     void GrillMeat();
}

Interface declaration note

An interface definition should preferably be on its own in a separate unit, but if it absolutely needs to live with either caller or implementer, it should really be with the caller. Otherwise the caller gets an immediate dependency on the implementer which is defeating the purpose of interfaces altogether. See also: Declaring interface in the same file as the base class, is it a good practice? on Programmers and Why should we place interfaces with classes that use them rather than those that implement them? on StackOverflow.

share|improve this answer
    
Can you see the update I made? –  EdvRusj Jun 21 '13 at 20:39
    
" the caller gets an immediate dependency on the implementer" ... only if you violate DIP (dependency inversion principle), if caller internal variables, parameters, return values, etc are of type ICook instead of type SomeCookImplementor, as DIP mandates, then it doesn't have to depend on SomeCookImplementor. –  user61852 Jun 21 '13 at 20:57
    
@user61852: If interface declaration and implementer are in the same unit, I do immediately get a dependency on that implementer. Not necessarily at run time, but most certainly on the project level, simply by the fact that it is there. The project can no longer compile without it or whatever it uses. Also, Dependency Injection is not the same as the Dependency Inversion Principle. You might be interested in DIP in the wild –  Marjan Venema Jun 22 '13 at 9:24
    
thank you all for helping –  EdvRusj Jun 22 '13 at 18:01

You confuse the word "client" as used in the Gang of Four documents with a "client" as in consumer of a service.

A "client", as intended by Gang of Four definitions, is a class that implements an interface. If class A implements interface B, then they say A is a client of B. Otherwise the phrase "clients should not be forced to implement interfaces they don't use" wouldn't make sense since "clients" ( as in consumers ) don't implement anything. The phrase only makes sense when you see "client" as "implementor".

If "client" meant a class that "consumes" (calls) the methods of another class that implements the big interface, then by calling the two methods you care about and ignoring the rest, would be enough to keep you decoupled from the rest of the methods you don't use.

The spirit of the principle is avoid the "client" ( the class implementing the interface ) having to implement dummy methods in order to comply with the whole interface when it only cares about a set of methods that are related.

Also it aims to having the less amount of coupling as possible so that changes made in one place cause the less impact. By segregating the interfaces you reduce the coupling.

That problems appears when the interface does too much and have methods that should be divided in several interfaces instead of just one.

Both of your code examples are OK. It's only that in the second one you assume "client" means "a class that consumes/calls the services/methods offered by another class".

I find no contradictions in the concepts explained in the three links you gave.

Just keep clear that "client" is implementor, in SOLID talk.

share|improve this answer
    
But according to @pdr, while code examples in all the links do adhere to ISP, the ISP definition is more about "isolating the client ( a class that call methods of another class ) from knowing more about the service" than it is about "prevention from clients ( implementors ) being forced to implement interfaces they don't use." –  EdvRusj Jun 21 '13 at 18:09
1  
@EdvRusj My answer is based on the documents in Object Mentor ( Bob Martin enterprise ) website, writen by Martin itself when he was in the famous Gang of Four. As you know the Gnag of Four was a group of software engineers, including Martin, that coined the S.O.L.I.D acronym, identified and documented the principles. docs.google.com/a/cleancoder.com/file/d/… –  user61852 Jun 21 '13 at 18:37
    
So you disagree with @pdr and thus you find the first definition of ISP ( see my original post ) more agreeable? –  EdvRusj Jun 21 '13 at 18:49
    
@EdvRusj I think both are right. But the second one adds unnecessary confusion by using the client/server metaphor. If I have to choose one, I'd go with the official Gang of Four one, which is the first. But what is important it to reduce coupling and unnecessary dependencies which is the spirit of the SOLID principles after all. It doesn't matter which one is right. The important things is you should segregate interfaces acording to bahaviors. That's all. But when in doubt, just go to the original source. –  user61852 Jun 21 '13 at 18:53
1  
I so disagree with your assertion that "client" is implementor in SOLID talk. For one it is linguistic nonsense to call a provider (implementer) a client of what it is providing (implementing). I also have not seen any article on SOLID that tries to convey this, but I may simply have missed that. Most importantly though it sets up the implementer of an interface as the one deciding what should be in the interface. And that makes no sense to me. The callers/users of an interface define what they need out of an interface and the implementers (plural) of that interface are bound to provide it. –  Marjan Venema Jun 21 '13 at 19:47

ISP is all about isolating the client from knowing more about the service than it needs to know (protecting it against unrelated changes, for example). Your second definition is correct. To my reading, only one of those three articles suggests otherwise (the first one) and it is just plain wrong. (Edit: No, not wrong, just misleading.)

The first definition is much more tightly linked to LSP.

share|improve this answer
2  
In ISP, clients shouldn't be forced to CONSUME interface components that they don't use. In LSP, SERVICES shouldn't be forced to implement method D because the calling code requires method A. They are not contradictory, they are complementary. –  pdr Jun 21 '13 at 17:16
1  
@EdvRusj, the object that implements InterfaceA that ClientA calls may in fact be the exact same object that implements InterfaceB needed by Client B. In the rare cases where the same client needs to see the same object as different Classes, the code won't usually "touch". You'll be looking at it as an A for one purpose and a B for the other purpose. –  Amy Blankenship Jun 21 '13 at 17:20
1  
@EdvRusj: It might help if you rethink your definition of interface here. It's not always an interface in C#/Java terms. You could have a complex service with a number of simple classes wrapped around it, such that client A uses wrapper class AX to "interface" with service X. Thus, when you change X in a way that affects A and AX, you are not forced to affect BX and B. –  pdr Jun 21 '13 at 17:56
1  
@EdvRusj: It would be more accurate to say that A and B don't care if they're both calling X or one is calling Y and the other calling Z. THAT is the fundamental point of ISP. So you can choose which implementation you go for, and easily change your mind later. ISP doesn't favour one route or the other, but LSP and SRP might. –  pdr Jun 21 '13 at 18:08
1  
@EdvRus "It might help if you rethink your definition of interface here..." Interface segregation definitely is referring to the API of the Class, not a layer on top of the Class that provides access Though you could provide a layer that provides the correct Interface and passes through to a different Class, the fact that the outer Class is mediating access to an inner Class is completely unrelated and invisible to the fact that it is implementing whatever Interface it is providing. –  Amy Blankenship Jun 22 '13 at 19:38

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.