Dando continuidad a la publicación anterior sobre la "Arquitectura Limpia (Capa de Dominio)", es el momento propicio para explorar a fondo lo que conlleva la capa de aplicación en este contexto arquitectónico.
¿Qué implica la capa de aplicación?
La Capa de Aplicación puede considerarse como el epicentro del proyecto. Tal como sugiere su nombre, es en este estrato donde se desarrolla la aplicación en su forma tangible, dando vida a la lógica previamente definida en la capa de dominio. En otras palabras, es el espacio donde se materializan los casos de uso que, en última instancia, definen el comportamiento de la aplicación.
Esta capa me he centrado en los siguientes aspectos cruciales, que incluyen:
Comandos y sus Validadores: Aquí, los comandos representan los datos que requiere el dominio. Los validadores desempeñan un papel fundamental al verificar que los parámetros proporcionados a estos comandos sean correctos y cumplan con las reglas definidas en la lógica del dominio.
Casos de Uso: La presente capa es el lugar donde se implementa de manera concreta la lógica central de la aplicación. Estos casos de uso describen escenarios específicos en los que se utiliza la funcionalidad principal de la aplicación para lograr objetivos específicos.
Persistencia: Aunque en esta etapa la aplicación aún no se conecta directamente a una base de datos u otros sistemas de persistencia, aquí he definido las clases abstractas e interfaces que la futura capa de infraestructura utilizará para gestionar la persistencia de datos. Esto asegura una transición fluida hacia la capa de infraestructura cuando sea necesario.
Puedes encontrar el repositorio de la capa de aplicación en el siguiente enlace, donde he logrado una cobertura del 99% en pruebas unitarias:
https://github.com/ProfeJulianLasso/todo-backend-application
Estructura
Lo siguiente es la estructura actual de la capa de dominio
📦src
┣ 📂commands
┃ ┣ 📂inputs
┃ ┃ ┣ 📜complete-to-do-command.input.ts
┃ ┃ ┣ 📜create-to-do-command.input.ts
┃ ┃ ┣ 📜create-user-command.input.ts
┃ ┃ ┣ 📜get-all-to-dos-command.input.ts
┃ ┃ ┣ 📜index.ts
┃ ┃ ┗ 📜login-command.input.ts
┃ ┣ 📂validators
┃ ┃ ┣ 📂base
┃ ┃ ┃ ┣ 📜index.ts
┃ ┃ ┃ ┗ 📜validator.base.ts
┃ ┃ ┣ 📜complete-to-do.validator.ts
┃ ┃ ┣ 📜create-to-do.validator.ts
┃ ┃ ┣ 📜get-all-to-dos.validator.ts
┃ ┃ ┣ 📜index.ts
┃ ┃ ┣ 📜login.validator.ts
┃ ┃ ┗ 📜new-user.validator.ts
┃ ┣ 📜complete-to-do.command.ts
┃ ┣ 📜create-to-do.command.ts
┃ ┣ 📜get-all-to-dos.command.ts
┃ ┣ 📜index.ts
┃ ┣ 📜login.command.ts
┃ ┗ 📜new-user.command.ts
┣ 📂common
┃ ┣ 📂config
┃ ┃ ┣ 📜app.config.ts
┃ ┃ ┗ 📜index.ts
┃ ┣ 📂enums
┃ ┃ ┣ 📜config.enum.ts
┃ ┃ ┣ 📜db-order.enum.ts
┃ ┃ ┗ 📜index.ts
┃ ┣ 📂exceptions
┃ ┃ ┣ 📜application.exception.ts
┃ ┃ ┗ 📜index.ts
┃ ┣ 📂interfaces
┃ ┃ ┣ 📜index.ts
┃ ┃ ┣ 📜jwt-data-user.intertface.ts
┃ ┃ ┗ 📜query-options.interface.ts
┃ ┣ 📂libs
┃ ┃ ┣ 📂jwt
┃ ┃ ┃ ┣ 📂interface
┃ ┃ ┃ ┃ ┣ 📜index.ts
┃ ┃ ┃ ┃ ┣ 📜jwt-header.interface.ts
┃ ┃ ┃ ┃ ┣ 📜jwt.interface.ts
┃ ┃ ┃ ┃ ┗ 📜payload.interface.ts
┃ ┃ ┃ ┣ 📜index.ts
┃ ┃ ┃ ┗ 📜jwt.lib.ts
┃ ┃ ┗ 📜index.ts
┃ ┗ 📜index.ts
┣ 📂persistence
┃ ┣ 📂exceptions
┃ ┃ ┣ 📜index.ts
┃ ┃ ┗ 📜persistence.exception.ts
┃ ┣ 📂models
┃ ┃ ┣ 📂base
┃ ┃ ┃ ┣ 📜document.base.ts
┃ ┃ ┃ ┗ 📜index.ts
┃ ┃ ┣ 📜index.ts
┃ ┃ ┣ 📜to-do.mode.ts
┃ ┃ ┗ 📜user.mode.ts
┃ ┣ 📂repositories
┃ ┃ ┣ 📂base
┃ ┃ ┃ ┣ 📜index.ts
┃ ┃ ┃ ┗ 📜repository.base.ts
┃ ┃ ┣ 📜index.ts
┃ ┃ ┣ 📜to-dos.repository.ts
┃ ┃ ┗ 📜users.repository.ts
┃ ┗ 📜index.ts
┣ 📂use-cases
┃ ┣ 📂base
┃ ┃ ┣ 📜index.ts
┃ ┃ ┗ 📜use-case.base.ts
┃ ┣ 📜complete-to-do.use-case.ts
┃ ┣ 📜create-to-do.use-case.ts
┃ ┣ 📜create-user.use-case.ts
┃ ┣ 📜get-all-to-dos.use-case.ts
┃ ┣ 📜index.ts
┃ ┗ 📜login.use-case.ts
┣ 📜app.ts
┗ 📜index.ts
Diagramas
Sí por alguna razón no deseas revisar el código, aquí te dejo los diagramas de modelado de los apartados más relevantes.
Aplicación y casos de uso
Comandos, inputs y validadores
Librería para el manejo de JWT
Persistencia
¿Qué hace falta?
El próximo paso es establecer la capa de infraestructura, y para ello, trabajaré con NestJs, TypeOrm y PostgreSQL. Sin embargo, es importante destacar que, en teoría, la elección del Framework, ORM y el tipo de base de datos debería ser transparente para la capa de aplicación.
Además, es importante mencionar que en esta capa de aplicación, he utilizado Zod para la validación de datos. Idealmente, y en teoría, deberíamos evitar cualquier tipo de dependencia de bibliotecas externas. En este sentido, la práctica ideal sería desarrollar nuestro propio motor de validación, una opción que consideraré en un momento posterior.
Palabras finales
Como siempre agradezco cualquier duda, pregunta, inquietud o aporte que desees realizar.
Estoy totalmente abierto a recibir cualquier tipo de retroalimentación. No dudes en contactarme, estaré encantado de recibir tus comentarios.
Top comments (0)