4Trabes Historias de una empresa en 100 metros cuadrados

El blog de Trabe Soluciones

Trabe, Ruby, Rails y el hip-hop

| | Comentarios

Este post va dedicado: al hombre detrás de Jasypt para que no me diga que lee el blog pero no entiende nada.

Ya casi llevamos dos años de Trabe, así que los balances, las miradas atrás, las lecciones aprendidas, etc. comienzan a cobrar un poco de sentido. Todavía somos una empresa joven (muy joven, dirán algunos) pero el tiempo es inexorable y ya ha transcurrido suficiente como para que empiecen a notarse los “posos” que la experiencia va dejando acumulados.

Creo que lo que más ha marcado estos dos años a nivel tecnológico ha sido el uso de Rails como framework de desarrollo web. Como ya hemos dicho otras veces (creo recordar), y como siempre decimos en nuestras escasas charlas y ponencias, somos muy poco dogmáticos a la hora de utilizar tecnologías, de modo que todo lo que diga a continuación no se debería interpretar como una loa a Rails, ni mucho menos como una muestra de desprecio hacia otros frameworks. Son sólo una serie de pensamientos, incluso no demasiado meditados :P, pero aquí los dejo de todas formas.

Trabe y Rails

Lo primero que pensé cuando vi por primera vez código Rails (es decir, Ruby), antes de que montaramos la empresa, fue algo así como “¿qué demonios…?”. Por aquel entonces estaba trabajando con las primeras versiones de Monorail y quería saber de donde había sacado el amigo Hammet su inspiración. Lo vi y me volví rápidamente al confortable mundo de los lenguajes compilados (aunque fuese un mundo .NET), eso sí, con la sensación de que, aunque por aquel entonces no entendiese nada, algo bueno tenía que haber en todo eso de Rails, porque Monorail era realmente bueno.

Cuando montamos la empresa todos teníamos experiencia en el desarrollo de aplicaciones web con frameworks “tradicionales” como Struts o ASP.NET y sabíamos, porque los habíamos sufrido en nuestras carnes, cuáles eran sus problemas; así que decidimos darle una oportunidad a Rails. Empezamos desarrollando nuestra propia Intranet y un pequeño proyecto de comercio electrónico, y una vez comprobamos que realmente era posible utilizar Rails (y que éramos capaces, que es algo que hay que comprobar y demostrarse a uno mismo, y que mucha gente parece obviar) empezamos a ofrecerlo como solución a nuestros clientes.

Desde esos inicios hemos montado desde pequeñas webs casi estáticas hasta una completa (y compleja) solución de comercio electrónico, sufriendo las carencias y problemas de Rails (aquí nadie se libra, amigos) y disfrutando de sus muchas ventajas.

Rails y Ruby

Y es que, si bien Rails es un framework al que se puede acusar de muchas cosas, cuenta con una ventaja sobre muchos de sus competidores: está escrito en Ruby. Y es que Ruby es un lenguaje realmente peculiar (supongo que en realidad es muy parecido a muchos otros, pero mi experiencia con lenguajes dinámicos no es muy amplia, así que tendréis que disculparme). Es peculiar, decía, porque, aunque al principio resulta complicado de entender, una vez te acostumbras permite escribir de manera terriblemente compacta pero a un tiempo perfectamente clara algunas construcciones que en otros lenguajes necesitan diez veces más líneas y cinco veces más llaves, paréntesis y puntos y coma.

Así, lo compacto de Ruby, unido a las buenas ideas que el señor DHH aplicó en Rails, dan como resultado un framework que permite desarrollar realmente rápido, sin la sensación de pesadez, lentitud y “mamotretismo” (disculpas por la palabrilla) que son inherentes a otras opciones (léase en este caso, si así se desea, Struts).

Rails, Ruby y el hip-hop

Este es un símil que surgió hace un par de semanas por Trabe:

RubyOnRails es como el hip-hop

No sé muy bien a cuento de qué venía, pero sí sé cuál es su sentido: muchas veces, la sensación al desarrollar con Rails es la de estar encadenando rimas. La base del tema son esas tareas repetitivas a las que al final se reduce el 80% de cada aplicación, ese continuo leer datos, mostrar datos, modificar datos, repetido una y otra vez. Y sobre esa base, Rails – gracias principalmente a Ruby – permite escribir código con flow. Mientras que con otros frameworks tienes la sensación de estar en un monasterio entonando un canto gregoriano (que no digo que no sea bonito, pero a veces se hace lento, repetitivo y pesado), con Rails tienes la sensación de estar rimando, fluyendo sobre la base, buscando la estructura que mejor se ajusta a cada nuevo problema. Y, como en el rap, dices mucho en poco espacio, mientras que hace falta mucho tiempo de canto gregoriano para cantar unas pocas frases.

