DEV Community

Cover image for Principios SOLID
Ariel Calix
Ariel Calix

Posted on

Principios SOLID

¿Qué son los principios SOLID?

Cuando hablamos de SOLID, hablamos de un conjunto de buenas prácticas de desarrollo, también podemos decir que son los principios de la programación orientada a objetos, estos principios tienen una estrecha relación con los patrones de programación.

¿Qué aportan a nuestros código?

Los principios SOLID nos ayudan a tener un mejor tiempo durante la compilacion, alta coherencia de nuestro código y una fuerte encapsulación del mismo. Estos principios tienen en esencia la finalidad de escribir código de mayor calidad, facilitar el mantenimiento, permitir la reutilizacion y la escalabilidad del código.

SOLID es un acrónimo introducido por el Sr. Michael Feathers, tomando como base los 5 principios propuestos por Robert C. Martin en el año 2000.

Cada letra del acrónimo es la referencia a un principio de modo que:

  • S (SRP) – Principio de responsabilidad única (Single responsibility principle)
  • O (OCP) – Principio de abierto/cerrado (Open/closed principle)
  • L (LSP) – Principio de sustitución de Liskov (Liskov substitution principle)
  • I (ISP) – Principio de segregación de la interfaz (Interface segregation principle)
  • D (DIP) – Principio de inversión de la dependencia (Dependency inversion principle)

1. Principio de Responsabilidad Única

“Nunca debería haber mas de una razón en una clase para cambiar”

Con este principio buscamos que un objeto/clase tenga únicamente una responsabilidad y que se encuentre completamente encapsulada por la clase. Cuando hablamos de responsabilidad, hacemos referencia a una razón para cambiar. Este principio dirige nuestro desarrollo hacia una coherencia más fuerte en la clase y un encaje más flojo entre la dependencia de clases, una mayor lectura, más eficiente y un código con menos complejo. Por ejm:

   Clase Rectangulo {
      area();
      dibujar();
   }

   Clase CalcularGeometria : Rectangulo {
      area calcularArea();
      dibujar dibujarArea();
   }

   Function dibujar(){
      return dibujarArea();
   }
Enter fullscreen mode Exit fullscreen mode

En este ejemplo se muestra la clase rectángulo con dos métodos, area() y dibujar(), Como puedes observar la clase Rectángulo.area() se encargaría de retornar el valor del área para ser dibujada por Rectángulo.dibujar().
Con esta forma de diseñar una clase, si en un futuro realizáramos una modificación a la clase dibujar, para extender su funcionalidad a otra clase llamada Triangulo. Estaríamos forzados a tener que probar de nuevo la clase Rectángulo para asegurarnos que su funcionalidad no fue alterada. Lo que el SRP propone es lo siguiente:

   Clase Dibujar {
      dibujar();
   }

   Clase Rectangulo : Dibujar {
      area();
      dibujar dibujarRectangulo();
   }

   Clase CalcularGeometria {
      return calcularArea();
   }

   Function dibujarVista(){
      return dibujarRectangulo();
   }
Enter fullscreen mode Exit fullscreen mode

Ahora si observas, se crea una nueva clase llamada dibujarVista que contiene un solo método llamado dibujarRectangulo().
Es fácil comprender que las clases son generales, y que cualquier llamado a estas no significa tener que modificarla, y si quisiéramos extender su funcionalidad lo podríamos hacer fácilmente.

Este principio probablemente sea el más importante de todos, al mismo tiempo es el más sencillo y a su vez el más complicado de llevar a cabo.

2. Principio Abierto-Cerrado

“Las entidades de Software (clases, módulos, funciones, etc.) han de estar abiertas para tener extensiones, pero cerradas para modificaciones”

Este principio busca que una entidad nos permita que su comportamiento se pueda extender en cuanto a funcionalidad, pero nunca modificarse el código existente. Cualquier clase (o cualquier cosa que codifiques) debe estar escrito de un manera que pueda ser utilizada por lo que es, y que pueda entender de ser necesario. Pero nunca se deben realizar cambios modificando el código ya existente.

3. Principio de sustitución de Liskov

“Los subtipos deben ser sustituidos por su tipo de base”

Lo que este principio definido por Barbara Liskov sugiere es que los objetos deberían ser reemplazados por ejemplos de su subtipo, y ello sin que la funcionalidad del sistema desde el punto de vista de los clientes se vea afectada. En esencia en lugar de utilizar la implementación actual, deberías ser capaz de inplementar una clase base y obtener el resultado deseado. Frecuentemente, cuando queremos representar un objeto, diseñamos la clase base en sus propiedades y en lugar de eso deberíamos poner énfasis en su comportamiento.

Muchos desarrolladores dicen que este principio de Liskov tiene una estrecha relación con el principio anterior (open-close).

“una violación de LSP es una violación latente de OCP”.

4. Principio de segregación de la interfaz

“Las clases que implementan interfaces, no deberían ser forzadas a implementar los métodos que no serán utilizados.”

Este principio expone cómo escribir interfaces. si la interfaz se convierte en un largo archivo de código, será necesario particionarla en pequeñas partes específicas. Una interfaz será definida por el cliente que lo utilice, lo que significa que es el único que tenga conocimientos de todos los métodos relacionados entre ellos.

En realidad, si al añadir métodos que no deberían estar ahí, las clases que implementan la interfaz deberán implementar tambien los métodos que no utilice. Los clientes no deberían ser forzados a depender de las interfaces que usarán. ISP intenta mantener un sistema desacoplado, más fácil de refactorizar, cambiar y desplegar.

5. Principio de inversión de la dependencia

“Los módulos de altos modelos no deberían depender de niveles de módulos bajos, sino de abstracciones. Abstracciones no deberían depender de detalles; sino los detalles de la abstracción”

Este principio en esencia consiste en la reducción de dependencias entre los diferentes módulos de nuestro código, esto nos sera de ayuda para entender cómo vincular correctamente sistemas juntos.

Cuando los detalles de implementación dependen de altos niveles de abstracció, este prinicipio nos ayudara a conseguir un sistema bien acoplado. También, influirá en la encapsulación y en coherencia del sistema.

Supongamos que un módulo concreto A, no debe depender directamente de otro módulo concreto B, sino de una abstracción de modulo _B. Tal abstracción se convierte en una interfaz o una clase (que podría ser abstracta) y que sirve como base para un conjunto de
clases hijas.

Al inicio de la vida como desarrollador, aplicar estos principios puede resultar un poco complejo, pero con el tiempo y la práctica se llega a un dominio de ellos mejor.

Foto por Fotis Fotopoulos en Unsplash

Latest comments (0)