Ya que me lo han pedido bastante, en este post vamos a ver qué es clean architecture o arquitectura limpia, hoy vamos a ver qué es y al final daré mi opinión.
índice
Nota: el código que hay enlazado no es mio, es un proyecto de Github muy popular a la hora de utilizarlo como plantilla para clean architecture.
1 - Qué es clean architecture o arquitectura limpia?
Para entender qué es clean architecture o arquitectura limpia primero tenemos que entender que es una arquitectura que se centra en el dominio. O en otras palabras, todas las dependencias apuntan al dominio.
Imagen de Robert C martin.
Lo que este gráfico quiere decir es que tu aplicación esta compuesta de capas, y acciones/cambios que pasan en capas exteriores no afectan a las capas interiores.
1.1 - Cómo se dividen las capas en clean architecture?
Por ejemplo, imagínate que tienes una API Rest y quieres migrar a grpc, pues simplemente cambias la capa de presentación (azul), y eso no afecta a las capas interiores. Porque la capa exterior siempre es el punto de entrada a tu aplicación, ya sea una api, una app de escritorio, o una web, es el punto de entrada.
La segunda capa que vemos es la que identifica como “interface adapters” (verde) esto no es ni más ni menos que la capa de acceso a datos, la que va a consultar/insertar en la base de datos, el sistema de ficheros, o servicios externos, por ejemplo a través de una llamada api, etc.
La tercera capa, es la capa de los casos de uso, por ejemplo en la típica aplicación, es muy común utilizar mediatr en estos proyectos, así que los command, queries y handlers estarán ahí. Básicamente donde está la lógica de lo que cada escenario tiene que hacer.
La capa central (amarilla) es la capa de dominio, que en la gran mayoría de casos van a ser las entidades de la base de datos., en el caso de .NET las entidades de entity framework.
Por cierto en esta capa podemos poner reglas; Por ejemplo imagina que tienes una app de hacer una lista de tareas, típico “Todo List” y puedes querer que solo se pueda incluir una tarea al día, pues esa regla la puedes hacer en la capa de dominio, sin ningún problema.
Esto quiere decir que la capa de lógica de negocio cuando utilizamos clean architecture son las dos capas interiores, la capa de aplicación y la capa de dominio.
1.2 - Las dependencias en Clean architecture
Pero la parte más importante son las flechitas que podemos ver, porque esto quiere decir que las capas exteriores pueden referenciar capas interiores pero las capas interiores no pueden referenciar a las exteriores. Por eso, como he dicho antes, podemos cambiar la api rest a grpc tocando únicamente la capa exterior.
Y esto para mi, es lo mas importante de clean arquitecture y donde entra en especial la capa de dominio, porque es nuestra capa interior, y no depende de ninguna otra. Esto es importante, a tener en cuenta, porque, como he dicho, la capa de dominio son las entidades de entity framework (en la gran mayoría de casos en .NET), pero la capa que hace las llamadas a la base de datos es la de aplicación, la cual es una capa superior, de hecho está fuera de la lógica de negocio, como puedes ver en esta otra representación:
Lo que se hace es, en la capa de aplicación indicamos una interfaz, la cual será implementada por la capa de infraestructura la cual es la responsable de decidir si eso es una llamada a la base de datos o a un servicio externo.
Aunque bueno en el caso de .NET con entity framework, es muy probable es que pongas un IDbContext y tengas referenciado entity framework dentro de la capa de aplicación, lo cual, en mi opinión pues tampoco es la mejor práctica.
Y porque? bueno la idea de la interfaz es abstraer la implementación, pero si vamos al código que tomamos como ejemplo podemos ver la sigueinte interfaz
public interface IApplicationDbContext
{
DbSet<TodoList> TodoLists { get; }
DbSet<TodoItem> TodoItems { get; }
Task<int> SaveChangesAsync(CancellationToken cancellationToken);
}
Y qué contiene? Un DbSet
... En teoría estamos abstrayendo la capa de datos de la capa de aplicación, pero si bien es cierto que no la referenciamos, estampos importando la librería de Entity Framework en la capa de apliación, lo cual bueno, pues destruye la idea de la abstracción.
2 - Necesito clean architecture en mi aplicación?
Respuesta rápida: Posiblemente NO.
Ahora vamos a ver el por qué.
En la práctica clean architecture puede parecer que nos soluciona todos los problemas. Lo primero que tenemos que tener en cuenta es que no hay una solución que solucione todo, y eso tenemos que tenerlo siempre en cuenta.
La realidad de clean architecture es que si tu proyecto es pequeño es hacer sobre ingenieria. Y para prueba, el proyecto enlazado de GitHub.
Dentro de cada capa tenemos subcapas, por ejemplo, si usamos mediatr, que por lo que sea es muy común con clean architecture (esto me da para otro post), vamos a tener nuestro command, nuestro query y nuestro handler, y la estructura de archivos y carpetas puede ser la siguiente:
Si la aplicación es pequeña, de primeras no necesitas todo esto y lo único que haces es crear carpetas, capas y abstracciones sin sentido más allá que justificar el uso de "clean" architecture.
Esto es especialmente alarmante cuando la app que estás creando el 90% de las operaciones que haces son CRUD planos, que por algún motivo alguien ha decidido aplicar clean architecture. Resaltando especialmente en microservicios, donde muchos son únicamente insertar lo que llega en la API haciendo unas validaciones básicas.
Otro punto muy importante es que TODO va detrás de una interfaz, mira, yo soy el primero que usa interfaces, pero no todos los tipos necesitan interfaces (otro tema que podría hacer un post únicamente de eso). Tener tantas interfaces hace que nuestros tests dependan en exceso de los mocks (y el trabajo que ello conlleva). Encima la abstracción que tenemos tras la interfaz no arregla los problemas, normalmente o los mueve de sitio, o crea otros nuevos.
Esos problemas son también llevados a los miembros más inexperimentados del equipo, porque dentro de lo que cabe, clean architecture, tiene una curva de aprendizaje más o menos alta ya que cuando abres un proyecto y te preguntas qué es lo que hace?, Cuáles son las funcionalidades? Pues no lo sabes de primeras porque está todo escondido detrás de carpetas llamadas “servicios” , “interfaces”, “data”, vamos que está todo organizado de forma técnica. Y muchas veces cuando alguien nuevo llega al sistema puede ser complejo de entender, y si es un proyecto grande, un cambio pequeño puede ser difícil de identificar dónde hacerlo.
Mi opinión personal es que con tantas capas cuando un proyecto crece nunca sigue siendo tan fácil de mantener. (seguro que algun tonto menciona skill issues). Como digo, es mi opinión basada en mi experiencia personal.
2.1 - Cuándo usar clean architecture?
Cuando tu proyecto tiene un “rich domain” que se diría en inglés, o en otras palabras, cuando tienes mucha lógica en la(s) capa de lógica de negocio, cuando esa lógica va más allá de agrupar información y mostrarla al usuario o en las actualizaciones pasar la request entre capas, y validar si un campo es mayor que X.
Las reglas del dominio es lo principal, ya que como he dicho antes es una arquitectura centrada en el dominio.
Por eso, cuando veo clean architecture “by the book” en sistemas de microservicios se me hincha una vena, porque la gran mayoria de veces es overengineering.