Retrospectiva de un proyecto con ReactJS

Los que seguís este blog desde hace tiempo sabéis que me gusta ir comentando cómo evolucionan mis preferencias a la hora de desarrollar software y que no suelo tener problema en admitir cómo éstas cambian con el tiempo. Hace tiempo escribí sobre cómo había ido mi primer proyecto serio con AngularJS y, unos meses después, que era lo que empezaba a no gustarme de ese AngularJS.

Como era de esperar viendo todos los posts que he escrito sobre ReactJS recientemente, nuestra última aplicación web la hemos desarrollado con esta librería y, ahora que acabamos de liberar la primera versión, es el momento de hacer un pequeño balance.

Antes de entrar en materia, me gustaría dejar claras un par de cosas.

Este post trata sobre las experiencias de un equipo concreto desarrollando una aplicación concreta, por lo que puede que tu caso sea completamente diferente. Además, todavía es pronto para conocer las implicaciones a medio plazo del uso de ReactJS, por ejemplo a nivel de mantenimiento de la aplicación; ya llegará el momento de escribir ese post dentro de unos meses.

Puede parecer que esto se trata de un AngularJS vs ReactJS, y en cierto modo es así puesto que son los dos estilos que conozco de primera mano. Aunque ReactJS y AngularJS tengan objetivos distintos y no sean comparables, lo cierto es que el uso de uno u otro afecta directamente a la forma de trabajar y eso sí es comparable.

Los componentes básicos

Toda la aplicación la hemos organizado alrededor del uso de librerías independientes, en contraposición a usar un framework «todo incluido» como AngularJS o Durandal. La librería básica ha sido ReactJS, pero también hemos usado jQuery (muy poco, la verdad) y lodash para hacer más soportable el uso de Javascript.

Para orquestar la «compilación» de la aplicación, que sigue una organización basada en features, hemos utilizado grunt con browserify y las react-tools, además de algún minificador de css, mocha para tests unitarios y nightwatch para tests de extremo a extremo.

En el aspecto visual, acabamos descartando el uso de frameworks css porque necesitábamos un layout un poco extraño, basado en columnas css con scroll horizontal y, pese a nuestro escaso talento para el diseño gráfico, resultaba más fácil hacerlo a mano que convencer a Bootstrap o alguno de sus amigos de hacerlo por nosotros.

Las partes malas

Antes de empezar a glosar las bondades de nuestra solución y lo listos que somos por haberla empleado (ejem), creo que es más honesto ver los puntos que han resultado más complicados, incómodos, o costosos, que también los ha habido.

Lo primero que hay que tener en cuenta cuando se opta por una solución de estas características, basada en librerías independientes, es que vas a necesitar dedicarle algo de tiempo a coordinar todas estas librerías, decidir cómo «compilarlas», «modularizarlas» y demás. En nuestro caso, eso supuso aproximadamente una semana de experimentos hasta que encontramos un flujo de trabajo que nos resultara cómodo.

La parte más complicada, sin duda, fue el montaje de los tests de extremo a extremo con nightwatch. Con AngularJS acabamos un poco hartos de karma y nos acabamos pasando a protractor, que tampoco es que fuera una maravilla, pero al menos el montaje fue mucho más sencillo que con nightwatch.

Otro factor a considerar es el uso de JSX para generar las vistas. Al quedar tan mezclado el JSX usado para generar el Virtual DOM con el código Javascript usado para coordinar los componentes, hay que ser cuidadoso para que aquello no acabe siendo un lío mezclando lógica de presentación y lógica de negocio.

Ha habido momentos en los que nos ha tocado refactorizar código que empezaba a ser demasiado complicado en algún componente, o en los que empezábamos a tener código duplicado en varios componentes sin darnos cuenta. Al ser tan sencillo añadir nuevo comportamiento a un componente, es fácil que se te vaya de las manos.

El uso de JSX tiene otro efecto, no tan importante, pero que también puede resultar molesto, y es el uso de herramientas para trabajar con él. Aunque sólo sea para colorear la sintaxis e indentarlo correctamente, hay que hacer algunos ajustes. Al final hemos acabado con distintas soluciones, algunos utilizando WebStorm, otros Sublime y otros emacs.

Las partes buenas

Sin duda, lo mejor de utilizar ReactJS es la naturalidad con la que se hace todo.

Seguramente sea por el uso de JSX, que sí, que como mencionaba antes tiene sus riesgos, pero permite una cohesión mucho mayor del código en los componentes. En AngularJS cuando querías reutilizar un componente usando una directiva o un controller, generalmente acababas saltando entre dos ficheros, el que contenía la plantilla de HTML y el que contenía el código en Javascript, y eso hacía que fuese mucho más incómodo trabajar.

La gestión del ciclo de vida del componente, con sus componentDidMount, componentWillUnmount, etc., resulta muy intuitiva y decidir dónde y cuándo hay que hacer las cosas suele ser bastante directo.

También ayuda mucho la separación entre información mutable e inmutable. Simplifica mucho la forma de razonar sobre los componentes, sobre todo si lo comparamos con el sistema de scopes anidados/aislados/clonados de AngularJS, que resultaba especialmente complejo.

Gracias a que es más sencillo razonar sobre los componentes, en parte por la mayor cohesión entre el código Javascript y el DOM (JSX), y en parte por la inmutabilidad, hemos podido partir la aplicación en componentes más pequeños, reutilizables y simples.

