- Clean-Architecture
- Notas
El objetivo de este repositorio es dar explicaciones y ejemplos de como se aplicaría el patrón de arquitectura Clean Architecture.
Lo que van a encontrar acá son mis experiencias y lo que aprendí con la utilización de esta arquitectura y cómo se implementa en el código.
Actuamente programo en WebApis con C# y .NET así que los ejemplos se van a encontrar en estas tecnologías.
- Diagramas
- Comandos de consola
- Ejemplos de código
- Principos SOLID
- Scaffolding
Microservicios y Clean Architecture, ¿Son formas distintas de arquitectura o un Microservicio tiene dentro Clean Architecture?
La confusión es muy común porque en el desarrollo de software usamos la palabra "arquitectura" para referirnos a cosas que ocurren en escalas completamente diferentes.
Un microservicio puede (y muchas veces debería) tener Clean Architecture en su interior. No son patrones excluyentes, sino complementarios. Resuelven problemas distintos en niveles distintos: uno a nivel de sistema y otro a nivel de aplicación.
El patrón de microservicios dicta cómo se estructura un sistema completo. Se enfoca en cómo dividir un dominio de negocio grande en piezas más pequeñas, independientes y desplegables por separado.
- Se preocupa: De la comunicación entre servicios (HTTP, gRPC, RabbitMQ), la resiliencia, el escalado independiente, los despliegues y la división de bases de datos.
- Lo que ignora: A la macro-arquitectura no le importa en absoluto cómo está escrito el código dentro de cada servicio. Un microservicio podría ser un script espagueti de 2000 líneas o una obra maestra del diseño de software. Al ecosistema le da igual, siempre y cuando exponga los endpoints correctos y cumpla su contrato.
Clean Architecture dicta cómo se estructura el código fuente de una sola aplicación, en este caso, de un solo microservicio. Se enfoca en la separación de responsabilidades y en mantener el dominio del negocio aislado de los detalles técnicos.
- Se preocupa: De que las reglas de negocio (Entidades, Casos de Uso) no dependan de la base de datos (SQL, Mongo), del framework web o de las APIs externas.
- Lo que ignora: A Clean Architecture no le importa si la aplicación es un monolito gigante, una herramienta de consola, o uno de cincuenta microservicios. Solo le importa que el código interno esté desacoplado y sea testeable.
Empecemos por el principio. Cuando tuve que aprender sobre esta arquitectura fué un reto, porue yo ya había aprendido la clásica "Programación en capas". Entonces, ¿Cómo podía traducir lo que yo ya conocía a esto nuevo?
El cambio mas notorio son los nombres de las capas. Aprendí las capas BE, BLL, DAL y UI pero en el estandar de la inudstria es otro. Se utilizan las capas Domain, WebApi o Presentation, Application e Infraestructure. Entonces la pregunta es ¿Cuál es cuál?
| Programación en capas | Clean Architecture | Funcionalidad |
|---|---|---|
| Business Entity Layer (BE o BEL) | Domain | Entidades |
| User interface (UI) | Presentation o WebApi | Controllers |
| Business Logical Layer (BLL) | Application | Lógica de negocio |
| Data Access Layer (DAL) | Infraestructure | Acceso a datos |
Entonces, Clean Architecture también usa capas (generalmente representadas como anillos concéntricos o cebolla), pero invierte el control usando la Regla de Dependencia: El código solo puede apuntar hacia adentro. Las capas internas no deben saber absolutamente nada de las capas externas.
Esto se traduce a:
- Presentation "conoce" a Application.
- Presentation "conoce" a Infraestructure. TODO: Fijarse si esto es así
- Infraestructure "conoce" a Application.
- Application "conoce" a Domain.
- Domain no "conoce" a nadie.
Por la inyección de dependencias y el contexto de la BD.
flowchart TD
%% Definición de estilos basados en los colores de tu imagen
classDef presentation fill:#A5D66F,stroke:#333,stroke-width:2px,color:#000,font-weight:bold;
classDef infrastructure fill:#3DB7FF,stroke:#333,stroke-width:2px,color:#000,font-weight:bold;
classDef application fill:#FF545A,stroke:#333,stroke-width:2px,color:#000,font-weight:bold;
classDef domain fill:#8C8BD4,stroke:#333,stroke-width:2px,color:#000,font-weight:bold;
subgraph OuterLayer [Capa Externa]
direction TB
P(Presentation):::presentation
subgraph MiddleLayer [Capa Intermedia]
direction TB
A(Application):::application
subgraph InnerLayer [Capa Interna]
direction TB
D(Domain):::domain
end
end
I(Infrastructure):::infrastructure
end
%% Regla de dependencia de Clean Architecture (Siempre hacia el centro)
P -->|Conoce a| A
P -->|Conoce a| I
I -->|Conoce a| A
A -->|Conoce a| D
%% Estilos de los contenedores
style OuterLayer fill:none,stroke:#666,stroke-width:2px,stroke-dasharray: 5 5
style MiddleLayer fill:none,stroke:#666,stroke-width:2px,stroke-dasharray: 5 5
style InnerLayer fill:none,stroke:#666,stroke-width:2px,stroke-dasharray: 5 5
Es el centro de todo. Contiene las Entidades (los modelos de negocio fundamentales) y las reglas de negocio puras. No tiene ninguna dependencia externa. No sabe de bases de datos, ni de JSON, ni de HTTP.
Contiene los Casos de Uso (lo que el sistema puede hacer). Aquí se define la lógica de la aplicación y las interfaces (abstracciones) para interactuar con el mundo exterior (como IUserRepository). Tampoco sabe cómo se guardan los datos.
Aquí es donde se implementan las interfaces definidas en la capa de Aplicación. Es donde vive el código que interactúa con Entity Framework, Dapper, clientes HTTP, o el sistema de archivos.
La capa más externa. Contiene los Controladores (Controllers) que reciben las peticiones HTTP y devuelven respuestas. Su único trabajo es traducir el mundo web a parámetros que la capa de Aplicación pueda entender.
La diferencia clave: Inversión de Dependencias (SOLID) En Clean Architecture, la capa de Casos de Uso (Aplicación) no depende de la implementación de la base de datos (Infraestructura). En su lugar, la Aplicación define una interfaz y la Infraestructura la implementa.
Esto significa que tanto la Presentación como la Infraestructura apuntan sus dependencias hacia el centro. Si mañana decides cambiar tu base de datos relacional por una base de datos NoSQL, o cambiar tu API REST por un sistema de mensajería, tu Dominio y tus Casos de Uso permanecen exactamente iguales porque nunca estuvieron acoplados a esa tecnología.
Son diferentes proyectos (.proj).
Infraestructure, Application y Domain son proyectos classlib y Presentation es un proyecto webapi.
# Crear los proyectos de las capas (Dominio, Aplicación, Infraestructura) como Class Libraries
dotnet new classlib -n NOMBREPROYECTO.Domain
dotnet new classlib -n NOMBREPROYECTO.Application
dotnet new classlib -n NOMBREPROYECTO.Infrastructure
# Crear el proyecto WebAPI
dotnet new webapi -n NOMBREPROYECTO.WebApiSon las referencias entre los proyectos.
# Establecer las refenrecias entre proyectos (Regla de dependencia de Clean Arch)
# WebApi (Presentation/UI) depende de Application (para usar casos de uso) e Infrastructure (para inyección de dependencias)
dotnet add src\NOMBREPROYECTO.WebApi\NOMBREPROYECTO.WebApi.csproj reference src\NOMBREPROYECTO.Application\NOMBREPROYECTO.Application.csproj src\NOMBREPROYECTO.Infrastructure\NOMBREPROYECTO.Infrastructure.csproj
# Infrastructure conoce Application
dotnet add src\NOMBREPROYECTO.Infrastructure\NOMBREPROYECTO.Infrastructure.csproj reference src\NOMBREPROYECTO.Application\NOMBREPROYECTO.Application.csproj
# Application conoce de Domain
dotnet add src\NOMBREPROYECTO.Application\NOMBREPROYECTO.Application.csproj reference src\NOMBREPROYECTO.Domain\NOMBREPROYECTO.Domain.csprojNOMBREPROYECTO (carpeta)
├── src/
│ ├── NOMBREPROYECTO.Domain/
│ │ ├── Entities/ # Clases puras.
│ │ ├── Interfaces/ # Contratos abstractos (ej. IUserService).
│ │ └── NOMBREPROYECTO.Domain.csproj
│ │
│ ├── NOMBREPROYECTO.Application/
│ │ ├── DTOs/ # Objetos para transferir datos por la red.
│ │ ├── Services/ # Casos de uso y orquestación.
│ │ ├── Mappings/ # Transformaciones de objetos (ej. AutoMapper).
│ │ ├── Interfaces/ # Contratos para servicios externos.
│ │ └── NOMBREPROYECTO.Application.csproj
│ │
│ ├── NOMBREPROYECTO.Infrastructure/
│ │ ├── Data/ # Configuración de Entity Framework y DbContext.
│ │ ├── Repositories/ # Implementación real con la base de datos.
│ │ └── NOMBREPROYECTO.Infrastructure.csproj
│ │
│ └── NOMBREPROYECTO.WebApi/
│ ├── Controllers/ # Endpoints REST.
│ ├── Properties/ # Configuración de arranque local.
│ ├── Program.cs # Inyección de dependencias y Swagger.
│ ├── appsettings.json # Variables de entorno y connection strings.
│ └── NOMBREPROYECTO.WebApi.csproj
│
├── test/
├── Docker
├── .dockerignore
├── README.md
├── .gitignore
└── NOMBREPROYECTO.slnx
# Crear las sub-carpetas internas de cada proyecto
# Subcarpetas de Domain
mkdir src\NOMBREPROYECTO.Domain\Entities
mkdir src\NOMBREPROYECTO.Domain\Interfaces
mkdir src\NOMBREPROYECTO.Domain\Enums
# Subcarpetas de Application
mkdir src\NOMBREPROYECTO.Application\DTOs
mkdir src\NOMBREPROYECTO.Application\Services
mkdir src\NOMBREPROYECTO.Application\Mappings
mkdir src\NOMBREPROYECTO.Application\Interfaces
# Subcarpetas de Infrastructure
mkdir src\NOMBREPROYECTO.Infrastructure\Data
mkdir src\NOMBREPROYECTO.Infrastructure\Repositories
# Subcarpetas de WebAPI
mkdir src\NOMBREPROYECTO.WebApi\ControllersPor que repository pattern no está en refactoring.guru
La razón principal por la que el patrón Repository no aparece en Refactoring.guru es porque ese sitio web se centra casi exclusivamente en los 23 patrones de diseño clásicos del "Gang of Four" (GoF).
El patrón Repository pertenece a una categoría diferente y tiene orígenes distintos. Aquí te explico las diferencias clave:
- Patrones de Diseño (GoF) vs. Patrones Arquitectónicos Refactoring.guru (Patrones GoF): Se enfoca en el libro de 1994 Design Patterns: Elements of Reusable Object-Oriented Software. Estos patrones (como Singleton, Factory, Observer, o Strategy) resuelven problemas de bajo y medio nivel sobre cómo crear y comunicar objetos en la memoria.
El patrón Repository: Es un patrón arquitectónico (o patrón de arquitectura de aplicaciones empresariales). Resuelve un problema de nivel más alto: cómo aislar la lógica de dominio o de negocio de los detalles de acceso a datos (bases de datos, APIs, etc.).
- El origen de Repository Mientras que los patrones de Refactoring.guru vienen del Gang of Four, el patrón Repository fue popularizado principalmente por dos fuentes literarias distintas:
Patterns of Enterprise Application Architecture (PoEAA) por Martin Fowler (2002).
Domain-Driven Design (DDD) por Eric Evans (2003).
Martin Fowler define Repository como algo que "media entre el dominio y las capas de mapeo de datos usando una interfaz similar a una colección para acceder a los objetos del dominio". Refactoring.guru no cubre patrones empresariales ni de persistencia de datos.
- ¿Dónde puedes aprender sobre el patrón Repository? Dado que Refactoring.guru no lo cubre, te recomiendo estas fuentes (que son los "estándares de la industria" para este patrón):
El catálogo online de Martin Fowler: Tiene una excelente definición técnica en su sitio web.
Documentación de Microsoft (Arquitectura de .NET): Microsoft tiene guías extensas y muy visuales sobre cómo implementar el patrón Repository y Unit of Work, especialmente en el contexto de C# y Entity Framework, pero los conceptos aplican a cualquier lenguaje.
Libros de Domain-Driven Design: Cualquier recurso introductorio a DDD abordará el patrón Repository en detalle.
En resumen: Refactoring.guru es un catálogo de micro-soluciones orientadas a objetos (GoF), mientras que Repository es una macro-solución orientada a la persistencia y arquitectura del software.