Y es que puede que el hip-hop no tenga la solera del canto gregoriano, pero no se puede negar que tiene ritmo :D.

Trabe, Ruby, Rails y el hip-hop

Resumiendo, que en Trabe nos gusta Rails (a unos más que a otros, eso sí), que nos gusta el estilo que imprime al desarrollo. Y que también nos gusta el hip-hop (de nuevo, a unos más que a otros :).

Y termino, como no podía ser de otra manera, con una cita de SFDK, extraída del tema Mi nombre es rap, de su nuevo álbum Los Veteranos:

La lengua se me afila
ve y cuéntale a tus amigas que has conocido al rap
que ya conoces mi nombre de pila

Listo.

Lo sentimos, pero los comentarios están cerrados

El hombre detrás de Jasypt :-P os agradece la dedicatoria y acto seguido afirma lo siguiente, a tener en cuenta por generaciones venideras:

1. Me alegro de que os guste Rails. Yo como no lo he probado, no puedo opinar y esperar que se me tenga en cuenta… quizás algún día. O no. Ya sabéis que yo aplico eso de que quien mucho abarca…

2. A un dinosaurio como yo, totalmente abducido por el mundo Java, entenderéis que afirmaciones como “Rails no necesita control de concurrencia, porque lo que hace es usar un servidor diferente por petición”, como poco hace que se le atragante el desayuno tres veces.

3. No os preocupéis por (2), seguro que algún día soy capaz de explicarme a mí mismo por qué la gente es feliz con Rails pese a que le pasen ese tipo de cosas.

4. Lo del hip-hop no es que tengáis vena poética, sino simplemente que sois un poco horteras :-P, pero yo os quiero igual…

¡Salud!
Dani.

12/Feb/2008 Dani

Me alegro de que te alegres de lo que te alegras. La alegría es buena. Por otra parte, 1, 2 y 3 me parecen bien, pero por 4 no puedo pasar… ¿horteras? ¿y me lo dice el hombre del polo color pistacho nuclear? No me lo puedo creer XD

12/Feb/2008 Asís

Tranquilo Dani, yo te explico 2).

Si tu servidor web al arrancar no fagocita 100 millones de megas de memoria y el 99.9% de tu CPU, y se mantiene en unos números razonables, puedes lanzar varias instancias y quedarte tan tranquilo, ya que el resultado final va a ser lo mismo. Tu código será más sencillo, y tú serás más feliz.

Cuando despliegas aplicaciones Rails te apoyas muyo más en los servicios que ofrece el operativo: cron, logrotate, etc, etc, y menos en los servicios del contenedor.

¡Ah! Y ya sabes que aquí en Trabe estamos deseando ayudar a evolucionar a un dinosaurio de tu valía. ¿Cuándo vienes a currar con nosotros?

13/Feb/2008 David

Aja, vale. Pero no me has explicado nada, sólo me lo has descrito más en profundidad.

A ver, a primer golpe de cerebro, se me ocurren dos cuestiones:

Da ferst
—————-

Si cada petición tiene un proceso aparte, y no hay un espacio de datos compartido, eso significa que si tengo a 10 usuarios pidiéndome la misma cosa al mismo tiempo (tan solapados como queráis), tendré 10 procesos haciendo 10 consultas iguales a la base de datos, metiendo 10 veces los mismos datos en 10 lugares diferentes de memoria, y generando 10 veces el mismo interfaz para devolver esos datos. No digo que el servidor no sea ligero, pero muy muy óptimo no parece…

En todo caso, no me importa. Lo que sí me importa es que tal arquitectura me impide usar cualquier tipo de caché en el servidor de aplicaciones, ya sea a nivel de sesión o a nivel de aplicación (a no ser que meta la caché en ficheros del S.O., claro, y el sistema de archivos es no-transaccional, con lo cual, mogollón de miedo).

De modo que cada vez que quiera un dato lo tendré que pedir, y me veré limitado por la rapidez de la BD. Lo cual en muchas aplicaciones es una parida, porque al fin y al cabo los SGBD son rápidos y la latencia de comunicación SGBD-Servidor de Aplicaciones no es gran cosa… siempre que mi modelo de datos sea sencillo, mis queries sean bastante tontas, mi pool de conexiones sea ampliamente abundante y a mi SGBD (o al DBA que lo gestiona) le haga puñetera gracia que lo achicharre a consultas como nunca había visto antes (salvo que trabaje para cierta empresa que todos sabemos xD).

Bueno, pues no digo que no haya aplicaciones que sean así, sí… y bastantes… pero como modelo general para aplicaciones web “de empresa” tiene un problema gordo: no escala. Una aplicación muy tonta será “bastante” óptima con esto, pero una aplicación complicada no será “poco óptima”, sino “infernalmente poco óptima”… en cuanto pases la barrera de “el tiempo total de consulta a SGBD es despreciable”, la oscuridad se cernirá sobre ti.

