Logotipo SOLID

Introducción

En el principio Dahl y Nygaard crearon la programación orientada a objetos. Y esta se encontraba desordenada y vacía, y las tinieblas estaban sobre la faz de la programación. Pero entonces Robert C. Martin, habló a los congregados y les dijo:

"Aquí tenéis los 5 mandamientos de la programación orientada a objetos. No son verdades absolutas y no siempre podrán vivir conjuntamente. Usadlos con mi beneplácito".

Ejem.... perdón, que quería realizar una idealización de nuestro pasado en la programación. Así que dejemos las introducciones grandilocuentes para comenzar a hablar de SOLID. ¿Qué es? ¿Con que fin nace?.

SOLID es un conjunto de prácticas propuestas por Robert C. Martin con el fin de evitar la problemática existente hasta el momento con las aplicaciones desarrolladas usando POO. De forma que fueran más sencillas de leer, mantener y testear. El acrónimo nace de la inicial de cada uno de los principios o prácticas:

Al buscar información por la red, muchas veces se encuentran datos muy difusos sobre estos principio, o artículos extremadamente largos que terminan dejando más dudas de las que despejan. La idea es esta nueva serie de de 5 artículos, es explicar cada principio de forma clara y práctica, de forma que podáis saber cuando, cómo y por qué aplicarlos.

(S) Principio de responsabilidad única

"Una clase debería tener una, y sólo una, razón para cambiar"

Robert C. Martin

Una clase debería ser responsable de una única cosa, o por ende, tener sólo una responsabilidad. Si hacemos que una clase se encargue de todo, cualquier cambio en la funcionalidad requerirá de modificaciones en dicha clase, e incluso en partes en las que no se debiera cambiar. Cabe destacar que estos principios, no quedan relegados a las clases, se puede aplicar a otros ámbitos.

Hay varias preguntas que podemos hacernos para detectar si estamos cumpliendo este principio:

  • ¿La clase es muy grande? Normalmente esto nos puede dar una pista de que está haciendo demasiadas cosas.
  • ¿Cualquier cambio en otras capas del código requieren cambios en la clase? Esto implica que la clase está llevando a cabo funciones de capas de la arquitectura que no debería ni saber que existen. Por ejemplo, que una clase con información de usuario tenga métodos de guardado de en base de datos. ¿Si cambia la base de datos o las consultas por qué deberías cambiar la clase usuario?
  • ¿Por qué tengo "grupos" de atributos en la clase que no parecen estar relacionados entre sí? Volviendo al ejemplo del punto anterior, ¿qué hace un atributo dbConnector en mi clase Usuario?
  • ¿Por qué tengo que configurar medio entorno para testear sólo esta clase? Con la excepción de que quisieras hacer un test de la clase que carga toda tu aplicación. En la famosa clase Usuario, no debería ser necesario configurar o mockear una gran cantidad de elementos para crear los tests unitarios.

Para ver un ejemplo, partamos de una clase TextDocument "mal escrita". Es decir, contendrá lo propio de un documento pero será también capaz de compartirlos:

Con la clase anterior tenemos un problema, y es que está teniendo dos responsabilidades, por un lado está permitiendo gestionar un documento, pero por otro se está encargando de compartir dicho documento. ¿Realmente es algo que el documento debe saber? Ya que no estamos hablando de cambiar las propiedades del documento, sino de como usarlo para otros fines. Lo que no debería ser responsabilidad de éste. Es más, esta parte quedaría muy acoplada a la forma de compartir, no es lo mismo enviar por mail, que compartir por Bluetooth. Por lo que volvemos a preguntarnos, ¿un documento debe saber que hay mail y Bluetooth en nuestro proyecto? La respuesta es bien sencilla, no debe saber nada del exterior o de lo que puedan hacer con él. Debe vivir en su mundo aislado cual hikikomori.

¿Cómo podemos solventar esto? Pues bien, la forma más sencilla es tener una clase que se encargue de la responsabilidad de compartir documentos, pero además, en lugar de poner sólo una clase vamos a poner un ejemplo más real de como podría quedar todo (no voy a poner todo lo necesario, porque si no al final este simple ejemplo quedaría más confuso 😉):

En la parte anterior estamos separando por funcionalidades lo que debe hacer cada clase. Esto previene que por ejemplo TextDocument, tenga que saber la forma en que puede compartirse, y que por otro lado las clases EmailSharer y BluetoothSharer tengan que saber cómo rellenar un documento.

Con esto tenemos algo fácilmente testeable y desacoplado por funcionalidades, lo que si a futuro seguimos algún patrón como DDD, nos ayudará a tener el código también más organizado.


En el siguiente artículo pasaremos a la letra O: Open/Closed Principle. Cualquier duda, comentario o corrección podéis dejarla en comentarios; y si para ti hay mucho texto, puedes ver el resumen en este post de Instagram.

Más artículos de esta serie:
Capítulo O: Open/Closed Principle
Capítulo L: Liskov Substitution Principle
Capítulo I: Interface-Segregation Principle
Capítulo D: Dependency Inversion Principle

Comparte este artículo con quien quieras
3 formas extra de definir constantes con TypeScript
Principios SOLID. Capítulo O: Open/Closed Principle

Leave a Comment

Your email address will not be published. Required fields are marked *

El tiempo límite ha expirado. Por favor, recarga el CAPTCHA.