01Principio de Responsabilidad Simple – SOLID

Saludos.

Iniciamos una serie de publicaciones sobre los principios SOLID. Los principios S.O.L.I.D. son un conjunto de diseños y buenas prácticas que se emplean en OOD y OOP (diseño y programación orientada a objetos). Estos principios fueron desarrollados y publicados por primera vez por Robert “Tío Bob” Martin hace más de una década. En esta oportunidad detallaremos el primero de los principios, el Principio de Responsabilidad Simple. Este principio nos dice:

«There should never be more than one reason for a class to change»

«No debe existir mas que una sola razón para que una clase cambie»

El punto es que todos los atributos y todas las operaciones de una clase deben estar intrínsecamente relacionados con un solo propósito. Si se encuentra que al modificar una clase tiene dos responsabilidades se debe separar en dos clases respectivamente. Una clase que hace muchas cosas, es muy grande o muy complicada de seguro tendrá mas de una sola responsabilidad.

Para comprender mejor este principio vamos a ejemplificar mediante un diseño de clases.

Diagrama Clases - Violación al Principio de Responsabilidad Simple
Diagrama Clases – Violación al Principio de Responsabilidad Simple

 

El anterior diagrama muestra la violación del principio de responsabilidad simple ya que vemos que la clase Cuenta tiene más de una responsabilidad, esto se lo puede verificar mediante el método Transferir. Si bien tiene sentido que podamos transferir dinero de una cuenta a otra, vemos que se viola este principio al darle la responsabilidad a la clase Cuenta para dicho propósito. Esta operación debe ser sacada de la clase y llevada a otra que podemos  llamar por ejemplo ServicioTransferencia, así nuestra clase Cuenta solo tendría operaciones relacionadas a ella misma.

Veamos como seria una posible solución a la violación del Principio de Responsabilidad Simple.

Solución a Violación al Principio de Responsabilidad Simple
Solución a Violación al Principio de Responsabilidad Simple

 

Mediante este nuevo diseño podemos verificar la única responsabilidad para cada clase. Se ha delegado la responsabilidad a la clase ServicioTransferencia de Transferir dinero de una cuenta origen a una cuenta destino.

Ventajas de Aplicar este principio

  • Código más fácil de escribir y de entender.
  • Menos propenso a errores, ya que cada clase tiene una única responsabilidad bien definida
  • Facilita las tareas de testing : tenemos bien definido que debemos testear en cada clase.
  • Facilita las tareas de mantenimientos
  • Hace que nuestro código sea más robusto y extensible.

Espero les sea de utilidad.

 

 

02 Principio de Abierto/Cerrado – SOLID

Saludos.

Volviendo con las publicaciones de los principios SOLID, hoy veremos el Principio de Abierto/Cerrado (OCP).

Todas las aplicaciones cambian durante su ciclo de vida, ya sea esta por nuevos requerimientos, alguna mala identificación de los requerimientos o por el simple hecho que el cliente así lo requiera. Este principio nos ayuda a estar preparados para estas posibles situaciones, evitando así y reduciendo el impacto a futuros cambios.

El Principio Open/Closed (Open/Closed Principle, OCP) fue presentado por el Dr. Bertrand Meyer en su libro «Object Oriented Software Construction» y afirma que:

Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.

«Las entidades del software (clases, módulos, funciones, etc.) deben estar abiertas para la extensión pero cerrados para la modificación»

 Para comprender mejor este principio vamos a ejemplificarlo por medio de un diseño.

Diagrama clases – Explicación del Principio Abierto/Cerrado
Diagrama clases – Explicación del Principio Abierto/Cerrado

El diagrama anterior es un ejemplo de una clase que rompe con el principio abierto/cerrado (OCP). Vamos a suponer un sistema de gestión de proyectos, de tal manera nos vamos a centrar en la entidad Tarea y vamos a descubrir como rompe con el principio abierto/cerrado.

Como se puede observar en las relaciones dicha clase viene determinando por uno de los estados de la enumeración EstadoTarea (Pendiente, Finalizada, Cancelada), además se puede observar que la clase implementa 3 métodos, Iniciar, Cancelar y Finalizar que cambian si es posible el estado de la tarea. Veamos como sería una posible implementación del método Finalizar.

Violación al Principio de Abierto/Cerrado
Violación al Principio de Abierto/Cerrado

Al parecer esta implementación no esta nada mal, de hecho no esta nada mal si no se agregarán nuevos estados :), pero como comentamos al inicio, «todas las aplicaciones cambian durante su ciclo de vida».

Supongamos entonces un nuevo requerimiento o cambio típico solicitado por el cliente de la aplicación, el cual sería la adición de un nuevo estado para controlar las tareas que se han Propuesto, con lo que la implementación de este método podría ser:

Violación al Principio de Abierto/Cerrado
Violación al Principio de Abierto/Cerrado

Aparentemente, parece una modificación trivial pero este cambio puede involucrar muchos otros, en los métodos y/o clases donde se utilice la enum EstadoTarea, no olvidemos que este nuevo cambio nos haría modificar también la implementación del método Cancelar.

Violación al Principio de Abierto/Cerrado
Violación al Principio de Abierto/Cerrado

Vemos claramente, por cada nuevo estado que implementemos tendremos que identificar la implementación para todas las clases que lo utilizan y modificarlas, violando el principio Abierto/Cerrado (OCP).

A continuación planteamos una solución a la violación del principio utilizando el patrón State.

Solución a violación del Principio Abierto/Cerrado
Solución a violación del Principio Abierto/Cerrado

Básicamente, lo que se ha hecho es crear una clase por cada estado en lugar de tener una única clase cuyos métodos están basados en sentencias condicionadas por el estado de la tarea. Además, con esta nueva implementación se ha delegado la responsabilidad de finalizar, cancelar o posponer a una nueva clase BaseEstadoTarea que que se ha marcado como abstracta. La clase Tarea implementará sus propios métodos y delegará la responsabilidad a través de las clases TareasEstados que heredan de BaseEstadoTarea. Debido a que la clase Tarea gira en torno a un estado, asumimos que el estado inicial por defecto es Pendiente, y así se deberá especificar en el constructor, instanciando a TareaEstadoPendiente.

Vamos a ver como seria la implementación para esta solución.

Implementación de la Solución con el patrón State
Implementación de la Solución con el patrón State

Ante un nuevo requisito en el que intervenga un nuevo estado, lo único que se deberá hacer es crear una nueva clase que herede de BaseEstadoTarea e implementar los métodos virtuales, extendiendo así el comportamiento de la aplicación sin comprometer el código existente.

Espero le sea de utilidad.

Articulo extraido de http://www.programacion.com