Saltar al contenido principal

¿Qué es Clean Architecture?

Antes de escribir una sola línea de código, conviene entender la idea. Clean Architecture no es una carpeta ni una librería: es una forma de decidir qué parte del software puede depender de qué otra. En esta lección veremos qué es, qué problema resuelve, qué busca, qué propone y cuáles son sus partes.

Resumen en una frase

Clean Architecture propone que las reglas de negocio vivan en el centro del sistema y que todo lo demás (interfaz, base de datos, frameworks, APIs) sea un detalle intercambiable que depende del centro, nunca al revés.


1. Definición y origen​

Clean Architecture (Arquitectura Limpia) es un estilo de organización del software propuesto por Robert C. Martin, conocido como Uncle Bob, en un artículo publicado en 2012 y desarrollado ampliamente en su libro Clean Architecture: A Craftsman's Guide to Software Structure and Design (2017).

No parte de cero. Es una síntesis de ideas anteriores que perseguían el mismo objetivo: separar lo que es importante para el negocio de lo que es una herramienta.

Línea de tiempo: Hexagonal, Onion y Clean Architecture

PropuestaAutorAporte principal
Arquitectura Hexagonal (Ports and Adapters)Alistair Cockburn, 2005La aplicación se comunica con el exterior por puertos y adaptadores reemplazables.
Onion ArchitectureJeffrey Palermo, 2008Capas concéntricas con el dominio en el centro y dependencias hacia adentro.
Clean ArchitectureRobert C. Martin, 2012Unifica las anteriores y formaliza la Regla de Dependencia con cuatro círculos.

2. ¿Qué problema resuelve?​

El software cambia constantemente: se reemplaza el framework, se rediseña la interfaz, se migra de base de datos, el backend cambia su API. Cuando la lógica de negocio está mezclada con esas herramientas, cada cambio externo obliga a reescribir código que, conceptualmente, no debería haber cambiado.

Martin lo resume distinguiendo dos tipos de código:

  • Políticas: lo que el sistema hace y por qué importa al negocio (validar un ejercicio, calcular un precio, decidir un permiso). Cambian poco y despacio.
  • Detalles: cómo se muestra o se guarda (React, Next.js, PostgreSQL, fetch). Cambian rápido y con frecuencia.

El problema aparece cuando las políticas dependen de los detalles. La solución es invertir esa relación.

Una pregunta para evaluar cualquier arquitectura

¿Cuánto código tengo que tocar si mañana cambio de framework, de base de datos o de proveedor de API? Cuanto menos, más limpia es la arquitectura.


3. ¿Qué busca? Los objetivos​

Una arquitectura limpia persigue que el sistema sea:

ObjetivoSignificadoBeneficio práctico
Independiente de frameworksEl framework es una herramienta, no el esqueleto del sistema.Se puede actualizar o reemplazar sin reescribir el negocio.
Independiente de la interfazLa UI se puede cambiar sin tocar las reglas.La misma lógica sirve para web, móvil o consola.
Independiente de la base de datosEl negocio no sabe si hay SQL, NoSQL o una API.Se cambia el almacenamiento con impacto mínimo.
Independiente de agentes externosLas reglas no conocen servicios de terceros.Un proveedor puede sustituirse por otro.
TesteableLas reglas se prueban sin UI, sin servidor y sin base de datos.Pruebas rápidas, estables y baratas.

Núcleo con detalles intercambiables

En el diagrama, las piezas con borde punteado son alternativas que se pueden enchufar en el mismo lugar. Eso es independencia: el núcleo no se entera de cuál está conectada.


4. ¿Qué propone? La Regla de Dependencia​

Toda la propuesta se apoya en una sola regla:

Las dependencias del código fuente solo pueden apuntar hacia adentro, hacia las políticas de más alto nivel.

Esto significa que:

  1. Un círculo interno no puede nombrar nada que esté declarado en un círculo externo: ni funciones, ni clases, ni variables, ni formatos de datos.
  2. Un círculo externo sí puede usar lo que ofrece uno interno.
  3. Si el centro necesita algo del exterior (por ejemplo, guardar datos), declara una interfaz propia y el exterior la implementa.

Este último punto es la aplicación del Principio de Inversión de Dependencias (la D de SOLID).

Flujo de control frente a dependencia de código​

En tiempo de ejecución la llamada va de la interfaz al caso de uso y luego a la base de datos. Pero en el código fuente, la flecha hacia la base de datos se invierte:

Inversión de dependencias
// Círculo interno: el caso de uso declara QUÉ necesita
export interface ExerciseRepository {
getAll(): Promise<Exercise[]>;
}

export class GetExercisesUseCase {
constructor(private readonly repository: ExerciseRepository) {}
execute() {
return this.repository.getAll();
}
}

// Círculo externo: la infraestructura CUMPLE el contrato
export class ExerciseRepositoryImpl implements ExerciseRepository {
async getAll() {
// fetch, mappers, etc.
}
}

