¿Por qué utilizo Clean Architecture?

En este artículo me gustaría explicar los motivos por los que utilizó Clean Architecture como arquitectura para desarrollar proyectos desde 2016.

Antes de Clean Architecture

Antes de trabajar con Clean Architecture, allá por el 2010, solía desarrollar siguiendo una arquitecura típica en 3 capas presentacion -> business -> data.

Posteriormente, sobre 2012, trabajé siguiendo "más o menos" la estructura de capas que propone Erick Evans en su libro Domain-Driven Design:Tackling Complexity in the Heart of Software

Problemas de las arquitecturas anteriores

En la arquitectura clásica de tres capas, el problema principalmete es que la aplicación no esta desarrollada orientada al negocio, por lo tanto capa de dominio tiene dependencias con la capa de datos que hacen que sea menos escalable.

No me atrevería a decir que la estructura de capas que propone Erick Evans tiene problemas, lo que si puedo afirmar es lo que no funcionó en los equipos donde lo utilizé.

Falta un poco de definición concreta y reglas que ayuden a implemtar la arquitectura.

En esta arquitectura dentro de la capa de aplicación se ubican los servicios, su función es coordinar los distintos objetos de la capa de dominio y de datos para llevar a cabo una acción. Su labor estaba clara que es coodinar, asimilamos "más o menos bien" que no debían contener lógica empresarial, esta debe residir en los objetos de dominio.

El problema vino a la hora de definir qué se representa como un servicio, acabamos definiendo servicios para todo, incluso había servicios invocando a servicios.

Como consecuencia el código no quedaba limpio y gente que entraba en el equipo no tenía claro cuando había que crear un servicio y el código legacy nuestro al que se enfrentaba tampoco ayudaba.

¿Qué es Clean Architecture?

Clean architecture es un conjunto de principios cuya finalidad principal es ocultar los detalles de implementación a la lógica de dominio de la aplicación.

De esta manera mantenemos aislada la lógica, consiguiendo tener una lógica mucho más mantenible y escalable en el tiempo.

La regla de dependencia

Las principal característica de Clean Architecture frente a otras arquitecturas es la regla de dependencia.

En Clean Architecture, una aplicación se divide en responsabilidades y cada una de estas responsabilidades se representa en forma de capa.

De esta forma tenemos capas exteriores y capas interiores:

  • Las capa más exterior representa los detalles de implementación
  • Las capas más interiores representan el dominio incluyendo lógica de aplicación y lógica negocio empresarial.

La regla de dependencia nos dice que un circulo interior nunca debe conocer nada sobre un circulo exterior. Sin embargo, los circulos exteriores si pueden conocer circulos interiores.

La lógica de dominio es lo que menos va a cambiar con el tiempo y por lo tanto debemos evitar que tenga dependencias de detalles de implementación que van a cambiar con más frecuencia.

¿En qué capas se divide Clean Architecture?

Clean architecture se divide en las siguientes capas:

  • Entidades
  • Casos de uso
  • Adaptadores
  • Frameworks y drivers

Tambíen podemos ver estas capas bajo la siguiente agrupación:

  • Dominio -> entidades y casos de uso
  • Adaptadores
  • Detalles de implementación -> frameworks y drivers

Dominio

El dominio es el corazon de una aplicación y tiene que estar totalmente aislado de cualquier dependencia ajena a la lógica o los datos de negocio.

Entidades

La lógica de negocio empresarial es aquella lógica que existiría aunque no tengamos una aplicación para automatizar los procesos de una compañia.

Por ejemplo que para relizar un pedido es necesario que deba existir un cliente con nombre, apellidos, NIF y una dirección.

La lógica y datos de negocio empresarial se representa utilizando las entidades.

Las entidades contienen los datos de negocio así como las reglas de negocio empresarial.

Las entidades de una aplicación podrían ser compartidas entre diferentes aplicaciones dentro de una compañia.

Por ejemplo en el caso anterior la entidad cliente podría compartirse entre una aplicación móvil, si quisieramos realizar las validaciones sin necesidad de una llamada de red, y su backend o API porque las reglas para dar de alta un cliente serían las mismas.

Casos de uso

Los casos de uso representan la lógica de aplicación, que existe principalmente debido a la automatización de procesos mediante la aplicación y es inherente a cada aplicación.

Por ejemplo para crear un pedido, el caso de uso entre la aplicación móvil y la API tiene sentido que sean diferentes.

El caso de uso crear pedido en la aplicación móvil, puede tener unas validaciones mínimas necesarias si queremos evitar llamadas a red prevías y la posterior llamda a la API para crear el pedido.

Sin embargo en la API, tiene sentido que sea diferente. A parte de crear el pedido, es posible que el caso de uso se encargue de coordinar el envío de email al usuario, gestión de stock, generación de factura etc..

