¿Se puede hacer una GRAN aplicación con Groovy y Grails?

El que sea necesario responder a esta pregunta significa que todavía existe una imagen bastante distorsionada de Grails. Así que antes de responderla, será necesario saber primero qué es Grails y cómo está hecho, y averiguar por qué es tan común está pregunta.

Grails es un framework de desarrollo para aplicaciones Web creado en Java y Groovy en 2005. Pero también es una herramienta de construcción de proyectos y testing a la vez, que permite, además, añadir plugins desarrollador por terceros. Tiene la peculiaridad de que abarca las tres capas del desarrollo web: acceso a base de datos, capa de negocio y vista. Y para conseguir todo esto en un solo producto, Grails se basa en otros (muchos) frameworks opensource conocidos: principalmente Spring e Hibernate.

La principal característica y que más llama la atención de Grails es que esta diseñado para que programemos las aplicación en Groovy, un lenguaje dinámico con la misma sintaxis que Java, pero que añade muchísimas nuevas funcionalidades, permitiendo programar más con menos código.

Los orígenes

Sin embargo, Grails tiene fama de ser ideal para desarrollar pequeñas aplicaciones, pero para abordar una gran aplicación es mejor usar el stack de Java común hoy en día: Spring + Struts2 + Hibernate. Entonces me pregunto ¿y cuál es la diferencia, si Grails usa Spring + SpringMVC + Hibernate? Y es ahí cuando encontramos la semilla que siembra el temor en todos los arquitectos que se dedican a evaluar herramientas, antes de que los equipos de sus empresas empiecen a usarlas.

Estos arquitectos son los que, hace 10 años, evaluaron los Ejbs, los adoptaron y después se arrepintieron. Los mismos que, con mucha mas cautela, probaron y aceptaron Struts1 hace 8 años, y mejoraron su productividad, tanto que muchos equipos lo siguen usando hoy en día en sus proyectos. Los mismos que aceptaron sabiamente que Spring y Hibernate eran grandes herramientas, y las han convertido en un standard de facto para cualquier desarrollo actual. Y los mismos que tuvieron que descubrir como Struts1 fue una buena idea en su momento, pero que ahora se ha quedado completamente obsoleta, y tienen cada vez mas frameworks a elegir entre Struts2, JSF, SpringMVC, Wicket, Tapestry, Stripes… O entre Hibernate, iBatis, JPA, JDO…

Todos estos arquitectos llevan mucho tiempo, muchos años, probando nuevas herramientas, adoptándolas y desechándolas. Siempre aparece algo mejor, que se define a si mismo como la solución definitiva a todos los problemas. Pero después de tanto tiempo, no hay tanta confianza en las nuevas herramientas. ¿Y por qué? porque siempre requieren tiempo, una curva de aprendizaje. Y son fuentes de nuevos problemas, los problemas propios de la nueva herramienta y de integración con otras. Hasta el punto de que algunas empresas incluso han creado sus propios framework MVC y de persistencia.

Entonces estos arquitectos evalúan Grails, empiezan a programar controladores, prueban la persistencia, usan las vistas y dicen “¡qué fácil!”. Pero descubren que esto es posible porque programan con Groovy, y que Groovy es dinámico. Un lenguaje que resuelve las llamadas a métodos y evalúa las expresiones en tiempo de ejecución, no de compilación. Que no tiene un verdadero control de tipos, que es difícil refactorizar y depurar. Y empiezan a sospechar, claro. Pero cuando descubren que, usando incorrectamente el lenguaje, Groovy puede llegar a ser hasta 60 veces más lento que Java, es cuando Grails se desecha como opción directamente: ¿pero cómo voy a instalar en producción una aplicación que funciona hasta 60 veces más lento que la misma aplicación en Java?

La verdad sobre la velocidad de Groovy

Mi primera respuesta sería “no me importa que la aplicación sea más lenta, si puedo desarrollarla en menos de la mitad de tiempo o con una persona menos en el equipo“. Y es que en el ciclo de vida de desarrollo de un proyecto, tiene mucho más coste una persona más desarrollando, que poner un nuevo nodo en el cluster, ampliar la memoria RAM del hosting, o contratar una segunda máquina para el servidor.

Pero es que esto es falso. Spring, Sitemesh, Hibernate… todas las librerías que usa Grails están creadas 100% con Java. Y casi todo el código propio de Grails también. Veámoslo con números. Quitando las clases de tests, y sin tener en cuenta en qué están desarrolladas las partes más importantes (qué podríamos, y me consta que están en Java), este es el recuento de clases en función del lenguaje en el que están programadas (datos reales obtenidos sobre Grails 1.3.4)

Bauer.avilches:~/Work/Apps/grails-1.3.4/src2$ find . -name *.java|wc -l
    562
Bauer.avilches:~/Work/Apps/grails-1.3.4/src2$ find . -name *.groovy|wc -l
    155

Es decir, solo el 22% del código fuente de Grails está desarrollado en Groovy, el resto es Java auténtico 100%.

