SOLID Principles: las cinco reglas de oro de la OOP

Los principios SOLID son cinco prácticas y directrices para un código limpio, fácil de mantener y flexible en la programación basada en objetos. La aplicación y el cumplimiento de estos principios facilitan la comprensión del diseño de software durante largos periodos de desarrollo. De este modo, no solo se puede escribir mejor código, sino que también se puede mantener mejor el existente.

¿Qué son los principios SOLID?

Un buen código fuente comienza con reglas, paradigmas de programación y un estilo de programación adecuado para conseguir un código eficiente y limpio. Esto es exactamente lo que garantizan los cinco principios SOLID, acuñados por Robert C. Martin, Bertrand Meyer y Barbara Liskov. Siguiendo ciertos principios en la programación orientada a objetos (OOP) con lenguajes como Python o Java no solo escribirás mejor el código, sino que también conseguirás un mantenimiento más eficiente del mismo, un diseño de software sostenible y flexible, y una mayor seguridad a largo plazo.

SOLID hace referencia, por un lado, a la base sólida de desarrollo para todos aquellos que quieran aprender a programar. Por otro lado, al acrónimo se compone de las primeras letras de los cinco principios (por Michael Feathers):

  • Single Responsibility Principle: un objeto debe tener una sola razón para cambiar, es decir, una sola responsabilidad.
  • Open Closed Principle: las clases deben estar abiertas para su extensión, pero cerradas para su modificación.
  • Liskov Substitution Principle: las subclases deben ser sustituibles por sus clases base sin afectar al comportamiento del programa.
  • Interface Segregation Principle: los clientes no deben verse obligados a depender de interfaces que no utilizan.
  • Dependency Inversion Principle: los módulos de alto nivel no deben depender de módulos de bajo nivel, sino de abstracciones. Las abstracciones no deben depender de detalles, sino que los detalles deben depender de abstracciones.

¿Qué ventajas ofrecen los principios SOLID?

Sin reglas aparece el caos, afirmación que se hace evidente al programar. Incluso errores, imprecisiones y omisiones pequeños pueden volver “inutilizable” a largo plazo el código fuente. No se necesita mucho para esto: basta con clases complejas que dificultan la implementación, o subclases que carecen de ciertas propiedades de sus superclases. Los principios SOLID garantizan que se necesite la menor cantidad posible de reparación de código a través de la refactorización.

Las ventajas de aplicar los principios SOLID incluyen:

  • Claridad, limpieza y belleza: el software y los códigos son más fáciles de entender, más comprensibles, más eficaces y, en definitiva, más agradables a la vista.
  • Facilidad de mantenimiento: la estructura clara y despejada facilita el mantenimiento tanto del código nuevo como del que ha ido creciendo con el tiempo, incluso si hay múltiples partes interesadas.
  • Personalizable, ampliable y reutilizable: una mejor legibilidad, la reducción de complejidades y responsabilidades y la disminución de las dependencias de clases hacen que el código sea más fácil de editar, personalizar, ampliar mediante interfaces y reutilizar con flexibilidad.
  • Menos propenso a errores: un código limpio con una estructura sencilla ayuda a que los cambios en una parte no afecten indirectamente a otras áreas o funciones.
  • Más seguro y fiable: con menos o ninguna vulnerabilidad, incompatibilidad o error, la funcionalidad y fiabilidad de los sistemas mejora, al igual que la seguridad.

Los principios SOLID de un vistazo

Los principios SOLID se encuentran entre las reglas de oro de la buena programación y, por tanto, deberían resultar familiares a cualquiera que se dedique a la programación basada en objetos. Te presentamos los cinco principios en detalle.

SRP: Single Responsibility Principle (Principio de Responsabilidad Única)

La definición original según Robert C. Martin en “Agile Software Development: Principles, Patterns and Practices” establece:

Cita

“Nunca debe haber más de una razón para cambiar una clase”

El SRP establece que solo debe aplicarse una responsabilidad a cada clase del OOP. Por lo tanto, solo debe haber un motivo para realizar cambios en la clase. Al contrario de lo que se suele entender, esto no significa que una clase o módulo solo pueda tener una tarea. Sin embargo, debería asumir la responsabilidad solo de tareas específicas que idealmente no se superpongan con otras áreas.