Todo depende del tipo de aplicaciones que hagas. A mí en las que he hecho últimamente (excepto quizás en una) ni se me ocurriría prescindir de una caché de nivel de aplicación, vamos… me muero (si no me mata el cliente).

Ojo: y no hablo de cachear “páginas”, sino de cachear “datos”, que puedan ser necesitados por multitud de procesos en nuestra lógica de negocio.

Da second
———————-

Si un proceso me atiende a una petición y el espacio de datos no está compartido… hmmm… hmmm… ¿qué pasa con las tareas asíncronas?

Quiero decir: si tengo que hacer un envío de email, o si tengo que generar un informe que tarde lo suyo y que no deje esperando al usuario, o si quiero lanzar una tarea que me actualice lo que sea en la BD cada x miércoles a las 9:30… ¿cómo puedo hacerlo? Si me dices que Rails usa el cron por debajo, intuyo que sí podrá lanzar tareas programadas pero… ¿puedo hacerlo también desde la lógica de negocio? ¿y cómo comunico mi lógica síncrona con la asíncrona, si no hay espacio de datos compartido? ¿sólo a través de la BD? :-|…

Saludos,
Dani.

13/Feb/2008 Dani

Veamos Dani. Sin estar en desacuerdo con lo que dices, que me parece todo, como de costumbre, muy razonable y razonado, insisto en que tienes que cambiar el chip para entender como trabajamos con Rails.

=About da first thing

Efectivamente. Tienes las cosas repetidas. Igual de repetidas que si lanzas 10 threads en un proceso en lugar de diez proceso mono thread. Cada thread tiene su espacio de memoria y eso es lo que se usa. Cada hilo genera su salida, etc, etc. Si entramos a hablar de datos compartidos como cachés (que entiendo es lo que más te extraña). Una vez más te pido que cambies el chip. ¿Por qué tienes que tener la caché dentro del servidor de aplicaciones? ¿Acaso no puedes usar una caché externa?. Con Rails la gente usa memcached (ejemplo patrio, la Coctelera). Y la caché en disco también vale para muchas cosas (caching de páginas enteras en disco que tu servidor web sirve sin que el servidor de aplicaciones se inmute).
¿Qué pasa en Java cuando tienes más de un servidor? Parecido, ¿no?

Respecto a temas de rendimiento y demás, uff, eso es terreno pantanoso, y tú lo sabes. Eso hay que medirlo en la vida real. Hablas del cuello de botella de la BD, pero entendámonos, la BD ya tiene caché y muchas veces por exceso de celo se cachean esos datos en la aplicación otra vez (y peor). Además, también puedes replicar las BD (maestra-esclavos, escribimos en una y leemos de todas).

Puedes decirme que el despliegue es más complejo, cierto, pero añadir más hardware es sencillo.

=About da second

Lo que quise decir es que en lugar de lanzar un hilo que ande bailando la conga por ahí (cuyo ciclo de vida te ves obligado a gestionar) puedes llamar a una tarea cron periódica que haga exactamente lo mismo. Si eso te trauma, no te preocupes, existen librerías para tener procesos en background a la “classic enterprise” ;). Ruby es un lenguaje con soporte para threads (en las versiones nuevas también soporta fibers) y puedes escribir tanto código de sincronización como te plazca.

Respecto a comunicar lógica síncrona y asíncrona, puedes usar el espacio de datos compartido que más te apetezca/convenga, una BD, un servicio web,…

= Otras opciones posibles

MERB, que es otro framework ruby que sí es multihilo. De hecho el servidor que usamos (mongrel) es multihilo pero es Rails el que “sincroniza” por petición.

= Seguro que me dejo algo sin contestar

Y es normal, porque a base de comentarios de blog es difícil entendernos. Terminaré con un par de comentarios:
- Yo no digo que Rails sea mejor o peor que Java absolutamente, pero para según que cosas me gusta más.
- Deberías mirar Jruby. Puedes usar Rails con todo tu backend J2EE.
- Deberías dejar de usar el concepto aplicación “empresarial” para exponer tu punto de vista. Apesta. (“Enterprise is not a 4 letters word”, RailsConf 2007 ;)
- El rendimiento no es el punto clave en esta discusión: ¿Te parece que Twitter es una aplicación con poca carga? ¿Crees que Basecamp es una patata?.
- Échale un vistazo a Rails. Sólo por ver como es. No para usarlo. Échale un vistazo a .Net. Échale un vistazo a Python si hace falta. No hace falta que los domines y dejes Java, pero como dicen Dave Thomas y Andy Hunt en the Pragmatic Programmer: aprende un lenguaje cada año para cambiar tu enfoque. Si aprendes OO programarás en C de manera distinta.

Cuando quieras quedamos, nos tomamos un café y seguimos el debate :)

14/Feb/2008 David