¿Has oído hablar de los principios SOLID? Si eres experto o te interesa el diseño y la programación de software, este artículo es para ti. SOLID es un acrónimo que contiene 5 principios importantes al hacer OOP (Programación Orientada a Objetos).

En su documento de 2000 Principios de diseño y patrones de diseño, Robert C. Martin (tío Bob), introdujo estos 5 principios; sin embargo, no fue sino más tarde cuando Michael Feathers identificó el acrónimo SÓLIDO. Hacer que los diseños de software sean más comprensibles, más fáciles de mantener y más fáciles de extender es el principal propósito de estos 5 principios.

Aun si eres un gran experto en el área, es necesario que comprendas la base del significado del acrónimo. En este artículo verás ejemplos y detalles necesarios que te ayudarán a corregir las violaciones y a desarrollar software de excelente calidad.

Principios SOLID

Principios SOLID no es más que un acrónimo que hace mención a los cinco principios de diseño que se encuentran orientados a objetos (OOD). Cuando estos principios se combinan se facilita el trabajo de programación para el desarrollo de software de calidad.

Si se necesita refactorizar fácilmente el código y el desarrollo de software ágil o adaptativos, los principios SOLID se encargan de facilitar a los programadores o desarrolladores el trabajo, así como evitar y corregir errores de código. Los acrónimos cuando se expanden pueden parecer complicados, sin embargo, son bastante fáciles de entender. Veamos.

S – Principio de responsabilidad única

Robert C. Martin define una responsabilidad como una ‘razón para cambiar’, y concluye que una clase o módulo debe tener una, y solo una, razón para cambiar. Veamos cómo escribir un fragmento de código que viole este principio.

En el ejemplo se aprecia que el método CreatePost() tiene demasiada responsabilidad, dado que puedes crear una nueva publicación, registrar un error en la base de datos y registrar un error en un archivo local. El principio de responsabilidad única se viola. Al corregirlo:

Al abstraer la funcionalidad que maneja el registro de errores, ya no se viola el principio de responsabilidad única.

Ahora hay dos clases y cada una tiene una responsabilidad; para crear una publicación y registrar un error, respectivamente.

O – Principio abierto/cerrado

Este principio establece que las entidades de software (clases, módulos, funciones, etc.) deben estar cerradas para modificación pero abiertas para extensiones. Puedes asegurar que tu código cumpla con el principio abierto/cerrado mediante el uso de la herencia y/o la implementación de interfaces que permitan que las clases se sustituyan polimórficamente entre sí. Observa un ejemplo que dejará muy claro lo que se quiere decir.

En este fragmento de código, se debe hacer algo específico cada vez que una publicación comienza con el carácter ‘#’. Sin embargo, la implementación anterior viola el principio abierto/cerrado en la forma en que este código difiere el comportamiento en la letra inicial.

Si luego quisieras incluir también menciones que comiencen con ‘@’, tendrías que modificar la clase con un ‘else if’ adicional en el método CreatePost(). Observa cómo hacer que este código cumpla con el principio abierto/cerrado simplemente usando la herencia.

Al usar la herencia, ahora es mucho más fácil crear un comportamiento extendido para el objeto de sobrescribir el método CreatePost(). La evaluación del primer carácter ‘#’ ahora se manejará en otro lugar (probablemente en un nivel superior), y lo bueno es que si quieres cambiar la forma en que se evalúa un postMessage, puedes cambiar el código allí, sin afectar ninguno de estos comportamientos subyacentes.

L – Principio de sustitución de Liskov

Este es probablemente el principio más difícil de entender cuando se presenta por primera vez. En términos más generales, en un programa los objetos deben ser reemplazables con instancias de sus subtipos sin alterar la corrección de ese programa. Echa un vistazo a un ejemplo de cómo violar este principio.

Observa cómo la llamada de CreatePost() en el caso de un subtipo MentionPost no hará lo que se supone que debe hacer; notificar al usuario y sobrescribir la mención existente. Dado que el método CreatePost() no se sobrescribe en MentionPost, la llamada CreatePost() simplemente se delegará hacia arriba en la jerarquía de la clase y se llamará CreatePost() desde su clase principal.

Echa un vistazo a la corrección:

Al refactorizar la clase MentionPost de tal manera que se sobrescriba el método CreatePost() en lugar de llamarlo en su clase base, ya no violamos el principio de sustitución de Liskov.

I – Principio de segregación de interfaz

Si estás acostumbrado a usar interfaces, es probable que ya estés aplicando este principio. El principio de segregación de interfaz establece que ningún cliente debería verse obligado a depender de métodos que no utiliza. Ejemplo:

En este ejemplo, supón que primero tienes una IPostinterfaz con la firma de un método CreatePost(). Más tarde, modificas esta interfaz agregando un nuevo método ReadPost(), por lo que se vuelve como la IPostNewinterfaz. El principio de segregación de interface aquí es donde se viola. Para corregir simplemente crea una nueva interfaz.

En líneas generales, si alguna clase pudiera necesitar tanto el método CreatePost() como el método ReadPost(), podrás implementar ambas interfaces.

D – Principio de inversión de dependencia

Finalmente, D, el último de los 5 principios. Este principio establece, por un lado, que tanto los módulos de alto como de bajo nivel dependen de abstracciones; así pues, los módulos de alto nivel no deberían depender de los módulos de bajo nivel.

Por otro lado, las abstracciones no dependen de los detalles, sino que, al igual que los módulos de alto y bajo nivel, los detalles también deberían depender de las abstracciones. Para cumplir con este principio necesitas usar un patrón de diseño conocido como patrón de inversión de dependencia, que generalmente se resuelve mediante el uso de inyección de dependencia. Por ejemplo:

Observa cómo se creó la ErrorLogger instancia desde dentro de la Post clase. Esta situación viola el principio de inversión de dependencia. Si quisieras usar un tipo diferente de registrador, tendrías que modificar la clase Post. Se puede arreglar esto usando la inyección de dependencia.

Al usar la inyección de dependencia ya no se debe confiar en la Postclase para definir el tipo específico de registrador. En este principio, como se ha dicho anteriormente, las entidades no dependen de concreciones sino de abstracciones.

Conclusión

Al aplicar estos 5 principios que hacen el acrónimo SOLID, te puedes beneficiar de una base de código reutilizable, mantenible, escalable y fácil de probar. Estos son 5 principios esenciales utilizados por ingenieros de software profesionales en todo el mundo, y si eres serio sobre la creación de software ‘sólido’, ¡debes comenzar a aplicar estos principios hoy!

¿Qué te pareció el artículo? Si tiene alguna pregunta o comentario, no dude en comentar a continuación.
Ah, y si te ha gustado no te olvides de compartirla 😄