Por qué ruby on rails

Una de las primeras decisiones a la hora de comenzar a desarrollar una aplicación web es qué tecnología utilizar. En ASPgems actualmente trabajamos básicamente con dos tecnologías: Drupal y Ruby on Rails, aunque también hemos desarrollado aplicaciones con NodeJS. Muchas veces nos preguntan por qué Ruby on Rails, así que en este post, y en otros sucesivos, voy a intentar explicar por qué seguimos pensando que Ruby on Rails es la tecnología que mejor se ajusta, en la mayoría de los casos, al desarrollo web que solemos hacer nosotros. Pero para entender esta decisión, primero hay que entender (y asumir) una serie de hechos.

El contexto

Sólo sé que no sé nada

En ASPgems llevamos varios años desarrollando productos para clientes, a los que se suman los que cada miembro de nuestro equipo ha acumulado a lo largo de su experiencia profesional. Y una cosa hemos aprendido: cuando tenemos una idea y queremos implementarla, en realidad no sabemos lo que queremos tan bien como nos creemos. Lo que tenemos es una idea aproximada de lo que queremos en nuestra cabeza. Da igual lo seguros que estemos, siempre hay cosas en las que no hemos pensado, casos que se nos han escapado o, simplemente conceptos erróneos. Y no pasa nada por ello. Nos pasa a todos. La diferencia radica en si somos conscientes de ello… o no. Hay que tener en cuenta que el ejercicio de trasladar una idea al mundo real posiblemente sea de los más difíciles que hacemos los seres humanos. Así que el primer paso que tenemos que hacer es asumir, que en el mejor de los casos lo que tengo es una idea aproximada de lo que realmente quiero, y que lo que tengo que hacer es ir aprendiendo en el proceso mismo de la construcción de nuestra idea.

No estamos solos

Para bien y para mal no estamos solos en este mundo. Bien porque esto supone que hay muchos usuarios potenciales de nuestra aplicación, mal porque supone también que hay muchos competidores ahí fuera y que es razonable asumir que, si yo he tenido una idea, otro más la habrá tenido también. Y aquí es cuando la carrera empieza y la carrera consiste no tanto en sacar el mejor producto posible, sino en ser el primero en sacarlo… aunque no esté al 100% (¿os suenan todas esas aplicaciones en modo beta?). Así que cuando invertimos en un proyecto nuevo, un factor importantísimo, si no el más importante (en cuanto a desarrollo se refiere) es el time to market. Queremos salir cuanto antes, porque si no… otro lo hará y adquirirá una ventaja competitiva con respecto a nosotros muy difícil de superar.

Abrazando la incertidumbre

Vivimos en un mundo incierto. Tan incierto que no sabemos si mañana nuestro dinero va a valer más o menos, tan incierto que un contrato fijo hoy en día no te asegura que mañana sigas teniendo trabajo. Tan incierto como que por mucho plan de negocio que hagas, no sabes cómo va a salir: sólo vas a saber cuánto se ha desviado de tus previsiones. Así que no nos queda más remedio que asumir esta incertidumbre y abrazarla. Tenemos que aprender a vivir con ella, la vida es así. Y como el mundo es incierto, tenemos que estar preparados para adaptarnos lo más rápidamente posible a los cambios que se nos vengan encima.

El coste del error

Así que resulta que no sé lo que quiero, que tengo que aprender y que encima tengo que ir con prisas. Esto me suena como a que me voy a equivocar muchas veces. Efectivamente. Los seres humanos nos equivocamos por definición (la historia así lo demuestra). Lo único que podemos hacer es minimizar el coste de los errores en los que incurramos.

Por un lado, nos podemos apoyar en la experiencia. Si ya he intentado poner en marcha varios proyectos, seguro que he aprendido muchas cosas en el camino. Cosas que no se enseñan en ningún MBA. Cosas que se aprenden haciendo… y fallando. Si no tienes experiencia, apóyate en alguien que la tenga: proveedores, inversores, socios…