La superposición de responsabilidades, como proporcionar funciones para diferentes áreas comerciales, puede tener un impacto en la funcionalidad de la clase cuando se realizan cambios en una de esas áreas. Tener más de una responsabilidad y demasiadas dependencias puede resultar en que un cambio en un área provoque varios cambios adicionales o errores en el código.

Por lo tanto, el SRP tiene como objetivo desarrollar módulos coherentes responsables de una tarea claramente comprensible o de objetos claramente definidos. La estructura claramente definida con dependencias reducidas e implementaciones desacopladas permite realizar cambios y modularizaciones posteriores de manera más fácil, rápida y sin complicaciones.

Nota

Las clases, también conocidas como tipos de objetos, son el elemento central en la programación orientada a objetos (OOP). Pueden entenderse como un plano con atributos para construir objetos reales similares en objetos de software. Por ello, las clases, también conocidas como módulos, a menudo se comparan con tipos de archivos.

OCP: Open Closed Principle (Principio de Apertura y Cierre)

Bertrand Meyer y Robert C. Martin, en “Object Oriented Software Construction”, afirman lo siguiente sobre el OCP:

Cita

“Las entidades de software (clases, módulos, funciones, etc.) deben estar tanto abiertas para ampliaciones como cerradas para modificaciones”

El OCP garantiza que no haya que reescribir el software en su núcleo para aplicar cambios. Si se requieren modulaciones profundas del código, existe el riesgo de que se produzcan errores sutiles y hediondez del código. Un código bien estructurado debe poder dotarse de interfaces a través de las cuales pueda ampliarse con funciones adicionales. Aquí, la palabra clave es la herencia de clases.

Las nuevas características y extensiones con funciones y métodos claramente nuevos que deban implementarse pueden acoplarse simplemente a una superclase en forma de subclases a través de una interfaz. De este modo, no es necesario “retocar” el código escrito y estable. Esto simplifica el mantenimiento y la conservación de los programas y hace que la reutilización de elementos de código estables sea mucho más eficiente gracias a las interfaces.

LSP: Liskov Substitution Principle (Principio de Sustitución de Liskov)

Barbara H. Liskov y Jeannette M. Wing, en “Behavioral Subtyping Using Invariants and Constraints”, dicen sobre el LSP:

Cita

“Si q (x) es una propiedad del objeto x del tipo T, entonces q (y) debe cumplirse para todos los objetos del tipo S, donde S es un subtipo de T”.

Lo que suena críptico a primera vista es fácil de entender: las subclases enlazadas o extendidas deben funcionar como sus superclases o clases base. Esto significa que cada subclase debe conservar las propiedades de su respectiva superclase por medio de la herencia y que estas propiedades no deben modificarse en la subclase. En principio, deben ser reemplazables. Las superclases, en cambio, pueden modificarse mediante cambios.

El clásico ejemplo del rectángulo y el cuadrado de Robert C. Martin sirve para explicarlo. En las clases de geometría se reconoce que todo cuadrado es un rectángulo, pero no todo rectángulo es un cuadrado. Más bien, un cuadrado comparte la propiedad “lados en ángulo recto” con la superclase de los rectángulos, pero tiene la propiedad adicional “lados de igual longitud”.

En programación es diferente. En este caso, la suposición de que clases similares o aparentemente idénticas se relacionan entre sí o dependen unas de otras conduce a errores, malentendidos y código poco claro. Por eso, en programación, la clase “rectángulo” no es un cuadrado y la clase “cuadrado” no es un rectángulo. Ambas están “desacopladas” e implementadas por separado. Sin una conexión integrada entre las clases, un malentendido no puede dar lugar a errores entre clases. Esto aumenta la seguridad y la estabilidad a la hora de sustituir implementaciones en subclases o superclases sin repercusiones.

ISP: Interface Segregation Principle (Principio de Segregación de Interfaces)

En “The Interface Segregation Principle”, Robert C. Martin define el ISP de la siguiente manera:

Cita

“Los clientes no deben verse obligados a depender de interfaces que no utilizan”

El ISP establece que no se debe obligar a los usuarios a utilizar interfaces que no necesitan. En otras palabras: para proporcionar a los clientes las funciones de determinadas clases, se adaptan nuevas interfaces más pequeñas a requisitos específicos. Así se evita que las interfaces se hagan demasiado grandes y se crean fuertes dependencias entre clases. La ventaja: un software con clases desacopladas y varias interfaces pequeñas adaptadas a requisitos específicos es más fácil de mantener.

