Newsletter para devsEntra
Web Reactiva

WR 93: Principios S.O.L.I.D. para novatos

Un audio con código asociado, un experimento divulgativo para dar a conocer una de las bases de las buenas prácticas en programación.

Escúchalo también en Spotify | Apple Podcasts | Google Podcasts | iVoox

Un episodio con aires de experimento. Si alguien me dice hace dos años que me iba a atrever a hablar de estos temas… :)

Es muy importante para mi ayudarte a entender estos conceptos y buenas prácticas de programación. Es esencial que los adoptes como propios y eso estamos intentando conseguir en los directos de la Zona Premium.

Nos atrevemos incluso a ponernos retos para aprender a añadir a nuestro stack de conocimientos el análisis estático de código

Un buen punto de inicio

Tienes el código de ejemplo en este repositorio principios-solid-para-novatos.

Está ejecutado en PHP pero estimo que es sencillo de seguir. He intentado que sea ante todo didáctico, con lo que me he tomado algunas licencias como utilizar nombres de métodos con palabras en castellano o similares.

Si es conveniente tener conocimientos básicos de programación orientada a objetos. Puede ser una buena excusa para empezar intentar comprender justo lo que hablamos aquí.

A disfrutar ahora de los cinco principios S.O.L.I.D. postulados por Robert C. Martin a principios de los 2000. Aquí están:

1. Principio de responsabilidad única

“Single responsibility principle” en inglés.

Un objeto no debería tener más de un motivo para cambiar.

Dicho de otra forma, cada clase debe ocuparse sólo de una responsabilidad. Dejemos atrás esas clases “endiosadas” con métodos enormes donde mezclamos lógica de negocio, consultas directas a la base de datos e, incluso, inserción de plantillas como cadenas de texto.

Es el principio más fácil de romper y también de detectar.

Puedes ver el ejemplo de código en 1-single-responsability.

2. Principio de abierto/cerrado

“Open/closed principle” en inglés.

Las entidades deben estar abiertas para su extensión y cerradas para su modificación.

Es habitual cuando se comienza crear métodos o funciones querer diferenciar todos los casos posibles de una especificación. En nuestro ejemplo, el tipo de animal (vaca, pollo…) del que queremos calcular las “patas”.

Si usamos un if o un switch estaremos seguramente rompiendo este principio. El problema generado es claro: ¿qué hacemos si tenemos que añadir un nuevo tipo de animal? Hay que volver a modificar ese método condicional.

Mejor crear una abstracción en el que cada objeto sepa si tiene que devolver los valores de sus propiedades.

Un ejemplo en código con dos refactorizaciones en 2-open-closed.

3. Principio de sustitución de Liskov

“Liskov substitution principle” en inglés.

Cada clase que hereda de otra puede usarse como su padre sin necesidad de conocer las diferencias entre ellas.

El más completo de todos los principios, también el que puede pasar más inadvertido en la ejecución del código.

Este principio fue introducido por Barbara Liskov: la primera mujer doctorada en Ciencias de la Computación en Estados Unidos.

Tiene tres hitos fundamentales:

  1. Las precondiciones no pueden ser reforzadas por una clase hija y las postcondiciones no pueden ser debilitadas por un clase hija.
  2. Las invariantes establecidas por la clase padre deben ser mantenidas por las clases hijas.
  3. Las restricciones históricas dicen que no puede existir un método en la clase hija que vaya en contra de un comportamiento de su clase padre.

Lo decimos de otra manera: si cambiamos una clase por otra que es su hija o hereda de la misma, el comportamiento no debería variar.

Lo más obvio es si intentamos retornar desde un método de la clase hija un tipo de dato diferente al que devuelve ese mismo método en la clase padre.

Lo vas a ver mucho más claro en el código con las violaciones de los hitos está en 3-liskov-substitution.

Las vacas no vuelan. Principios SOLID

4. Principio de segregación de la interfaz

“Interface segregation principle” en inglés.

Una clase nunca debe ser forzada a implementar una interface que no usa, empleando métodos que no tiene por qué usar.

En el código seguimos con vacas y patos y la velocidad que pueden alcanzar. Las vacas no vuelan, así que la interface de la que dependen no debería tener un método que calcule la velocidad en el aire de una vaca.

Otro ejemplo claro es que si hay una clase GeometricCalculator no tiene sentido que un cuadrado y un cubo hereden de la misma si tiene un método que calcula el área y otra el volumen. Los cuadrados no tienen volumen.

El ejemplo con código está en 4-interface-segregation.

5. Principio de inversión de la dependencia

“Dependency inversion principle” en inglés.

Las entidades deben depender de abstracciones no de concreciones.

El módulo de más alto nivel no debería depender de lo que hay en el bajo nivel, lo correcto es que dependa de abstracciones.

Es tan evidente como el principio uno. Muy fácil de romper cuando acoplas en un método la lógica de negocio con las consultas a la base de datos de forma directa.

El código con la abstracción de la consulta está en 5-dependency-inversion.

Enlaces de referencia

Colofón

Este episodio ha sido un experimento, espero que te haya gustado. :)

Ya sabes que con tu apoyo a través de la suscripción de la Zona Premium haces todo esto más sostenible. Y además, aprendes un montón de cosas nuevas.

¡Hasta el próximo martes!

Escrito por:

Imagen de Daniel Primo

Daniel Primo

CEO en pantuflas de Web Reactiva. Programador y formador en tecnologías que cambian el mundo y a las personas. @delineas en twitter y canal @webreactiva en telegram

12 recursos para developers cada domingo en tu bandeja de entrada

Además de una skill práctica bien explicada, trucos para mejorar tu futuro profesional y una pizquita de humor útil para el resto de la semana. Gratis.