Rob Sutherland’s Musings on Life, Code, and Anything Else

ISP: Interface Segregation Principle

This is the I of the SOLID series.

In short: "no client should be forced to depend on methods it does not use."

If interfaces are kept small and extremely cohesive we prevent having to implement unrelated functionality in implementations or breaking the Liskov Substitution Principle.

This principle approaches common sense, but that doesn't mean it is easy. As a developer, we have to name things and we all know that naming things is hard. We tend to not want to do it. This is where the clutter comes in. If we name something generic enough we can put almost anything in it. This however leads to clutter.

public interface IDataAccess 
{
    void AddStudentToClass(int studentid, int classId);
    IEnumerable<Registration> AllStudentsInClass(int classId);
    IEnumerable<Class> GetClasses();
    IEnumerable<Course> GetCourses();
    IEnumerable<FiscalWeek> GetFiscalWeeks();
    IEnumerable<Registration> GetRegistrations(int studentId);
    IEnumerable<Registration> GetRegistrations(string classNumber);
    IEnumerable<Student> GetStudents();
    IEnumerable<Student> GetStudentsInClass(string classNumber);
    void RegisterStudent(int classId, int studentId);
    void SaveAccreditation(Accreditation accreditation);
    void RegisterStudentInMultipleClassesByNumber(int studentId, string[] classNumbers);
}

While this example takes it to the extreme you've probably seen code like it. I've written code like it before. It can be very tempting, especially when starting what you think will be a simple project with a short life-span. While in theory this limits the dependencies on the consumers of the interface (e.g. the controller only has to have one dependency) we make it more difficult to change anything about the interface or (more importantly) anything about the implementation of the interface.

Implementing this interface - without breaking LSP - would be tedious at best. Violating ISP also leads to either overly verbose method names or method names that aren't clear enough.

When the interface gets cluttered with unrelated methods it is also harder to see when we inadvertantly change conventions or when we duplicate work. In the above example, there's an AddStudentToClass and an RegisterStudent method. These may do the same thing, the sound like they could do the same thing. Notice that the parameters are slightly different too. They both take two integers, but not in the same order.

The Interface Segregation Principle teaches us to group like things together. This guides us to better cohesion within the interface and the implementation of that interface.

Take a moment: How would you group the methods in the IDataAccess interface to provide a set of interfaces that provided better segregation. After you made your separate interaces was it clearer to see the possible overlap of functionality in different methods? Was it easier to see differences in method naming conventions or parameter order and naming conventions?