Arquitectura limpia en la práctica: dónde trazar las fronteras
Arquitectura limpia vende bien en diagramas y mal en implementaciones. El problema no son los principios, sino saber dónde trazar cada frontera cuando el negocio empuja. Esta es la lectura práctica que funciona en proyectos medianos.
La única regla que importa: las dependencias apuntan hacia dentro
Todo el sistema se resume en una flecha: el dominio no conoce a nadie, y todo lo demás depende de él. Si una capa de infraestructura, un framework o un ORM se cuelan en el dominio, has perdido la batalla de la arquitectura — el diagrama ya no refleja la realidad.
src/
├── domain/ # reglas de negocio puras: sin imports de framework
├── application/ # casos de uso: orquesta el dominio
├── infrastructure/# repos: postgres, http, apis externas
└── entrypoints/ # presentación: controllers, cli, interfaces
Traza la frontera por costo de cambio, no por dogma
Pregunta práctica: si mañana cambiamos de framework HTTP o de base de datos, ¿cuánto código se pierde? La frontera vale la pena cuando la respuesta es “mucho”. En proyectos pequeños donde el framework ES el producto, una arquitectura en capas plena es papeleo. Aplica el criterio, no el catálogo.
Depende de interfaces, recibe implementaciones
El dominio/application declaran puertos (interfaces). La infraestructura los implementa. La magia está
en el cableado: composición en el arranque, nunca new hardcodeado dentro de un caso de uso.
// application/libro-compra.ts
interface RepositorioDePagos {
cobrar(importe: number, tarjeta: Tarjeta): Promise<Voucher>;
}
export const comprarLibro = async (repo: RepositorioDePagos, id: string) => {
const total = calcularTotal(id);
return repo.cobrar(total, tarjetaDelUsuario(id));
};
La fuga más común no es técnica, es de vocabulario
Cuando el código de application habla el idioma del ORM (UserEntity.save() con columnas), la
frontera ya se rompió por el lenguaje, no por la estructura. Define antes un vocabulario del dominio
(RegistrarUsuario, ChequeoDeLimite) y haz que las capas internas solo usen esas palabras.
Cómo empezar (sin reescribir todo)
- Encuentra el caso de uso que cambia con más frecuencia y aísla su lógica en
application. - Mueve las consultas de datos detrás de una interfaz, aunque el adaptador siga siendo el ORM.
- Elimina cualquier
importdel framework dentro dedomain/. - Vuelve a ejecutar los tests tras cada paso; la arquitectura se paga en incrementos.
La arquitectura limpia no es un destino, es una deuda gestionada. La trazas cuando el costo del cambio supera el costo de la frontera — y un buen agente de IA sabrá leer exactamente dónde la dejaste.