Principios SOLID
Tags: codeclean, javascript, refactor, interview
Published: 2021-12-07 22:09:20

## ¿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);
    }
}
```
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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8f1jf8fcn6m2ndqomiwj.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e8pi4nye2ntz4ml8w56o.png)

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{
    ...
  }
```

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ywzo2mzm8ci04io1n2q8.png)

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

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/trqcxcbm1ffiwqbkn3xl.png)

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


**D- Dependecy Inversion**

continuara...