Por otro lado, ten una forma de trabajar que te permita detectar pronto los errores y que te facilite subsanarlos. No quiero entrar en temas metodológicos, que daría para muchos posts, pero tampoco quiero pasar por este punto sin dar un pequeño consejo: la forma tradicional de enfocar proyectos, esas planificaciones, esas capturas de requisitos, y esos diagramas de Gantt… no funcionan. No estamos mandando un cohete a la luna, ni estamos construyendo una red de ferrocarriles de alta velocidad. Lo único que vas a conseguir con estas metodologías es salir tarde… y mal. Tú caja de herramientas debería estar basada en metodologías ágiles.

¿Y dónde entra Rails en todo esto?

Recapitulemos: hemos dicho que no conocemos realmente lo que queremos poner en marcha (en serio, hay que asumirlo), que el contexto es muy cambiante y que estamos obligados a adaptarnos, que tenemos competidores y que eso nos obliga a correr, y que nos vamos a equivocar y que hay que minimizar el coste de estos errores. Al final todo esto se traduce en una realidad a la hora de desarrollar: tenemos que ser capaces de desarrollar rápido y de realizar cambios en nuestro código de forma rápida y fácil.

Y es aquí donde rails nos encaja como anillo al dedo en la mayoría de los proyectos que requieren una aplicación web. Con esto no quiero decir que no haya alternativas, o que haya particularidades en determinados proyectos que hagan que haya alternativas mejores a rails (puede que en otro post me explaye más sobre este tema).

Metodologías ágiles

Rails nace, desde el primer momento, enfocado hacia las metodologías ágiles. Desde el primer día, y ya hace de eso casi 10 años. 10 años caminando de la mano del desarrollo ágil. 10 años en los que la comunidad ha aprendido, ha corregido errores, y ha ido incorporando nuevas herramientas para que esto siga siendo así.

Convención sobre configuración

Todavía recuerdo mis tiempos en los que desallorraba con tecnologías J2EE. Y todavía recuerdo, porque era muy doloroso, todo el tiempo que tenía que invertir en configurar un proyecto. Esto incide directamente en la productividad: cada vez que tengo que preocuparme de la configuración del proyecto estoy dejando de invertir tiempo en el desarrollo en lo que realmente me importa: mi lógica de negocio.

Con Ruby on Rails esto se minimiza mucho puesto que es un framework con opinión en el que, aunque tienes la posibilidad de personalizarlo como tú prefieras, viene ya con unas formas definidas de trabajar, que va a permitir dos cosas: evitar preocuparme de la configuración del proyecto, que cualquier desarrollador que llegue nuevo al proyecto va a conocer la estructura del proyecto. De esta forma se maximiza la productividad de un desarrollador y se minimiza el aterrizaje en los proyectos por parte de nuevos desarrolladores.

Y no sólo estamos hablando de configuración del proyecto, sino que rails también asume una serie de prácticas como el nombrado de clases, tablas en base de datos, controladores, etc. Esto hace que si seguimos sus reglas, haremos nuestro código mucho más centrado en la esencia y nos ahorraremos la dichosa ceremonia.

Modificación del modelo de datos

Los que llevamos tiempo desarrollando aplicaciones web con bases de datos relacionales (MySQL, PostgreSQL, etc.) sabemos el esfuerzo de trabajo y coordinación que hay que hacer cuando se modifica el modelo de datos. Normalmente tenemos que solicitar los cambios a un DBA, y tendré que cambiar los DAOs, POJOs y demás beans de turno (hablando en java) acorde a dichos cambios del esquema.

Esto me lo resuelve de forma espectacular ActiveRecord, un (anti?)patrón de diseño, y que es el ORM por defecto que viene con Rails. Gracias a la metaprogramación que me ofrece ruby, mi clase es lo suficientemente lista como para saber que si tengo una columna llamada name, en una tabla llamada users, mi modelo asociado (el modelo User) tendrá automáticamente los métodos name y name= funcionando sin haber tenido que escribir una sola línea de código.

Y no sólo eso, sino que además, todas las asociaciones entre mis modelos se definen en una sola línea utilizando las macros que me ofrece Rails, de forma que todas esas tediosas sentencias SQL las tengo disponibles desde el principio sin tener que haber escrito ni una sola consulta SQL.