El caso de uso nunca importa ExerciseRepositoryImpl. Es la infraestructura la que importa la interfaz del dominio. Por eso la dependencia de código apunta hacia adentro aunque la ejecución viaje hacia afuera.


5. Las partes: los cuatro círculos​

Anillos concéntricos y regla de dependencia

El diagrama original de Martin tiene cuatro círculos. El diagrama de arriba es una versión simplificada que agrupa los dos círculos externos en uno. De adentro hacia afuera, los cuatro son:

5.1. Entidades (Entities)​

Contienen las reglas de negocio de la empresa: objetos con datos y comportamiento que serían válidos en cualquier aplicación del mismo negocio. Son lo más estable del sistema y lo último que debería cambiar por razones técnicas.

Ejemplo: un Exercise que exige un nombre de mínimo tres caracteres.

5.2. Casos de uso (Use Cases)​

Contienen las reglas propias de la aplicación. Cada caso de uso representa una intención concreta del usuario y orquesta el flujo de datos desde y hacia las entidades. No sabe si lo llaman desde una web o desde una prueba.

Ejemplo: CreateExerciseUseCase, GetExercisesUseCase.

5.3. Adaptadores de interfaz (Interface Adapters)​

Son traductores. Convierten los datos del formato cómodo para casos de uso y entidades al formato cómodo para el exterior, y viceversa. Aquí viven controladores, presentadores y gateways, es decir, repositorios concretos y mappers.

Ejemplo: ExerciseMapper, ExerciseRepositoryImpl.

5.4. Frameworks y drivers​

Es la capa más externa: herramientas y detalles. Base de datos, framework web, cliente HTTP, la interfaz gráfica. Aquí se escribe poco código propio, sobre todo configuración y pegamento.

Ejemplo: Next.js, React, fetch, el servidor NestJS.

Resumen por capa​

CapaQué contieneEstabilidadConoce a
EntidadesReglas de negocio generalesMuy altaNadie
Casos de usoReglas de la aplicaciónAltaEntidades
AdaptadoresMappers, repositorios, presentersMediaCasos de uso y entidades
Frameworks y driversUI, base de datos, web, HTTPBajaAdaptadores
Los cuatro círculos no son obligatorios

Martin aclara que el diagrama es esquemático: puedes tener más o menos círculos. Lo único que no se negocia es la Regla de Dependencia.


6. Cruzar las fronteras​

Cuando los datos pasan de un círculo a otro deben hacerlo como estructuras simples: objetos planos, DTOs o argumentos. Nunca se debe pasar hacia adentro una fila de base de datos o un objeto propio del framework, porque eso haría que el círculo interno dependa de un detalle externo.

  • Hacia adentro: el mapper convierte el DTO crudo en una entidad.
  • Hacia afuera: el mapper convierte la entidad en el DTO que espera la API.

Esto es lo que veremos en detalle en las lecciones de infraestructura.


7. ¿Cómo se ve en un frontend con Next.js?​

Clean Architecture nació pensando en sistemas de backend, pero la idea se traslada al frontend con una adaptación pragmática:

Círculo de MartinEn nuestro proyecto Next.js
Entidadesdomain/entities
Casos de usodomain/usecases y contratos en domain/repositories
Adaptadores de interfazinfrastructure/mappers, infrastructure/repositories, hooks de presentación
Frameworks y driversNext.js, React, fetch, componentes visuales

Usaremos tres carpetas por feature (domain, infrastructure, presentation) en lugar de cuatro círculos. Es una simplificación válida porque respeta la regla esencial.


8. Críticas y cuándo no aplicarla​

Ninguna arquitectura es gratis. Conviene conocer sus costos:

  • Más archivos y más indirección: para una pantalla simple puede parecer excesivo.
  • Curva de aprendizaje: exige comprender interfaces, inversión de dependencias y mappers.
  • Riesgo de sobreingeniería: aplicar todas las capas a un CRUD pequeño o a un prototipo desperdicia tiempo.
Regla práctica

Aplica Clean Architecture cuando el proyecto vaya a vivir y crecer, tenga reglas de negocio reales, cambie de fuentes de datos o necesite buenas pruebas. Para un prototipo de un fin de semana, una arquitectura más simple es razonable. La clave es decidirlo de forma consciente, no por inercia.


9. Ideas para llevarse​

  1. Clean Architecture separa políticas (negocio) de detalles (herramientas).
  2. Su regla central: las dependencias apuntan solo hacia adentro.
  3. Busca independencia de frameworks, UI, base de datos y servicios externos, además de ser testeable.
  4. Se organiza en círculos: Entidades, Casos de uso, Adaptadores y Frameworks.
  5. La inversión de dependencias permite que el centro defina contratos y el exterior los cumpla.
  6. En las siguientes lecciones la llevaremos a la práctica con Next.js y TypeScript.

Para profundizar​


Cuestionario de Autoevaluación​

Cargando cuestionario...