Los componentes nos han permitido aplicar un patrón más parecido a MVP que a MVVM. Sin entrar en flame wars, siempre me ha parecido que ese patrón aportaba una mejor separación de responsabilidades y, fundamentalmente, hacía que fuese más sencillo razonar sobre la aplicación.

Al final los componentes que representan «pantallas» de la aplicación acaban haciendo una labor «doble» de Vista y Presenter, siendo la vista el método render y el resto del código del componente haciendo las veces de Presenter.

Que no haya una separación mayor (todo está en el mismo objeto) es algo que reconozco que me pone un poco nervioso. Si lo piensas fríamente (y eres un poco disciplinado), al final no importa tanto en qué objeto se encuentre cada cosa sino la forma en que interactúan. De todas formas no descarto que en un futuro acabemos separándolo.

En cualquier caso, toda la lógica de negocio queda siempre fuera del componente en otros módulos o funciones, y que se acoplen vista y presenter tampoco es tan grave (en realidad siempre lo van a estar aunque no queramos aceptarlo).

Una parte que pensé que echaría más de menos es el sistema de módulos e inyección de dependencias de AngularJS, pero la verdad es que con browserify para poder modularizar la aplicación esto no ha sido nada problemático.

Supongo que si hubiésemos querido escribir más tests unitarios con mocks lo hubiéramos notado más, pero como nuestra política desde hace tiempo es aislar la lógica de la interacción para facilitar los tests, esto no ha sido un problema.

Una ventaja adicional de utilizar browserify es que facilita la experiencia de depuración. Puedes utilizar todas las versiones completas de las librerías (sin minificar) durante el desarrollo y, en la fase de compilación, browserificarlas junto con tu aplicación y minificarlo todo junto.

Eso se supone que ayudaría también al rendimiento porque tendrías automáticamente un bundle con todo tu Javascript, pero ahora mismo es algo que en nuestro caso no nos preocupa mucho. De hecho, una de las teóricas ventajas de ReactJS, su rendimiento, para nosotros es poco importante. Tampoco tuvimos problemas de rendimiento con AngularJS pese a la mala fama que tiene a veces.

Conclusiones

Utilizar ReactJS en una aplicación real requiere un esfuero adicional con respecto a otras soluciones porque necesitas buscar soluciones para todas las cosas que no cubre la librería.

Que esto merezca la pena o no, es una cuestión difícil de responder y depende mucho de las circunstancias de cada uno. A mi personalmente me deja más tranquilo tener más grados de libertad y elección en el futuro si quiero cambiar alguna parte, pero esto no es gratis.

Si tuviera que definir cómo ha sido la experiencia de trabajar con ReactJS en una sola palabra sería divertido. Está todo tan al alcance de la mano y es todo tan directo, sin tener que dar vueltas entre capas y capas de abstracción, que trabajar con ReactJS resulta muy placentero.

Lo que más me preocupa a medio plazo, y posiblemente venga derivado de eso, es que los componentes se puedan acabar convirtiendo en monstruos complejos llenas de casos límite para tratar con el DOM. Si llega ese punto, como decía antes, mi plan consiste en extraer más lógica de los componentes (lo que sería el Presenter) para generar una separación mayor.

6 comentarios en “Retrospectiva de un proyecto con ReactJS

  1. Juan, tu blog esta buenisimo. Hice algunos trabajos con Angular y actualmente me interesa trabajar con ReactJS.
    Cuales son las librerias (si es que usas) para complemententar a ReactJS en cuanto al ruteo de las vistas, las peticiones ajax, etc?

  2. Gracias por la respuesta Juan. Voy a tener en cuenta react-router, para el routeo, ademas pensaba integrar browserify con los modulos que te permite usar en el browser como http, stream, etc. Veremos que sale.

  3. Yo uso browserify, y después de haber usado el sistema de módulos de angular (aunque no sirvan exactamente para lo mismo), me quedo con browserify.

    No te da la parte de inyección de dependencias, pero la estructura de código queda más clara y te ahorras todo el jaleo de services, providers y factories que, sinceramente, muchas veces introduce una complejidad que no necesitas.

  4. Jose Ubaldo Carvajal dijo:

    Excelente Post, me gusta mucho la objetividad con la que abordas el tema. Una de mis preocupaciones con RactJS, es precisamente toda la parafernalia que toca armar a mano para que se integre a la librería y así tener una solución completa, con una buena arquitectura y bien estructura, por un lado es reinventar la rueda, ya que los patrones para estos problemas existen y por otro lado es la posibilidad de tener la libertad de elegir y cambiar algún aspecto del proyecto, siempre va a depender de la mirada que se le dé. He visto algunos esquemas de trabajo con Flux por ejemplo para estructurar bien tu aplicación Patrones de arquitectura para Front-end con Flux y ReactJS.

    Lo cierto es que el trabajo de estructurar bien una SPA, no es para todo el mundo, necesitas un bagaje y unas habilidades que vienen con el tiempo.

    Excelente Post y el contenido de tu blog es definitivamente un muy buen referente para quienes queremos hacer las cosas mejor.

  5. Hola José,

    Coincido en lo que comentas, si no tienes unos ciertos conocimientos, utilizar soluciones «todo incluido» puede ayudarte a estructurar una solución más coherente.

    Muchas gracias por el enlace y el comentario!

Comentarios cerrados.