SOLID: Principio de Segregación de Interfaces

Introducción al principio

Fue propuesto por Robert C.Martin (Uncle Bob), indica lo siguiente:

Los clientes no deben verse obligados a depender de interfaces que no utilizan.

Este principio demuestra que los principios SOLID interactúan y se mejoran entre sí. Nos ayuda a resolver el problema que se suele presentar si no aplicamos bien el Principio de sustitución de Liskov al definir interfaces. Como consecuencia nos vemos obligados a lanzar una excepción en métodos que no usamos y que estamos obligados a tener porque implementamos un interface.

Este principio divide las interfaces que son muy grandes en otras más pequeñas y adaptadas al cliente, ya que las interfaces pesadas no escalan bien.

Un interface lo marca el cliente que lo consume, por lo tanto no debe tener métodos que no va a utilizar.

Ejemplo visual

Adapta el interface a las necesidades individuales del cliente.

Ejemplo de código

Inicialmente en el ejemplo de Sustitución de Liskov teníamos una interface y dos implementaciones, donde una de ellas no implementaba un método y en su lugar generaba una excepción.

public interface IProductService  
{
   IResult Update(IEnumerable<Product> products);

   List<Product> GetFilteredProductList
                  (int pageNumber, int pageSize);
}

public class APIProductClient: IProductService  
{    
   public IResult Update(IEnumerable<Product> products);
   {
         //code
   }

   public List<Product> GetFilteredProductList
            (int pageNumber, int pageSize);
   {
        //code
   }
}

public class FTPProductClient: IProductService  
{    
   public IResult Update(IEnumerable<Product> products);
   {
         //code
   }

   public List<Product> GetFilteredProductList
            (int pageNumber, int pageSize);
   {
         throw new NotImplementedException();
   }
}

Para solucionar el problema aplicamos el Principio de Segregación de Interfaces.

public interface IProductReadService  
{
   List<Product> GetFilteredProductList
                  (int pageNumber, int pageSize);
}

public interface IProductWriteService  
{
   IResult Update(IEnumerable<Product> products);
}
public class APIProductClient:  
         IProductReadService,
         IProductWriteService
{    
   IResult Update(IEnumerable<Product> products);
   {
         //code
   }

   List<Product> GetFilteredProductList
                  (int pageNumber, int pageSize);
   {
        //code
   }
}

public class FTPProductClient:  
                 IProductWriteService
{    
   IResult Update(IEnumerable<Product> products);
   {
         //code
   }
}

Separando la abstracción en dos, estamos escuchando a las necesidades de los clientes. El cliente de la implementación por FTP solo le interesa el método de escritura y no el de lectura.

Conclusiones

Aplicando el Principio Segregación de Interface cada cliente solo tiene acceso a lo que necesita. También conseguimos que los detalles dependan de las abstracciones y no las abstracciones de los detalles que es muy importante para que las necesidades las marque el cliente.