Clean Architecture


Clean Architecture es una forma de estructurar una aplicación para que la lógica importante sea fácil de entender, cambiar y probar.

La idea central es separar las reglas de negocio de los detalles de implementación. La UI, el framework, la base de datos, los proveedores externos y las librerías son detalles. El dominio y los casos de uso son el centro.

Regla de dependencias

Las dependencias apuntan hacia dentro:

  • La UI puede depender de casos de uso.
  • Los controllers pueden depender de casos de uso.
  • La infraestructura puede implementar interfaces definidas por la aplicación o el dominio.
  • El dominio no debería depender de React, Next.js, Laravel, bases de datos, HTTP ni SDKs externos.

Si una capa interna necesita algo externo, define una interfaz. La implementación concreta vive fuera.

Capas

Frameworks & Drivers

Código acoplado al framework: rutas, Server Actions, Route Handlers, React Server Components, páginas, componentes, comandos CLI o handlers HTTP.

Esta capa debería ser fina. Recibe eventos del mundo exterior y delega.

Interface Adapters

Convierte datos entre el mundo exterior y la aplicación.

Aquí viven controllers, presenters, view models, validación de input externo y mapeos entre DTOs y modelos internos.

Application

Contiene los casos de uso: operaciones concretas que la aplicación permite hacer.

Ejemplos:

  • createTodo
  • publishPost
  • inviteUser
  • syncProductStock

Los casos de uso orquestan reglas, permisos, transacciones y llamadas a puertos. No deberían saber si detrás hay PostgreSQL, Stripe, WordPress o una API REST.

Domain

Contiene entidades, value objects, errores de dominio, reglas puras e interfaces que expresan necesidades del negocio.

Aquí debería estar el código más estable y más fácil de testear.

Infrastructure

Implementa detalles técnicos:

  • Repositorios contra base de datos.
  • Clientes HTTP.
  • SDKs externos.
  • Servicios de email.
  • Storage.
  • Auth provider.

La infraestructura implementa interfaces definidas hacia dentro.

Flujo de una petición

  1. El usuario ejecuta una acción en la UI.
  2. La capa de framework llama a un controller o action.
  3. El controller valida y normaliza el input.
  4. El caso de uso ejecuta la operación.
  5. El caso de uso usa interfaces para persistencia o servicios externos.
  6. La infraestructura resuelve los detalles técnicos.
  7. El resultado vuelve convertido a una forma cómoda para la UI.

Cuándo merece la pena

Úsala cuando:

  • Hay reglas de negocio reales.
  • Esperas que el proyecto crezca.
  • Hay varias entradas posibles: UI, API, CLI, jobs.
  • Necesitas testear sin levantar toda la aplicación.
  • Cambiar de base de datos, proveedor o framework no debería reescribir la lógica.

No hace falta aplicarla completa para una landing, un CRUD pequeño o un prototipo sin reglas relevantes.

Señales de overengineering

  • Hay más archivos de arquitectura que lógica real.
  • Cada acción trivial requiere cinco capas.
  • Las interfaces solo tienen una implementación obvia y no aíslan nada importante.
  • El código es más difícil de leer por seguir el patrón.
  • Los tests prueban mocks, no comportamiento.

Relacionado