Blog/GeneralNuevo

Arquitectura Limpia: Cómo diseñar software de verdad

Todo lo que necesitas saber sobre Clean Architecture de Robert C. Martin.

General18 de junio de 2026
Arquitectura Limpia: Cómo diseñar software de verdad

Seguramente ya te ha pasado: empiezas un proyecto, todo va bien las primeras semanas, y de repente cada cambio que haces rompe tres cosas que no tienen nada que ver. Tu controller tiene 600 líneas, la lógica de negocio está mezclada con consultas a la base de datos, y si alguien te pregunta "¿dónde vive tal funcionalidad?" la respuesta honesta es "en todos lados y en ninguno". Este blog está basado en el libro "Arquitectura Limpia" de Robert C. Martin (Uncle Bob), publicado en 2018, y mi objetivo es explicarte las ideas principales para que puedas aplicarlas en tus propios proyectos sin tener que leerte las 400+ páginas (aunque te lo recomiendo).

¿Qué es la arquitectura de software y por qué debería importarte?

Una de las primeras cosas que aclara el libro es que no hay diferencia real entre "diseño" y "arquitectura" de software. Normalmente pensamos en arquitectura como las decisiones de alto nivel y en diseño como los detalles, pero en realidad son parte de lo mismo: un continuo de decisiones que van desde la estructura general hasta el último if en tu código. Lo que sí tiene una definición clara es el objetivo de todo esto: minimizar los recursos humanos necesarios para construir y mantener un sistema. Así de simple. Si cada nuevo feature te cuesta más esfuerzo que el anterior, tu arquitectura está fallando.

"El objetivo de la arquitectura de software es minimizar los recursos humanos necesarios para construir y mantener el sistema requerido." — Robert C. Martin, Arquitectura Limpia (Cap. 1)

El problema real: cuando el código se convierte en un desastre

Uncle Bob presenta un caso de estudio con datos reales de una empresa. El equipo de ingeniería creció release tras release, pero la productividad (medida en líneas de código por release) se estancó. El costo por línea de código se disparó: en la versión 8 era 40 veces más caro producir código que en la versión 1. ¿Qué pasó? No le pusieron atención a la estructura del código. Cuando los sistemas se construyen rápidamente y sin cuidar la organización, eventualmente cada cambio se vuelve costoso y arriesgado. Es la diferencia entre correr rápido al inicio y poder seguir corriendo a largo plazo.

Los paradigmas de programación como cimientos

Antes de hablar de arquitectura, el libro repasa tres paradigmas que son la base de todo: programación estructurada, programación orientada a objetos y programación funcional. Lo importante no es memorizarlos, sino entender qué le quita cada uno al programador. La programación estructurada nos quitó el goto (control de flujo directo), la OOP nos quitó los punteros a funciones (reemplazándolos con polimorfismo), y la funcional nos quita la asignación de variables (inmutabilidad). Cada paradigma es una restricción que nos obliga a escribir mejor código, no una herramienta que nos da más poder.

Los principios SOLID: la base de un buen diseño

Los principios SOLID son cinco reglas de diseño que aplican a nivel de clases y módulos, y que son el fundamento de la arquitectura limpia. No son leyes absolutas, pero seguirlas te va a ahorrar muchos problemas. Vamos uno por uno:

S — Principio de Responsabilidad Única (SRP)

Este es probablemente el principio más malinterpretado. NO significa que "una clase debe hacer una sola cosa" (eso es un principio de funciones, no de clases). Lo que realmente dice es que una clase debe tener un único motivo para cambiar, o dicho de otra forma: debe ser responsable ante un solo actor. Si tu clase Employee tiene métodos para calcular el salario (que usa Finanzas), generar reportes (que usa Recursos Humanos) y guardar en la base de datos (que usa el DBA), tienes tres razones para cambiarla. Cuando Finanzas te pida un cambio en el cálculo de nómina, podrías romper el reporte de RH sin darte cuenta. La solución es separar esas responsabilidades en clases distintas.

O — Principio Abierto-Cerrado (OCP)

Un módulo debe estar abierto a la extensión pero cerrado a la modificación. En otras palabras, deberías poder agregar comportamiento nuevo sin tener que cambiar el código existente. ¿Cómo? Organizando las dependencias para que los componentes de alto nivel (reglas de negocio) estén protegidos de los cambios en componentes de bajo nivel (UI, base de datos). El libro presenta una jerarquía de protección: el Interactor (lógica de negocio) es lo más protegido, luego los Controllers, después los Presenters, y finalmente las Vistas. Los cambios en la Vista nunca deberían obligarte a modificar la lógica de negocio.

L — Principio de Sustitución de Liskov (LSP)

