Skip to content

Instantly share code, notes, and snippets.

@luc0
Last active January 6, 2025 19:44
Show Gist options
  • Select an option

  • Save luc0/0374bb499996f13236b8bda629f187a1 to your computer and use it in GitHub Desktop.

Select an option

Save luc0/0374bb499996f13236b8bda629f187a1 to your computer and use it in GitHub Desktop.
DDD and Clean

https://www.youtube.com/watch?v=DBJYKWD-xBA

Que es? Para que?

Muchos problemas que surgen a los 2 o 3 años, son que vas a tener problemas a la hora de querer intercambiar implementaciones. El codigo va a estar muy acoplado a la infraestructura. Aunque es un "symbol of success" que tu empresa logro vivir todo este tiempo. Invertimos la dependencias, no dependemos de como le hablamos a la DB/mail, sino que vamos a depender de abstracciones que dicen que quiero hacer, el como no nos importa. Entonces nos desacoplamos.

Para que sirve?

  • En general se dice que no sirve porque: cuando vas a cambiar la DB en prod? y es cierto, pero es solo una parte:
    • En los distintos environments para distinta gente: Dev / STG / QA, va a ser mas facil intercambiar por otro filesystem o mailserver o database. Al tener el sistema modularizado es facil.
    • Para unit test tambien sirve, por ej. tenes un checkout method en un ecommerce. Guardas la order, procesas la tarjeta, envias un email, si haces todo eso en 1 metodo todo muy acoplado, buena suerte haciendo Unit Testing, como mucho podrias hacer una integration testing pero necesitas toda la infraestructura. En cambio si tenes abtracciones, ej dependenes de interfaces, no hace falta usar la implementacion de pago verdadera, podes mockearla.

Inversión de Dependencias en Clean Architecture:

Fuente: Clean architecture. Cap 22. pagina 203.

Los circulos concentricos tienen que ver con detalles de implementacion de cada capa. Las interfaces estan en el circulo mas interno.

  1. Los módulos de alto nivel (capas internas) nunca deben depender de módulos de bajo nivel (capas externas). (Ej, entidades, no deben depender de implementaciones service/repo) Deben depender de interfaces que estan definidas en la capa interna.

  2. Los modulos de bajo nivel (Las capas externas: controllers, repositories) pueden depender de modulos de alto nivel (las internas), pero siempre a través de interfaces para lograr flexibilidad, testabilidad y desacoplamiento. Ej. una implementacion de repositorio puede depender de detalles internos, como una entidad. (pero idealmente a través de una abstraccion)

Excepciones (para sistemas pequeños): Las implementaciones concretas de esas interfaces pueden depender de detalles internos (como entidades) si las entidades son estables, pero lo ideal es depender de abstracciones para mantener un diseño limpio y escalable.

image

Beneficios Inversion dependencias:

  • Cambios externos, solo afectan a lo externo: Un cambio o nueva implementación en la capa externa, evita que cambios en la interna sean necesarios. Ya que usara un contrato (idealmente agnostico a detalles internos) por lo que no esta acoplado a lo interno, y no hace falta modificar capas internas. Ej. si una implementacion de Repository esta acoplado a recibir una Entidad por params, y en realidad necesito un DTO, para poder hacer testing usando mockups.

  • Conocimiento de scope de refactorizacion: Sin esta inversion de dependencias, si modifico los detalles de implementacion puedo estar rompiendo quien la use y no saberlo. Si uso un contrato, me voy a dar cuenta que voy a tener que modificarlo, por lo tanto ENTIENDO el scope de la refactorizacion, voy a entender que es un cambio de la capa interna que afecta a la externa.

Fuentes:

https://www.youtube.com/watch?v=eNFAJbWCSww

https://www.youtube.com/watch?v=bDWApqAUjEI

Arquitectura Hexagonal (puertos & adaptores: interfaces e implementaciones)

image

Sirve para desacoplar lógica de (por ej) la APP y la DB.

Infra: DB, Cache, Redis, entrada y salida

App: Casos de uso -> crear user, login, logout

Domain: Lógica de negocio

In/Out:

  • Por cada input y output se crea un puerto. El puerto es una abstracción para comunicarse con el exterior sin conocer como se implementa.
  • El puerto (interfaz) luego tiene un adapter (implementación), es donde esta la lógica principal para escribir en la DB o donde sea. Convierte el output de nuestra app por algo que pueda usar la fuente externa.
image image

Dependencia

Infra conoce detalles de App + Domain

App conoce detalles de Domain.

Domain conoce solo de si mismo.


Vertical Slicing (opcional)

image

Es una forma de organizar carpetas.

Seria agregar infra / app / domain, dentro de cada modulo.

image

Parte 2:

Fuente: https://www.youtube.com/watch?v=f7Su4KoqSio

Resumen: https://youtu.be/f7Su4KoqSio?si=_oWICWS5Gz-qGMOK&t=3209

Uso de Inversión de dependencias

image

En la primera el servicio depende del repositorio, porque si quiero cambiar algo de la implementacion del repo (entrada o salida de data), puedo romper el servicio.

En cambio en el segundo caso el repositorio tiene que cumplir un contrato

Use Cases

Al servicio se lo puede partir en archivos de Use Cases por ej: un service con metodos para crear libros y borrar, separarlo en: CreateBookUseCase.ts y RemoveBookUseCase.ts c/u con un solo metodo execute()

(ver mas)

DTOs

Se suelen usar DTOs de entrada (ej. GetEventDTO) y de salida/response (ej. EventDTO). Cada uno implementando una interface. Si se quiere agrar estructura a la respuesta, se puede hacer en el controller

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment