DEV Community

Pablo Agustín Canale
Pablo Agustín Canale

Posted on • Updated on

Principios SOLID

¿QUE ES SOLID?

Es un acronónimo acuñado por Robert C.Martin (el tío Bob :D ), el escritor del Code Clean, representa los 5 principios basicos de la programación orientada a objetos.

S- Single Responsability: Resposabilidad simple

Un componente o clase debe tener una responsabilidad única, sencilla y concreta. Dando simplicidad al código.

Un ejemplo se observa cuando trabajamos con controladores y servicios en un MVC, por ejemplo:

export class AccountStatusController {
Si qui
  constructor(private accountStatusService: AccountStatusService) { }

  @Post() 
  create(@Body() accountStatus: AccountStatus): 
    Promise<AccountStatus> {
    return   
       this.accountStatusService.createStatus(accountStatus);
    }
}
Enter fullscreen mode Exit fullscreen mode

El controlador solo se encarga de la redirección de información (manejo de responses y requests), y los servicios de la lógica de negocio. En el controlador no se conocen detalles de la implementación de las funciones del servicio, de como realiza las consultas.

O- Open/Close:

Las entidades de software deben ser abiertas para la herencia pero cerradas a las modificaciones.

Significa que ante peticiones de cambio en nuestro programá, debemos ser capaces de añadir funcionalidad sin alterar el codigo ya existente o al menos intentar tocarlo lo menos posible.

Los problemas con el principio Open/close se suelen solucionar utilizando polimorfismo, es decir con la utilización de clases abstractas o interfaces.

Supongamos que tenemos un servicio de notificaciones, que se encarga de mandar notificaciones dependiendo del tipo que le sea espeficicado por parámetro, esto rompe con el principio open/close porque sí el dia de mañana quiero agregarle otro tipo de envio, debo modificar el codigo ya existente.

Image description

Una forma de refactorizar es la siguiente, abstraemos en una clase abstracta o interface INotifications y la implementamos en las siguientes dos clases

Image description

De esta forma, el servicio de notificación podría usar un array de notificaciones y las implementación del método notify() dependenderia especificamente de cada clase concreta. Ahora sí quisieramos agregar otro tipo de servicio de notificación solo deberiamos crear una clase nueva e implementar la interface, no tocariamos para nada el codigo ya existente.

**

L-

Liskov Substitution Principle (LSP)**

Si tienes una clase padre la cual hereda a una clase hija, no debe la hija alterar el funcionamiento del padre.

Esto quiere decir que si en un programa usamos cierta clase, deberíamos poder usar cualquiera de sus subclases sin interferir en la funcionalidad del programa.

Para resaltar, es un principio que intenta dar buenas prácticas a la implementación de la herencia. Veamos un codigo donde no se cumple este principio:

class Persona {  

    constructor(nombres, dni, tarjeta){
      this.nombres = nombres
      this.dni = dni
      this.tarjeta = tarjeta
    }  

    getNombres() {
      return this.nombres;
    }
    setNombres(nombres) {
      this.nombres = nombres;
    }
    getDni() {
      return this.dni;
    }
    setDni(dni) {
      this.dni = dni;
    }
    getDni() {
        return this.dni;
      }
    setDni(tarjeta) {
        this.tarjeta = tarjeta;
    }
    Pagar() {
      return (console.log('Se realiza un pago'))
    }
  }

  class Niño  extends Persona{
    ...
  }
Enter fullscreen mode Exit fullscreen mode

La clase persona esta bien definida individualmente, pero si intentamos hacer una clase derivada Niño que extienda de persona nos encontrariamos con PROBLEMAS! Un niño no podría tener una tarjeta y menos aun realizar pagos!

Si cuando sobreescribimos un método en la clase que hereda necesitamos lanzar una excepción o no realizar nada, entonces probablemente estamos violando el LSP.

I- Interface Segregation

Una clases nunca debería depender de métodos que no usa, es decir que cuando hagamos interfaces que modalan comportamientos, deberiamos asegurarnos que las funciones que tenga esa interfaz van a ser relavantes para cualquier clase que las implemente. Si esto no pasa, podriamos dividir la interface en varias más pequeñas.

Digamos que estamos implementando un zoológico y queremos crear una interfaz que sirva para todas las aves, la InterfazPajaro podria tener los métodos comer y volar para implementar en las clases gabiotas, flamenco y gorriones. Pero luego queremos agregar pingüinos (no vuelvan pero nadan) y aveztruces (corren)

Image description

La mejor forma de resolver esto es justamente ulilizando el principio de segregación de interfaces de la siguiente manera

Image description

De esta forma cada pájaro solo implementara las interfaces que necesita.

D- Dependecy Inversion

continuara...

Top comments (0)