DIP: Dependency Inversion Principle (Principio de Inversión de la Dependencia)

Según Robert C. Martin en “The Dependency Inversion Principle”, el quinto y último elemento de los principios SOLID es el siguiente:

Cita

“A. Los módulos de alto nivel no deben depender de los de bajo nivel. Ambos deben depender de abstracciones. B. Las abstracciones no deben depender de los detalles. Los detalles deben depender de las abstracciones”.

El DIP garantiza que las funciones y dependencias concretas en los niveles de código fuente se basen en interfaces abstractas y no entre sí. Para explicarlo: las arquitecturas de software pueden dividirse a grandes rasgos en niveles de usuario superiores y niveles abstractos inferiores o más profundos. Lógicamente, cabe suponer que la base abstracta determina el comportamiento de los niveles superiores. Sin embargo, el DIP considera que esto es propenso a errores, ya que los niveles superiores dependen de los niveles inferiores.

En lugar de vincular los niveles superiores con los inferiores, las clases de los niveles altos y bajos deben depender de interfaces abstractas intermedias. Las interfaces recuperan de los niveles inferiores las funcionalidades necesarias en los niveles superiores y las ponen a su disposición. De esta forma, se evita una “jerarquía de abajo arriba” de dependencias, que puede dar lugar a errores en el código con el paso del tiempo. Esto facilita la reutilización de los módulos y permite introducir cambios en las clases inferiores sin afectar a los niveles superiores.

Web Hosting
El hosting como nunca lo habías visto
  • Rápido, seguro, flexible y escalable
  • Seguro con SSL y protección DDoS
  • Dominio y asesor personal incluidos

¿Qué ocurre en caso de incumplimientos de los principios SOLID?

Un código bonito y fácil de leer que facilite al máximo el mantenimiento debería ser el objetivo de todo desarrollo de software. Sin embargo, si se olvidan directrices como los principios SOLID, el código envejece muy mal debido a vulnerabilidades, redundancias, errores acumulados y demasiadas dependencias. En el peor de los casos, el código se vuelve inutilizable con el tiempo. Este es un problema importante en el desarrollo ágil de software, ya que suele haber muchas personas trabajando en código complejo.

Las consecuencias de un código descuidado o mantenimiento deficiente incluyen:

  • Code Smell: las debilidades heredadas de un código poco limpio, conocidas como code smell o “hediondez del código”, pueden provocar fallos de funcionamiento y programas incompatibles.
  • Code Rot: si no se realiza el mantenimiento o la reparación mediante refactorización o una costosa revisión de código, el código puede “podrirse” metafóricamente y perder completamente su funcionalidad. Otra denominación para un código ilegible y confuso es la de “código espagueti”.
  • Vulnerabilidades de seguridad: además de los fallos, el mantenimiento complicado o las incompatibilidades, también hay riesgos de seguridad, que pueden dar al malware la oportunidad de explotar vulnerabilidades o ataques de día cero.

¿Quién desarrolló los principios SOLID?

El origen de los principios SOLID se encuentra en varios principios que introdujo por primera vez Robert C. Martin (“Uncle Bob”), uno de los iniciadores de la programación ágil, en su ensayo “Design Principles and Design Patterns” en 2000. El grupo de cinco principios SOLID fue acuñado por Robert C. Martin, Bertrand Meyer y Barbara Liskov. El pegadizo acrónimo formado por las cinco letras iniciales de los principios fue propagado a su vez por Michael Feathers reordenando cinco de los principios esenciales.

¿Qué principios de programación similares existen?

En el desarrollo de software, los principios representan directrices y recomendaciones de actuación generales o muy específicas similares a los principios SOLID, que ofrecen un conjunto de principios para el paradigma de la programación orientada a objetos. Otros principios de programación para código limpio incluyen:

  • Principio DRY (Don’t repeat yourself) para funciones con una única y exclusiva representación.
  • Principio KISS (Keep it simple, stupid) para un código lo más sencillo posible.
¿Le ha resultado útil este artículo?
Utilizamos cookies propias y de terceros para mejorar nuestros servicios y mostrarle publicidad relacionada con sus preferencias mediante el análisis de sus hábitos de navegación. Si continua navegando, consideramos que acepta su uso. Puede obtener más información, o bien conocer cómo cambiar la configuración de su navegador en nuestra. Política de Cookies.
Page top