Adaptadores

Los adaptadores se van a encargar de transformar la información como se entiende y es representada en los detalles de implementación o frameworks, drivers a como la entiende el dominio.

Es habitual utilizar en este punto junto con clean architecture diferentes patrones de presentación como MVC, MVP, MVVM o BloC donde los presenters, controllers, view models o blocs serían los adaptadores encargados de transformar la información de las vistas a información que necesitan los casos de uso.

Por otra parte, también vamos a tener adaptadores que se van a encargar de trasformar información como la entiende el dominio a como la entienden framewors de persistencia o red como ORMs, base de datos, API Rest etc..

Detalles de implementación

Los detalles de implementación en clean architecture son todos aquellos framworks, librerías que se suelen utilizar en una aplicación para mostrar o almacenar información:

  • librerías de UI
  • librerías de base de datos
  • librerías de red
  • librerías de analíticas
  • Framework de Android
  • Framework de iOS
  • ReactJS
  • VueJS
  • etc..

En definitiva todo aquello que no es lógica intrínsica a nuestra aplicación, librerías o los formatos utilizados por estas librarías para representar la información xml, json, html etc..

Son detalles de implementación porque no son o no seberían ser, que este es otro tema, piezas fundamentales de una aplicación.

Si yo utilizo xml o json para comunicarme con la api de servidor o si esta api es rest o graphql son conceptos que deberían quedar relegados a la capa de datos y el dominio de una aplicación no deberia depender de ello.

El dominoo de una aplicación tampoco deberia depender de la librería o framework de UI como Android, iOS, ReactJS, VueJS.

Si hacemos esto bien debería ser sencillo cambiar de framework de UI o incluso tener dos interfaces diferentes de una aplicación, en el caso más extremo por ejemplo ReactJs y terminal.

Comunicación entre las capas

Como hemos visto en la regla de dependencia, los circulos interiores no pueden depender de los exteriores.

Sin embargo los circulos exteriores si tienen que poder comunicarse con los exteriores y para poder realizar esto vamos a utilizar el Principio de Inversión de Dependencia.

Crearemos en la capa de casos de uso, las abstracciones que deben implementar los adaptadores.

De esta forma conseguimos que los adaptadores dependan del dominio pero este no dependa de ellos.

El uso de este principio es lo que consigue que el dominio quede aislado y pueda ser sencillos reemplazar adaptadores con el tiempo o incluso por dobles de test para realizar pruebas.

Ventajas de usar Clean Architecture

Las principales ventajas de usar Clean Arcchitecture son:

  • Independencia de Frameworks. No estas acoplado a librerías, lo que permite utilizar estas librerías como herramientas que son fácilmente sustituibles.

  • Testable. las reglas de negocio son fácilmente testables sin utilizar la interfaz de usuario, base de datos, servidor web.

  • Independiente de la interfaz de usuario. La interfaz de usuario es fácilmente sustituible o las nuevas versiones del framework de UI que usas tienen un impacto mínimo.

  • Independientes de la base de datos. Es fácil sustituir una base de datos por otra sin afectar a las reglas de negocio o o las nuevas versiones del framework de persistencia que usas tienen un impacto mínimo

  • El dominio es la parte más importante. siguiendo la regla de dependencia, la capa de dominio es la más importante y de la que dependen todas las demás pero el dominio no depende de ninguna. ¿como consigue el dominio comunicarse con las demás capas sin depender de ellas?, haciendo uso del principio SOLID de Inversión de dependencia.

  • Jerga funcional, En Clean Architecture los objetos encargados de la coordinación entre objetos de la capa de dominio y datos son los Use Case, también denominados Interactors. Esta definición esta más cercana la jerga funcional y se entiende mejor.

¿Cuando usar Clean Architecture?

Clean architecture tiene sentido cuando estamos desarrollando una aplicación que va a tener una duración de vida media o larga.

Si tienes que crear una aplicación para un evento como una feria y después no se va a mantener más tal vez no tenga sentido.

Si por el contrario va a tener una diración media o larga, donde la aplicación a va a ser evolucionada con nuevas features, vamos a actualizar librerias de las que depende a nuevas versiones en un futuro o utilizar nuevas, tiene sentido usar Clean Architecture.

Conclusiones

Hemos visto porque utilizo clean architecture, una introducción a las principales partes de arquitectura y sus ventajas.

Al final se trata de utilizar las herramientas en tu trabajo con las que te sientas más cómodo y sientas que haces tu trabajo mejor, de una forma más productiva.

Eso es lo que me sucede a mi cuando aplicó Clean Architecture en mis proyectos.

Código fuente

En mi GitHub tengo diferentes repositorios donde utilizo Clean Architecture:

Recursos relacionados