c# Object oriented design – ¿Cómo aplicas el principio Interface Segregation?

Si alguna vez te has preguntado ¿Qué es el principio Interface Segregation? y ¿Cómo lo puedo implementar? te recomiendo que leas este post.
Principio Interface Segregation
Principio Interface Segregation


Artículos relacionados:

Este término fue introducido por Robert C. Martin  durante una consultoría que realizó a la empresa Xerox. En ese momento Xerox había creado una impresora que ejecutaba una gran variedad de tareas. Este software fue creado desde cero, con forme iba creciendo el software hacer un cambio también se volvía poco a poco más complicado. El problema se debió a que una clase era la encargada de ejecutar la mayoría de las tareas; la solución que aplico Robert C. Martin es lo que conocemos ahora como el principio de Interface Segregation. Este es el cuarto de los cinco principios SOLID.

Iniciemos con esta frase obtenida del libro Agile Principles, Patterns, and Practices in C#:

No client should be forced to depend on methods it does not use.

Además, nos dice lo siguiente en su artículo The Principles of Object Oriented Design:

Make fine grained interfaces that are client specific.

Este principio señala que se deben definir interfaces pequeñas que resuelvan un problema específico (Role Interface), en lugar de tener interfaces grandes que  hagan muchas cosas (Head Interface). Los clientes no deben ser forzados a implementar interfaces que ellos no necesiten. En este caso debemos tomar como una interfaz a: el tipo Interface y a la interfaz pública de una clase que está formada por propiedades y métodos públicos.

ISP - Segregación de interfaces
ISP – Segregación de interfaces
¿Sobre qué artefactos aplica este principio?
  • Clases
  • Interfaces
¿Qué beneficios trae el trabajar con este principio?
  • Bajo acoplamiento.
  • Alta cohesión.
  • Código fácil de cambiar.
  • Código fácil de mantener.
  • Código fácil de desplegar.
¿Cuándo debemos aplicar este principio?
  • Cuando existan clases con métodos vacíos o que devuelvan valores por defecto.
  • Cuando existan clases con métodos que devuelvan excepciones del tipo NotImplementedException.
  • Cuando un cliente usa solo algunos métodos de una clase.
¿Cuándo no debemos aplicar este principio?
  • Cuando una clase no va a ser rehusada (Una clase controladora o un servicio web)
  • Cuando nadie depende de esta clase.
Argumentos en contra de este principio
  • Requiere mayor experiencia
Veamos el siguiente ejemplo:
Cómo no aplicamos este principio

Cuando tenemos una clase con tal cantidad de métodos y sobre todo SABEMOS que será extendida por otras clases:

ISP - SqlmembershipProvider
ISP – SqlmembershipProvider

En este ejemplo la clase MembershipProvider obliga a cada subclase, como a la clase SqlMembershipProvider, a implementar todos los métodos de su interfaz publica, aunque solo se necesite modificar el comportamiento de algunos métodos de la clase base. En este caso solo necesitamos modificar el método ValidateUser, pero por la forma en como fue diseñada la clase base nos obliga a implementar todos los métodos:

public class MembresiaPersonalizada : MembershipProvider
{
    public override bool ValidateUser(string username, string password)
    {
        //Codigo
    }

    public override bool ChangePassword(string username, string oldPassword, string newPassword)
    {
        throw new NotImplementedException();
    }

    public override bool ChangePasswordQuestionAndAnswer(string username, string password,
        string newPasswordQuestion, string newPasswordAnswer)
    {
        throw new NotImplementedException();
    }

    public override MembershipUser CreateUser(string username, string password, string email,
        string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey,
        out .MembershipCreateStatus status)
    {
        throw new NotImplementedException();
    }

    public override bool DeleteUser(string username, bool deleteAllRelatedData)
    {
        throw new NotImplementedException();
    }
}

Nota: Al diseñar una clase de esta manera se viola el principio Liskov Substitution.

Como aplicamos este principio

Podemos aplicar este principio creando interfaces pequeñas con métodos que tengan relación entre sí para no obligar al cliente que dependa de cosas que no necesita. Tomemos de referencia el nuevo modelo de identidad de Asp.net:

ISP - Aspnet Identity
ISP – Aspnet Identity

Si solo necesitamos manipular el password de una cuenta debemos implementar la interface IUserPasswordStore:

public class CustomPasswordStore : IUserPasswordStore<IUser>
{
    public Task<string> GetPasswordHashAsync(IUser user)
    {
        //Codigo
    }
    public Task<bool> HasPasswordAsync(IUser user)
    {
        //Codigo
    }
    public Task SetPasswordHashAsync(IUser user, string passwordHash)
    {
        //Codigo
    }
}

Si solo necesitamos manipular los datos del usuario debemos implementar la interface IUserStore:

public class CustomUserStore : IUserStore<IUser>
{
    public Task CreateAsync(IUser user)
    {
        //Codigo
    }
    public Task DeleteAsync(IUser user)
    {
        //Codigo
    }
    public Task<IUser> FindByIdAsync(string userId)
    {
        //Codigo
    }
    public Task<IUser> FindByNameAsync(string userName)
    {
        //Codigo
    }
    public Task UpdateAsync(IUser user)
    {
        //Codigo
    }
}
Conclusión

Este principio señala que se deben definir interfaces pequeñas que resuelvan un problema específico, en lugar de tener interfaces grandes que  hagan muchas cosas. Este principio se aplica a clases e interfaces. Como principales beneficios tenemos que nos permite aumentar la cohesión y bajar el acoplamiento. Se debe aplicar cuando existen métodos en una clase que devuelvan la excepción del tipo NotImplementedException. También tiene argumentos en contra que señalan que se requiere experiencia para diseñar las clases.

Referencias:
Metal Tip:

Este artículo lo escribí escuchando la canción Masterplan de la banda Masterplan de Alemania, les comparto el enlace.

Happy coding and Stay Heavy lml

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s