Si tienes una clase base y una subclase, deberías poder usar la subclase en cualquier lugar donde se espera la clase base sin que el programa falle o se comporte de manera inesperada. El ejemplo clásico de violación es el problema del Cuadrado y el Rectángulo: si Cuadrado hereda de Rectángulo pero modificar el ancho también cambia la altura, cualquier código que use un Rectángulo y espere que ancho y altura sean independientes va a fallar. Este principio aplica más allá de herencia de clases: aplica a nivel de APIs e interfaces en toda tu arquitectura.

I — Principio de Segregación de Interfaces (ISP)

No obligues a tus clases a depender de métodos que no usan. Si tienes una interfaz gigante con 20 métodos y una clase solo necesita 3, estás creando un acoplamiento innecesario. Es mejor tener varias interfaces pequeñas y específicas. A nivel de arquitectura, esto se traduce en no hacer que un componente dependa de un framework o módulo completo cuando solo necesita una pequeña parte de él.

D — Principio de Inversión de Dependencia (DIP)

Este es el principio más importante para la arquitectura limpia. Dice que el código de alto nivel no debe depender del código de bajo nivel — ambos deben depender de abstracciones. En la práctica: tu caso de uso no debe importar directamente Entity Framework o tu ORM. Define una interfaz (abstracción) en la capa de dominio, y que la implementación concreta (el repositorio con EF Core) viva en la capa de infraestructura. Así, si un día cambias de MySQL a PostgreSQL, tu lógica de negocio ni se entera.

EJEMPLO.cs
// Ejemplo del DIP en acción:
// MAL El caso de uso depende directamente de la infraestructura
public class CrearEntregaUseCase {
private readonly AppDbContext _context; // Dependencia directa a EF Core
}
// BIEN El caso de uso depende de una abstracción
public class CrearEntregaUseCase {
private readonly IEntregaRepository _repo; // Solo conoce el contrato
}

Principios de componentes: cohesión y acoplamiento

Más allá de clases individuales, el libro dedica dos capítulos a cómo agrupar clases en componentes (paquetes, módulos, ensamblados). Para la cohesión, hay tres principios que están en tensión entre sí: el de Equivalencia Reutilización/Release (agrupa clases que se liberan juntas), el de Cierre Común (agrupa clases que cambian por las mismas razones — es el SRP aplicado a componentes) y el de Reutilización Común (no obligues a depender de cosas que no se usan — es el ISP aplicado a componentes). Para el acoplamiento, la regla más importante es el Principio de Dependencias Acíclicas: no debe haber ciclos en el grafo de dependencias entre componentes. Si A depende de B y B depende de A, cualquier cambio en uno afecta al otro y perdiste la independencia.

La Arquitectura Limpia: el modelo completo

La Arquitectura Limpia es la síntesis de varias ideas previas: la Arquitectura Hexagonal de Alistair Cockburn, DCI de Coplien y Reenskaug, y BCE de Jacobson. Todas comparten el mismo objetivo: separación de responsabilidades mediante capas, donde las reglas de negocio están en el centro y los detalles técnicos en la periferia. El modelo se visualiza como círculos concéntricos, y toda la arquitectura se sostiene sobre una sola regla.

"Las dependencias del código fuente deben apuntar solo hacia adentro, hacia políticas de nivel superior." — Robert C. Martin, Arquitectura Limpia (Cap. 22)

Las capas, de adentro hacia afuera

Capa¿Qué contiene?Ejemplo concreto¿Con qué frecuencia cambia?
EntidadesReglas de negocio fundamentales de la empresa. Objetos con los datos y comportamientos más críticos.Una clase "Actividad" con sus validaciones de negocioCasi nunca
Casos de UsoLógica específica de la aplicación. Orquestan las entidades para cumplir un objetivoCrearEntregaUseCase, CalcularCalificacionUseCaseCuando cambian los requisitos del sistema
Adaptadores de InterfazTraducen datos entre las capas internas y el mundo exterior. Controllers, Presenters, Repositorios.Un ActividadesController, un EntregaRepositoryCuando cambia cómo se presenta o almacena la información
Frameworks e InfraestructuraHerramientas, librerías, bases de datos, UI. Todo lo que es un "detalle".Entity Framework, React, JWT, servicios de emailCuando se actualizan herramientas o se migra tecnología

La regla es simple pero poderosa: nada en un círculo interno puede saber nada sobre un círculo externo. Tu entidad no puede importar nada de Entity Framework. Tu caso de uso no puede referenciar un Controller. Las dependencias siempre apuntan hacia adentro. Esto se logra usando interfaces: el caso de uso define un "puerto de salida" (una interfaz), y el presentador o repositorio en la capa externa lo implementa. Es el Principio de Inversión de Dependencia aplicado a nivel de arquitectura.

¿Qué cruza los límites entre capas?

