Saltar al contenido

Mes: agosto 2019

Liskov Substitution Principle

El tercer principio que compone SOLID es el Liskov Substitution Principle, y este nos plantea

Plantea una guía de cuando debemos usar herencia en POO.

Let Φ (x) be a property provable about objects x of type T. Then Φ (y) should be true for objects y of type S where S is a subtype of T.

Barbara Liskov, 1988

Este principio, podemos entenderlo en su modo más simple de la siguiente forma «Las clases derivadas, deben poder ser sustituidas por sus clases base».

Para ejemplificar este principio, usaremos el típico ejemplo del rectángulo y el cuadrado. Veamos el proyecto que tenemos definido:

Nuestra clase base es el rectángulo:

Clase base rectángulo

Queremos calcular el área de nuestro rectángulo o las clases que lo implementen, como un cuadrado. Para esto, creamos el siguiente método:

Método para hallar el área

Digamos que ahora necesitamos implementar un cuadrado, y con esta finalidad creamos la siguiente clase:

Clase del cuadrado

Como ven, el cuadrado implementa nuestro rectángulo y lo que hacemos es definir en sus propiedades que las propiedades base (las que esta implementado) son iguales en su ancho y altura, que como sabemos corresponden a los lados de un cuadrado. Si probamos obtener el cuadrado de ambas clases, tendremos el siguiente resultado:

Resultado al obtener el área sin probar el principio Liskov

Notese que se esta creando una nueva instancia del Square y por esto obtenemos los resultados correctos. Sin embargo, si buscamos poner en práctica lo definido por el principio liskov, veamos que resultado obtenemos.

Resultado poniendo a prueba el principio Liskov

Lo que sucede es que nuestra clase Rectangle, es la que es inicializada, por lo tanto sólo posee el Width igual a 4, y no el Height. Cuando se busca obtener el área realiza la multiplicación del ancho por la altura y tenemos como resultado 0. Para poder respetar este principio, es necesario que realicemos el siguiente cambio:

Cambios para respetar el principio Liskov

Lo que hacemos es declarar como virtuales las propiedades de nuestra clase base, por lo que cuando se incialice y el compilador determine que es virtual, va a buscar algún override que es justo lo que hacemos en la clase derivada. De este modo, sabe que debe usar la propiedad de Square e iguala los lados a 4 que es lo que definimos en el Width. Si probamos ahora nuestro método, tendremos el siguiente resultado:

Prueba final del cálculo del área

Donde como se ve, ya se respeta el principio que hemos tocado ampliamente en este post. Espero que les ayude a entender un poco más este principio, así mismo comentarles que este es el tercer post de los principios que componen SOLID. Como siempre, dejo el video del desarrollo de esta post y el link al repositorio en github.

REPO: GITHUB

Listado de POST sobre SOLID anteriores:

Deja un comentario

Open Close Principle

Siguiendo con la linea de post que presentan los principios que componen marco de buenas prácticas SOLID. El que vamos a desarrollar en este post es el «Open Close Principle», esto hace referencia a que el código que desarrollamos debería estar abierto a ser extendido y cerrado a las modificaciones.

Sin más, veamos el ejemplo que vamos a desarrollar en este post:

Supongamos que estamos desarrollando un sistema para un almacen, en el cual se manejan productos. Estos productos, poseen características, las cuales pueden ser:

Clase de Productos

En donde los «Enums» mostrados poseen los siguientes elementos:

Clase de Enums

Digamos que por necesidad del negocio, nos vemos obligados a filtrar los productos que vamos almacenando por su color, teniendo esto en mente, creamos una nueva clase que llamaremos «ProductFilter».

De este modo, si queremos filtrar un grupo de colores, por un color en particular deberíamos hacer algo muy similar a esto:

Filtro por color los productos

De este modo, tenemos 3 productos, los cuales se agregan a una lista y esta lista se proporciona al método de filtrado que hemos creado. Si ejecutamos esta aplicación, tenemos el siguiente resultado:

Filtrado por color a los productos
Filtrado Correcto

Como podemos ver, se ejecuta sin problemas. El problema viene cuando requerimos realizar más filtros. Digamos que ahora nos indican que el filtrado también sea por tamaño, o por color y tamaño, terminariamos llenando nuestra clase «ProductFilter» de métodos. Algo muy similar a esto:

Llenado de métodos para diversos tipos de filtros

Como ven, esto rompe claramente el principio de Open Close Principle. Deberíamos de poder extender nuestros filtros, sin afectar la clase que ya se tiene, esto se puede conseguir a través de interfaces. En este caso, para respetar este principio voy a usar el «specification pattern». Veamos como podemos implementarlo y respetar este principio.

Es necesario creas dos interfaces para poder llevar a cabo la implementación de este patrón de diseño, siendo la primera una que nos permitirá definir la especificación, cuando esta va a estar satisfecha y el tipo de elemento que recibe como tipo de entrada y la segunda espara implementar el filtro y como este se lleva a cabo.

Interfaz IFilter
Interfaz ISpecification

Ahora, implementemos el primero de los filtros, este es es el «ColorSpecification»:

ColorSpecification

Como pueden ver, implementamos la interfaz definida en el paso anterior, tenemos una variable que se inicializa en el constructor, que para el filtro es el color y en el método «IsSatisfied» solo se retorna true si el color del producto que nos proporcionan es igual al que se inicializa en el constructor.

Para poder usar este filtro es necesario implementar también la interfaz «IFilter», lo cual realizamos del siguiente modo:

Implementación del IFilter

Del mismo modo que en la implementación anterior, se se le indica el tipo de elemento con el cual se desea filtrar, iteramos sobre la lista de estos elementos y solo solo cuando la especificación haya sido satifecha retornamos, el «yield» lo usamos por la eficiencia en el recorrido de nuestra lista.

Veamos como usamos este filtro en nuestra clase principal y que resultado obtenemos:

Uso del filtro
Resultado del nuevo filtrado

Finalmente, mostrare como se puede realizar el más de un filtro a la vez, para ejemplificar esto, creare un filtro por tamaño, siguiendo el mismo esquema ejemplificado anteriormente. Para poder adicionar más de un filtro es necesario crear una nueva clase pero ahora su tipo también será genérico, del siguiente modo:

AndSpecification para realizar más de un filtro

Inicializamos dos variables en el constructor, ambas del tipo «ISpecification», y sólo se satisface cuando ambas variables lo están. Para consumir este método, debemos de hacerlo del siguiente modo:

Consumiendo más de un filtro a la vez

Se le tienen que indicar los filtros que se quieren realizar y al consumir este filtro en el cual buscamos un producto del color verde y de tamaño pequeño, nuestro resultado es el siguiente:

Resultado de ambos filtros

Espero que les ayude a entender un poco más este principio, así mismo comentarles que este es el segundo post de los principios que componen SOLID. Como siempre, dejo el video del desarrollo de esta post y el link al repositorio en github.

REPO: GITHUB

Listado de POST sobre SOLID anteriores:

Deja un comentario