DEV Community

Rubén Aguilera Díaz-Heredero
Rubén Aguilera Díaz-Heredero

Posted on • Updated on

Arquitectura limpia en el front

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

Top comments (12)

Collapse
 
raguilera82 profile image
Rubén Aguilera Díaz-Heredero

Muchas gracias por vuestros comentarios!

He actualizado el artículo con un repo donde se pone en práctica la arquitectura: github.com/raguilera82/clean-arch-...

Espero que sea de valor.

Collapse
 
alextomas80 profile image
Alex Tomás

Suena genial. +1 a ese workshop

Collapse
 
aandresmc profile image
Andrés Felipe Mora Castro • Edited

faltó crear los interface repository y ahi si hacer use de implements asi facilitas la creacion de mocks y de los unitest
te quedaria como:

  • irepository.ts -> i de interface (dice el que se quiere)
  • repository.ts -> implementation donde llama al interface ( dice el como hacerlo)

el usecase recibiria por medio de inyección de dependencias la implementación pero el repository seria de tipo irepository

Collapse
 
claudiaochoa profile image
Claudia O.

Apoyo y suplico el workshop!!
Muchas gracias

Collapse
 
juanitourquiza profile image
juanitourquiza

Seria interesante el workshop

Collapse
 
jotatenerife profile image
JuanJo Yanes

Muy interesante, enhorabuena!

Collapse
 
sturpin profile image
Sergio Turpín

Enhorabuena! Es muy enriquecedor lo que compartes. +1 para el workshop ☺️👍

Collapse
 
marcoalayn profile image
MARCO ALAYN

Me encanta el conocimiento que compartes, El único problema sera convencer al tech lead de seguir estas recomendaciones

Collapse
 
leandro_nnz profile image
Leandro Nuñez

Muy bueno. Gracias.

Collapse
 
wesborland profile image
Marcos Javier Gómez Hollger

Muy buen aporte. ¡Gracias!