Cuando los datos pasan de una capa a otra, deben hacerlo como estructuras de datos simples: DTOs, objetos planos, diccionarios. Nunca pases una entidad directamente al controller, ni un objeto de respuesta del ORM directamente al caso de uso. ¿Por qué? Porque si pasas un objeto de Entity Framework desde tu repositorio hasta tu vista, tu vista ahora depende indirectamente de EF Core, y la Regla de Dependencia se rompe. Cada capa transforma los datos al formato que le conviene.

EJEMPLO.txt
Ejemplo de flujo de datos:
[HTTP Request]
Controller (Adaptador)
InputDTO
UseCaseInteractor (Caso de Uso)
llama a IRepository (interfaz)
Repository (Infraestructura implementa IRepository)
consulta DB
Entidad (Dominio)
UseCaseInteractor construye OutputDTO
OutputDTO
Presenter (Adaptador)
ViewModel
Vista (Framework React, HTML, etc.)

"Tu arquitectura debería gritar"

Uno de los capítulos del libro se titula "Arquitectura que grita". La idea es que cuando alguien nuevo vea la estructura de carpetas de tu proyecto, debería entender inmediatamente de qué trata el sistema, no qué framework usaste. Si lo primero que ves es "Controllers", "Models", "Views", tu arquitectura grita "MVC" o "ASP.NET". Si en cambio ves "Entregas", "Actividades", "Calificaciones", "Recompensas", tu arquitectura grita el dominio del negocio. Los frameworks son herramientas, no la identidad de tu proyecto.

"Las arquitecturas no se tratan de frameworks. Los frameworks son herramientas para utilizar, no arquitecturas a las que adaptarse." — Robert C. Martin, Arquitectura Limpia (Cap. 21)

Los detalles: la base de datos y la web

El libro dedica toda una sección a enfatizar que tanto la base de datos como la web son detalles, no decisiones arquitectónicas. Tu aplicación no "es" una aplicación web — la web es simplemente un mecanismo de entrega, un dispositivo de entrada/salida. De la misma forma, MySQL no es tu arquitectura — es donde guardas los datos. Una buena arquitectura te permite posponer estas decisiones: deberías poder cambiar de una interfaz web a una de consola, o de MySQL a PostgreSQL, sin tener que reescribir tu lógica de negocio. Si tu código de negocio tiene imports de un framework web o de un ORM específico, algo está mal.

Estructura de proyecto aplicando Arquitectura Limpia

MiProyecto
MiProyecto

Errores comunes al aplicar Clean Architecture

Después de leer sobre este tema, es fácil caer en ciertos errores. Primero: no todo proyecto necesita cuatro capas separadas en proyectos distintos. Si estás haciendo un script, un prototipo rápido o una app que sabes que no va a crecer, toda esta estructura es overkill. Segundo: crear abstracciones innecesarias. Si solo tienes una implementación de un repositorio y nunca va a cambiar, tal vez no necesites la interfaz (aunque el testeo unitario sí la justifica). Tercero: confundir la estructura de carpetas con la arquitectura real. Puedes tener las carpetas perfectas y aún así tener dependencias apuntando en la dirección equivocada. Lo que importa son las dependencias del código fuente, no los nombres de las carpetas.

¿Cuándo sí usar Clean Architecture?

La arquitectura limpia brilla cuando tu proyecto va a crecer, cuando hay varios desarrolladores trabajando al mismo tiempo, cuando necesitas escribir pruebas unitarias de tu lógica de negocio sin levantar una base de datos, o cuando sabes que las tecnologías podrían cambiar (migraciones de framework, cambio de base de datos, etc.). Un proyecto de tesis, un sistema que va a producción, o cualquier aplicación que vas a mantener por más de unos meses son candidatos perfectos.

Conclusión

La Arquitectura Limpia no es la única forma de organizar software. Pero te da un marco mental para tomar decisiones de diseño que escalan. La idea central es brutalmente simple: protege tu lógica de negocio de los detalles técnicos. Pon las reglas del dominio en el centro, los frameworks en la periferia, y asegúrate de que las dependencias siempre apunten hacia adentro. Si te interesa profundizar, el libro de Uncle Bob es la referencia obligada: "Clean Architecture: A Craftsman's Guide to Software Structure and Design" (Robert C. Martin, 2018, Pearson Education). También te recomiendo el template de Clean Architecture para .NET de Jason Taylor y el canal de YouTube de Milan Jovanović para ver estos conceptos aplicados.

Martin, R. C. (2018). Clean Architecture: A Craftsman's Guide to Software Structure and Design. Pearson Education. ISBN: 978-0-13-449416-6

https://github.com/dileofrancoj/elite-web-developer-books

Autor
Daniel Humberto Leyva Chavez
Daniel Humberto Leyva ChavezSoftware Engineer @UAS | 1x Hackathon winner 🥇