Entonces es cuando pensamos “ya, pero ¿y nuestro propio código, acaso no programamos las vistas, los servicios y los controladores en Groovy?“. Si, pero es que esa parte del código es mínima, si lo comparamos con todo el código que se ejecuta y el tiempo que se invierte en resolver una petición. Existe una gran cantidad de agentes intermedios involucrados que consumen mucho más tiempo, como el envío de información a través de la red, tanto la petición http como su respuesta, o el acceso a base de datos u otros servicios externos, desde el acceso a ficheros en disco a servicios web/rest. Y es ahí donde debemos preocuparnos por el rendimiento, no por la velocidad del lenguaje. Si nos preocupa el rendimiento, hay tareas muy concretas que se ha demostrado que funcionan, además de una buena optimización en la base de datos, cachear elementos estáticos, reducir o comprimir los recursos, aumentar el número de hilos, dividir la carga, etc.

Velocidad de ejecución vs. velocidad de desarrollo

Lo único en lo que no debemos escatimar es en la claridad en el lenguaje utilizado. Una mayor claridad significa menor cantidad código, pero mejor escrito. Significa que un nuevo programador se puede incorporar al equipo con el proyecto empezado, entender el código y empezar a trabajar rápidamente. Cada hora que un programador dedica a ponerse al día para entender cómo funciona un proyecto es dinero. Esta claridad, esta reducción de código con mayor funcionalidad, no lo conseguimos solo con Groovy, sino que ya lo llevamos haciendo mucho tiempo con Java.

Porque programamos en Java, ¿verdad? no programamos en C o en ensamblador, cuya velocidad de ejecución es varios ordenes de magnitud superior. No, lo hacemos en Java porque nos ha permitido hacer buenos diseños, usar patrones, nos permite programar de una manera clara, nuestra productividad mejora y somos más rápidos y mejores programando. Un lenguaje de alto nivel es más cercano al humano que a la máquina,es una abstracción que encapsula funcionalidades que alejan a los programadores del hardware. Cada nivel que sube un lenguaje, cada nivel que se aleja de la máquina, se añade más y más código intermedio por detrás. Instrucciones, rutinas, procesos, funciones, librerías, intérpretes, máquinas virtuales, clases, objetos, apis, frameworks. Java es un gran lenguaje de alto nivel, y Groovy lo es más todavía.

Resumiendo, preguntas y respuestas

  • ¿es más lento Groovy que Java? sí, pero solo en cosas muy puntuales.
  • entonces, ¿son verdad todos esos tests que dicen que Groovy es 60 veces más lento que Java? No del todo. Existen muchos benchmark publicados en internet comparando la velocidad entre Groovy y Java, con conclusiones como que Groovy era hasta 60 veces más lento que Java en un código equivalente. En la siguiente presentación que hizo Jochen Theodorou, uno de los líderes de Groovy, en la GR8, nos explica la realidad sobre los microbenchmarks, y como el mismo test, bien y mal diseñado, puede dar resultados muy dispares. Siempre hay que comparar el código más óptimo equivalente entre dos lenguajes, una línea situada dentro o fuera de un bucle puede hacer que una prueba tarde un orden de magnitud más.
  • ¿penaliza la velocidad de respuesta de una petición http? técnicamente, si, pero es despreciable.
  • ¿es siempre Groovy más lento que Java? no, es posible hacer optimizaciones muy simples en nuestro código para incrementar la velocidad.
  • Groovy es un lenguaje dinámico, por lo que hay muchos errores que deberían aparecer en tiempo de compilación y que no salen. Estos errores aparecen después, en tiempo de ejecución, a veces en producción ¿cómo lo evito? esto en realidad es un problema de metodología, no del lenguaje. Pero que sale a la luz cuando usamos lenguajes dinámicos. El verdadero problema es que no existen pruebas unitarias suficientes y hay poca cobertura de código. La solución es hacer más tests, lo cual tiene muchos más beneficios de lo que a simple vista parece. Más información aquí, es un artículo del 2006, pero que sigue vigente hoy en día.
  • ¿Está haciendo algo el equipo de Groovy para incrementar la velocidad? Si, son muy conscientes de ello y están trabajándolo.
  • Si uso Grails ¿estoy obligado a programar todo en Groovy? no, puedes programar en Java si te apetece, o si hay una parte crítica en tu sistema (complejos cálculos matemático, por ejemplo) que necesita el máximo rendimiento, pero tendrás que prescindir de la riqueza del lenguaje que añade Groovy a Java.
  • ¿tiene una curva de aprendizaje Groovy? si, pero si ya conoces Java, es muy pequeña.
  • ¿tiene una curva de aprendizaje Grails? si, pero si ya conoces Spring e Hibernate, es muy pequeña.
  • ¿puedo tener problemas con Grails? si, principalmente los mismos que tendrías al usar Spring e Hibernate. Y algunos nuevos que añade el simple hecho de usar una nueva plataforma, pero nada está exento de errores.
  • Entonces ¿puedo hacer una gran aplicación con Grails? Claro. Si la puedes hacer con Java con las mismas herramientas (Spring + Hibernate), también la puedes hacer con Grails, y además en menos tiempo, gracias a Groovy.

DISCLAIMER: El siguiente artículo apareció el 13 de octubre en el blog corporativo de Paradigma Tecnológico. Como me parece interesante compartirlo y el artículo es mio, lo publico aquí también.