ISP - Interface Segregation Principle

Many client-specific interfaces are better than one general-purpose interface.

The Interface Segregation Principle (ISP) states that the larger interfaces should be split into smaller ones. By doing so, we can ensure that implementing classes only needs to be concerned about the methods that are of interest to them.

This principle is quite easy to understand. Imagine that we have a big interface, about 100 methods. The implementations will be quite miserable and can be redundant because a class does not need to use all 100 methods. When an interface is broken down into many small interfaces, including related methods, it is easier to implement and manage.

interface Repository<T, ID> {
 
    Iterable<T> findAll();
 
    T findOne(ID id);
 
    T save(T entity);
 
    void update(T entity);
 
    void delete(ID id);
 
    Page<T> findAll(Pageable pageable);
 
    Iterable<T> findAll(Sort sort);
}

As you can see, the interface Repository includes a lot of methods: get list, get by id, insert, update, delete, get paginated list, sort, etc. The implementations will be quite miserable, sometimes unnecessary, we won't use them all.

Instead, we can split it like this:

interface CrudRepository<T, ID> {
 
    Iterable<T> findAll();
 
    T findOne(ID id);
 
    T save(T entity);
 
    void update(T entity);
 
    void delete(ID id);
 
}
 
interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {
 
    Page<T> findAll(Pageable pageable);
 
    Iterable<T> findAll(Sort sort);
}

Usually, the CrudRepository function is enough. For some functions that we need to implement from the PagingAndSortingRepository interface.

Another common ISP violation in the project is the CommonUtils class. This class includes a lot of methods: handling date-time, numbers, strings, converting to JSON format, etc. everything related to common processing is here. The more methods, the larger class, then there will be many problems such as duplicate code, many similar methods do not know which method to use, and when errors arise, it is difficult to debug, and maintain. For these cases, we should break them down by their function, for example, DateTimeUtils, StringUtils, NumberUtils, JsonUtils, and ReflectionUtils, ... so it will be easier to manage and use.

Techniques to identify violations of ISP:

  • Fast interfaces

  • Interfaces with low cohesion

  • Empty method implementations.

Last updated