Sobrearquitecturar

En una estructura tradicional, normalmente tendremos unos DAOs para el acceso a base de datos, unos POJOs para ir moviendo datos a lo largo de la aplicación, unos objetos de servicio para realizar la lógica de la aplicación… Sin embargo en ruby on rails, como he contado más arriba, contamos con ActiveRecord. ActiveRecord hace que el acceso a la base de datos y la lógica de negocio convivan en una misma clase. Esto puede parecer que va en contra de todo lo que hemos aprendido de los principios SOLID de programación. ¿Lógica y acceso a datos en una misma clase? Pues sí. Va directamente en contra del principio de única responsabilidad. Pero claro, estamos diciendo que necesitamos velocidad de desarrollo y posibilidad de introducir cambios en nuestro código de forma rápida y fácil, y resulta que ActiveRecord nos da justo esto: en lugar de tener que definir dos o más capas de abstracción para el tratamiento de datos, tenemos sólo una y con una cantidad mínima de código. Esto quiere decir que tengo que escribir mucho menos código (aumento la velocidad de desarrollo) y que si cambia el modelo de datos, sólo me tengo que preocupar de cambiar la lógica de negocio asociada a dichos cambios y me ahorro tener que modificar todos los accesores de mi clase (facilidad de introducción de cambios).

El problema de utilizar una arquitectura «de manual», en un proyecto nuevo es que de alguna forma estamos sobrearquitecturando. El proyecto en sus inicios no tiene un tamaño suficiente que justifique una arquitectura tan grande con tres capas para el uso de datos, y esto quiere decir que no estaremos optimizando los recursos de los que disponemos (hola, inversores).

Sin embargo, hay que ser justos y decir que, como todo gran poder, ActiveRecord conlleva una gran responsabilidad, y hay que vigilar que nuestros modelos no crezcan demasiado, puesto que entonces tendremos el problema contrario, un defecto de arquitectura, que incide directamente en el mantenimiento y en el desarrollo evolutivo de nuestra aplicación.

Idealmente, llegará un momento en nuestra aplicación en el que iremos cambiando de arquitectura y nos alejaremos de la que propone rails en un principio. Bendito problema: esto quiere decir que nuestra aplicación está creciendo, que está teniendo éxito y que seremos capaces de ir cambiando a una arquitectura que se ajuste mucho más a las necesidades particulares de nuestro proyecto. Rails nos habrá evitado pensar en arquitectura hasta que realmente sea necesario hacerlo.

Salvedades

Todo esto que he comentado es válido, en mi experiencia, para el 90% de aplicaciones web. Como siempre, hay proyectos que tienen unos requerimientos en los que creo que sería mejor utilizar otros lenguajes y/o frameworks

Tiempos de respuesta muy bajos

Si estamos hablando de que el tiempo de respuesta de página tiene que estar por debajo de los 300 ms, rails, debido a que se apoya en ruby, no sería la mejor de las alternativas. Habría que ver otros requisitos como el número de peticiones por segundo, la necesidad de tener los datos actualizados en tiempo real, etc. pero a priori es una bandera que requeriría, cuanto menos, valorar otras opciones. Cuando nos hemos enfrentado a proyectos con estas necesidades, hemos optado por utilizar NodeJS.

Estamos rehaciendo un proyecto grande que sabemos que funciona (y no está hecho en rails)

Si lo que estamos es haciendo una reescritura total o parcial de una aplicación más o menos grande y que sabemos que funciona, es decir, se están cumpliendo los objetivos de negocio, entonces no merece la pena utilizar rails porque normalmente esta necesidad de reimplementar algo que ya funciona, responde a que la aplicación necesita una arquitectura mucho más personalizada, y seguramente haya que alejarse de la arquitectura monolítica que propone rails. En estos casos, normalmente suele ser buena idea cambiar a una arquitectura de microservicios, utilzando la tecnología más adecuada para cada uno de los microservicios (en ruby tenemos sinatra, por ejemplo).

No estamos desarrollando una aplicación web, con un patrón MVC clásico

Tampoco utilizaríamos un martillo para cortar jamón, ¿o sí? 😉