Arquitectura limpia en el front
Tags: testing, spanish, javascript, architecture
Published: 2023-07-23 09:27:53

# Introducción

Lo primero que me gustaría decir es que entiendo yo por arquitectura limpia en el front, después de años de experiencia, de leer y practicar mucho este tema.

Para mi la arquitectura limpia en el front es aquella que es **_EVOLUCIONABLE_**, punto no hay más. 

Es aquella que me permite tener hoy una aplicación implementada en un framework X y poder pasar al framework Y sin tener que reescribirla de cero.

Hoy en día esto parece una utopía ya que las personas que estamos en este lado del desarrollo sufrimos un bombardeo constante de mega-frameworks que nos venden el poder hacer aplicaciones de front cada vez más rápidas y vistosas a cambio de que nos aprendamos su solución; ahora podría estar hablando de Angular, Vue, React, Lit, Svelte, NextJS, ...

De hecho poco se habla de la fátiga mental que esto supone y que no sería la primera vez que algunos de estos frameworks desaparecen o se transforman obligando a aprender nuevas soluciones.

Por otro lado ahora mucho se habla de la arquitectura hexagonal aplicada al front, que en mi opinión, es demasiado rígida en sus principios y no termina de casar con el desarrollo front actual.

Un solo ejemplo de esto, en el desarrollo backend me parece completamente necesaria esa inversión de control que propone ya que es la única forma de poder hacer dobles de pruebas en los tests unitarios; pero el front es un poco distinto y con tecnologías actuales de testing como Jest o Vitest podemos mockear cualquier dependencia sin pagar el coste de un sistema de inyección de dependencias en el front.

Ahora con esto no quiero decir que los frameworks sean malos pero si que se tienen que utilizar donde realmente aportan valor a nuestra aplicación, no en toda ella, haciendo que irremediablemente nos casemos con esa solución.

# Cómo conseguir una arquitectura limpia / evolucionable en el front

La respuesta es sencilla a la par que compleja, tenemos que abstraernos completamente del framework que hayamos seleccionado para montar nuestra aplicación.

Para ello vamos a estructurar nuestra aplicación en dos grandes capas:

- **core**: la cual puede estar implementada con Javascript o Typescript y debe aislar la parte funcional de nuestra aplicación sin tener ninguna relación con el framework, como mucho puede apoyarse en librerías que aporten soluciones especificas como Axios.

- **ui**: será la capa que contenga toda la parte relacionada con el framework en el que nos apoyemos para la presentación de nuestra aplicación y que nos ayudará en la creación de la interfaz gráfica y el router de páginas, entre otras cosas. 

La clave es que la capa "core" sea completamente independiente y que en caso de cambiar el framework solo tengamos que re-implementar la capa de ui.

# Vamos a centrarnos en la capa "core"

En la capa "core" irán los siguientes elementos funcionales (los cuales se pueden estructurar por módulos si desea):

- **model**: va a contener las entidades y value objects que representen el modelo de la aplicación, es muy importante que no estén 100% ligados al API de turno.

- **services**: van a ser clases que tengan funcionalidad transversal a la aplicación, es decir, que sea utilizada en distintos casos de uso o nos den cierta funcionalidad como helpers.

- **usecases**: van a ser clases que reflejen las funcionalidades que la aplicación permite hacer. Se van a caracterizar por tener un único método llamado "execute()" o "run()".

- **repositories**: van a ser las clases encargadas de la conexión con las APIs externas de servidor. Como recomendación personal, estas clases las implemento con Axios por el uso de interceptores y facilidad a la hora del testing en contraposición a solo usar fetch.

- **blocs**: son las clases que hacen de pegamento entre la capa de ui donde está el framework y nuestro core. Mantienen el estado de la aplicación independiente del framework.

La estrategía de testing a seguir en esta capa será probar de forma unitaria los distintos blocs de la aplicación mockeando únicamente la parte de conexión con el servidor, es decir, los métodos de axios. 

Con lo que queda probada el resto de la capa de forma social,  no teniendo que hacer test unitarios de cada elemento a no ser que esto nos ayude en su desarrollo.

Fíjate en el detalle de que está capa puede quedar completamente probada y funcional sin tener que levantar el navegador con el tiempo que eso nos ahorra.

Además es recomendable aplicar TDD para la creación del bloc haciendo que el resto de elementos se vaya autodescubriendo en base a los casos de prueba.

# Y qué hay en la capa de "ui"

Como hemos dicho en la capa de "ui" vamos a tener todo lo relativo a la presentación de nuestra aplicación apoyándonos en el framework seleccionado. 

Los elementos más comunes de esta capa serán:

- **pages**: serán los componentes que estén relacionado con el router de nuestra aplicación.
- **smarts**: son los componentes "inteligentes" que hacen uso de los blocs para conectar con el core. 
- **dumbs**: son los componentes donde se apoyan los "smarts" para crear la interfaz gráfica adecuada a nuestra aplicación.

Dependiendo de la rigidez del framework seleccionado esta estructura de elementos podrá variar significativamente.

Para la parte de testing de esta capa, la recomendación es hacer uso de una tecnología agnóstica al framework que se esté utilizando, como es Cypress.

# Conclusiones

Estructurando de esta forma la aplicación hacemos que sea más evolucionable y tengamos una red de seguridad de tests en ambas capas para no tener miedo a incluir nuevos cambios sean de la naturaleza que sean.

Ninguna de estas ideas son originales, son un batiburrillo de principios y buenas prácticas que actualmente intentamos poner en práctica en nuestros proyectos. 

Ojalá estas ideas a corto plazo se transmitan en las formaciones previas al empleo como son Universidades, Bootcamps, Formación profesional, etc... poniéndolas por encima del conocimiento del framework que en ese momento este moda.

Aplicando estas prácticas nos daremos cuenta de lo poco que aportan los mega-frameworks al front y lo sencillo que se hace estar pegados a los estándares de la web con las ventajas que supone.

Si quieres que haga un workshop empezando de cero con estas ideas, contáctame a través de los comentarios. 

Muchas gracias por llegar hasta aquí :-)

Este es el repo con un ejemplo de puesta en práctica de esta arquitectura con React + TypeScript usando Vite & Vitest: https://github.com/raguilera82/clean-arch-workshop-ts-react