What Is This Principle?

The Interface Segregation Principle states that no client code object should be forced to depend on methods it does not use. Basically, each code object should only implement what it needs, and not be required to implement anything else.

Interface Segregation Principle - You want me to plug this in, where?

Benefits

The ISP is all about reducing code objects down to their smallest possible implementation, and removing dependencies the object doesn't need to function properly. The result of implementing this principle, generally speaking, is to have a lot of small, focused interfaces that define only what is needed by their implementations.

A Simple Example

Let's say we are tasked with modeling a newly-opened clothing store that sells jeans. At the moment, that's all they will sell. Now we, being smart programmers, think that we should model this so that if the store wants to sell different products in the future, we can model them appropriately. So, we create an interface for the products and a class for Jeans:

public interface IProduct  
{
    int ID { get; set; }
    double Weight { get; set; }
    int Stock { get; set; }
    int Inseam { get; set; }
    int WaistSize { get; set; }
}

public class Jeans : IProduct  
{
    public int ID { get; set; }
    public double Weight { get; set; }
    public int Stock { get; set; }
    public int Inseam { get; set; }
    public int WaistSize { get; set; }
}

Just a week later, the owner of the store comes to us and tells us that they're now going to sell baseball caps. So, wanting to use the interface we already created, we implement BaseballCap:

public class BaseballCap : IProduct  
{
    public int ID { get; set; }
    public double Weight { get; set; }
    public int Stock { get; set; }
    public int Inseam { get; set; }
    public int WaistSize { get; set; }
    public int HatSize { get; set; }
}

But wait! Why does a baseball cap have an inseam or waist size? Those properties don't make sense for a baseball cap, but because they were defined in IProduct, BaseballCap must implement them.

So what's the solution? Refactor! But how?

Well, what properties do both BaseballCap and Jeans need? Those properties can become the new IProduce interface:

public class Jeans : IProduct  
{
    public int ID { get; set; }
    public double Weight { get; set; }
    public int Stock { get; set; }
}

We currently sell jeans, but Inseam and WaistSize can apply to any type of pants, so let's create an IPants interface:

public interface IPants  
{
    public int Inseam { get; set; }
    public int WaistSize { get; set; }
}

We should be willing to bet that baseball caps won't be the only kinds of hats we'll sell, so we also make a focused IHat interface:

public interface IHat  
{
    public int HatSize { get; set; }
}

Now we can implement both Jeans and BaseballCap:

public class Jeans : IProduct, IPants  
{
    public int ID { get; set; }
    public double Weight { get; set; }
    public int Stock { get; set; }
    public int Inseam { get; set; }
    public int WaistSize { get; set; }
}

public class BaseballCap : IProduct, IHat  
{
    public int ID { get; set; }
    public double Weight { get; set; }
    public int Stock { get; set; }
    public int HatSize { get; set; }
}

Each class now has only properties that they need. Now we are upholding the Interface Segregation Principle!

Potential Hazards

As you might have guessed from the example, the ISP can potentially result in a lot of additional interfaces. If the store was to start selling t-shirts, for example, we would probably create another interface IShirt. There is a possibility that we will have a LOT of interfaces if we strictly adhere to this rule.

There's another potential hazard with implementing this principle: we could have interfaces that are only ever used for one implementation. For example, if we create that IShirt interface and the store only ever sells t-shirts, did we really need the interface? I'd argue that such interfaces are code bloat and should be removed until such time as they are needed, but many people disagree with me.

Is It Worth It?

Maybe. This is the only SOLID principle I feel ambivalent about. On the one hand, aggressively adhering to this principle allows for much more flexible and modifiable code, something I'm a big fan of and is very useful in real-world projects. On the other hand, I'm an extreme deletionist, and would much prefer to delete code rather than write it, so writing a bunch of extra interfaces doesn't sit well with me.

What do you think? Is following the Interface Segregation Principle worth the potential benefits? Or is it more work than is necessary? Let me know in the comments!