Profundizando en Javascript, parte 1: funciones para todo

Javascript es un lenguaje que todos los programadores web creemos dominar. Da igual si programas en Php, Java o .Net: antes o después has tenido que hacer algo con Javascript. Y encima los que programamos en Java tenemos una pequeña ventaja añadida: que Javascript y Java comparten una sintaxix extremadamente parecida, lo cual lo hace todavía más sencillo, aparentemente, claro, porque solo se parecen en la sintaxis y nada más.

Así que dado el poco alcance (también aparentemente) que tiene Javascript, limitado normalmente al navegador (aunque hay excepciones), es poco usual profundizar en este lenguaje. Digamos que no merece la pena invertir tiempo en conocerlo a fondo, si lo comparamos con la utilidad que tiene profundizar en el propio Java, Hibernate, SQL o cualquier otro lenguaje/framework que usemos para nuestra aplicación web. Y encima ahora mucho más, ya que en estos últimos años han aparecido frameworks como jQuery, Prototype, Mootools o Mochikit que nos permiten, con mínimos conocimientos de Javacript, modificar el DOM a nuestro antojo, usar Ajax, hacer efectos y controlar eventos de manera no intrusiva sin importar el navegador en el que se visualice nuestra aplicación.

Sin embargo, este lenguaje tan “sencillo y facilón” esconde algo: no hay más que ver el código fuente de jQuery, por ejemplo, para darnos cuenta de que, simplemente, no se entiende tan facilmente como se debería: es como si el Javascript que conocemos de toda la vida se transformara en algo tremendamente distinto.

Un pelín de jQuery

Veamos, por ejemplo, que esconde el fichero jquery.js de la version 1.4.4 (podeis bajarlo desde aquí):

Para empezar, toda la librería, al completo, se engloba en este código:

(function( window, undefined ) {

	// Use the correct document accordingly with window argument (sandbox)
	var document = window.document;
	var jQuery = (function() {

		// Aquí va todo el código de jQuery

	});

})(window);

Vaya, es algo un poco, como lo diría, extravagante, ¿no? Intrigado, me puse a buscar que era toda esta suerte de funciones sin nombre que se ejecutan; y he encontrado cosas bastantes interesantes que me han hecho pensar que llevo toda la vida subestimando a este lenguaje y usándolo sin conocerlo del todo bien.

Una sola palabra clave para todo: function

Para empezar, Javascript es un lenguaje dinámico, interpretado, con closures, y que permite programación orientada a objetos (aunque no como la conocemos en Java, así que olvidate de herencia, interfaces, super, etc). Sin embargo, no tiene sentencias específicas para ello: no hay manera clara de definir un closure, ni un método, ni una clase, ni un objeto, ya que todos se hacen con la misma palabra clave: function.

Así que depende de como usemos “function” estamos definiendo una simple función, un closure, una clase o un método de una clase, ¡y todo con la misma palabra clave! Por supuesto, la palabra clave “this” tiene un significado más amplio, e incluso variable en función del contexto en el que se use. Para rematar, hay maneras distintas y equivalentes de programar orientado a objetos.

Pero empecemos por el principo. Esto es una función: la definición de un bloque de código que se ejecutará más adelante. A esta forma de crear funciones se llama función como declaración:

    function saluda(quien) {
        alert("hola "+quien)
    }

Esto por si solo no hace absolutamente nada, sino que es necesario invocarlo con una llamada a nuestra función

    saluda("mundo")

Las funciones son datos

Las funciones son funciones, pero tambien datos: el hecho de definir una función con su propio nombre (en este caso “saluda” es el nombre de la función) hace que se cree una variable global llamada “saluda” que podemos leer y pasar como parámetro, por ejemplo:

    function saluda() {
        alert("hola")
    }
    function ejecuta(func) {
        func()
    }
    ejecuta(saluda)

En este ejemplo, ejecutamos la función “ejecuta” pasándole como parámetro la función “saluda” como un dato, que pasa a llamarse “func” dentro de la función ejecuta, donde es invocada simplemente con func().

Tambien podemos crear funciones como expresiones de esta manera (además, es la recomendada, luego veremos porqué):

    var saluda = function(quien) {
        alert("hola "+quien)
    }
    saluda("mundo")

Con esta sintaxis lo que estamos haciendo en realidad es crear un función anónima y asignarle un nombre inmediatamente, por lo que es equivalente a definir la función como hacíamos al principio con function saluda(quien).

Para acabar, podemos crear funciones como expresiones y con nombre a la vez, como las funciones como declaración. La utilidad de esto es hacer funciones recursivas:

    var f = function fact(x) {
        if (x <= 1) return 1;
        else return x*fact(x-1); };

Dado que f es una variable externa y ajena a la función que puede cambiar en cualquier momento, darle el nombre “fact” a la función durante su propia definición es la única manera que tiene la propia función de llamarse a sí misma.

Funciones anónimas, autoejecutables y que devuelven funciones

Una función anónima se puede definir sin que sea asiganada a ninguna variable:

function(quien) {
	alert("hola "+quien)
}

Sin embargo, hacer esto es completamente inútil: definir una función sin nombre hace que sea imposible ser ejecutada más tarde, pues sin un nombre con el que acceder a ella es imposible encontrarla.
Pero podemos ejecutarla en el mismo momento en el que la definimos. Para ello, solo tenemos que encerrar entre paréntesis, y después usar unos nuevos paréntesis con los parámetros, como hacemos con una función normal.

	(function() { alert("hola mundo") })()

Por supuesto, podemos pasarle parámetros a nuestra función autoejecutable. En el siguiente ejemplo, se pasa como parámetro “mundo” a la función:

	(function(quien) {
		alert("hola "+quien)
	})("mundo")

Puede parecer poco útil hacer esto ahora, pero más adelante veremos como es una fantástica manera de arreglar ciertos problemas.

Por supuesto, una función puede devolver una función anónima. Sera responsabilidad del programador asignarla a una variable:

    function saludator(quien) {
        return function() {
            alert("hola "+quien)
        }
    }
    var saluda = saludator("mundo")
    saluda()

O podemos ejecutar la función que se ha retornado directamente, sin asignarla a ninguna variable:

    function saludator(quien) {
        return function() {
            alert("hola "+quien)
        }
    }

    saludator("mundo")()

Claro, nadie te impide sobreescribir una función con otra.

    function saludator(quien) {
        return function() {
            alert("hola "+quien)
        }
    }

    saludator = saludator("mundo")
    saludator()

Aquí, la primera vez que ejecutamos saludator(“mundo”) nos retorna una función anónima (que muestra “hola mundo”). Esta función es asignada a la variable saludator, por lo que la segunda vez que llamemos saludator(), estamos ejecutando la nueva función anónima (la del “hola mundo”), y la función inicial original se pierde para siempre.

Funciones dentro de funciones

Sigamos. Las funciones además se pueden anidar:

    function saluda(quien) {
        function alertasaludo(quien) {
            alert("hola "+quien)
        }
        alertasaludo(quien)

    }
    saluda("mundo")

Las funciones anidadas se llaman inner-private function. Inner porque son internas, y private porque son solo accesibles desde el código de la función desde donde son definidas. En nuestro ejemplo, alertasaludo() solo se puede invocar desde dentro de saluda().

Podemos combinar funciones anidadas con funciones que retornan funciones:

    function saludator(quien) {
        function alertasaludo() {
            alert("hola "+quien)
        }

        return alertasaludo
    }

    var saluda = saludator("mundo")
    saluda()

Y lo anterior lo podemos combinar con una función anónima auto-ejecutable.

    var saluda = (function(quien) {
        function alertasaludo() {
            alert("hola "+quien)
        }

        return alertasaludo
    })("mundo")

    saluda()

¿Y esto para que puede servir? Un ejemplo es el siguiente:

    var parOimpar = (function() {
        var hoy = new Date()
        if (new Date().getDate() % 2 == 0) {
            return function() { alert("hoy es dia par") }
        } else {
            return function() { alert("hoy es dia impar") }
        }
    })()

    parOimpar()

Con esto tenemos una función anónimoa autoejecutable que, evidentemente, solo se ejecutará una vez, con el único fin de crear una nueva función que nos muestre si el dia de hoy es par o impar.

Resumen

Llegados a este punto ya tenemos que tener claro varias cosas sobre las funciones:

- Que pueden tener nombre o no. Si no tienen nombre, son funciones anónimas.
- La dos sintaxis válidas para definir una función con nombre son:

   function nombre() {}
   var nombre = function() {}

- Que una función es tambien un dato y se puede manipular:
- Puedes asignar una función a una variable (y pasarla como parámetro a otra función)

         function yo() { alert("yo") }
         function saluda(alguien) { alguien() }
         saluda(yo)

- Puedes cambiar una función por otra, tan solo tienes que asignarle otra función al nombre anterior.

	    function yo() { alert("yo") }
	    function tu() { alert("tu") }
	    yo = tu

- Una función anónima puede ser ejecutada inmediatamente:

   (function() { alert("hola mundo") })()

- Las funciones se pueden anidar

   function quien() {
       function tu() { alert("tu") }
       tu()
   }

- Una función puede devolver otra función:

   function quien() {
   	   return function() { alert("yo") }
   }

Y con esto es todo por hoy. Todavía no tenemos el suficiente material para explicar porqué jQuery define todo la librería como una función anónima autoejecutable, pero al menos sabemos que lo hace y conocemos la sintáxis para hacerlo.
El próximo artículo veremos closures y programación orientada a objetos con Javascript, para acercarnos más y más a como funcionan jQuery y la mayoría de frameworks actuales por dentro. ¡Hasta entonces!

Más información:

Plugin TwitterChecker para Grails

PostedEn Groovy, Programación     Comments Comments Off
Jan
26

He desarrollado mi primer plugin público (y gratuito claro) para Grails.

Este plugin chequea nuevos followers, unfollows, RTs y menciones de una cuenta de Twitter.

La url con la documentación y descarga es http://grails.org/plugin/twitter-checker.

TwitterChecker accede a tu cuenta de Twitter (usando Twitter4J y OAuth) y comprueba si hay:

  • Nuevos followers y nuevos unfollows (gente que te deja de seguir).
  • Nuevos RTs de tus twits realizados por otros usuarios.
  • Nuevas menciones realizadas por otros usuarios.

TwitterChecker se encargará de comprobar periodicamente esta información y lanzar eventos programados. En estos eventos se pueden enviar mensajes directos al nuevo usuario que te sigue, publicar en tu timeline o simplemente guardar la información en base de datos o enviar emails (en caso de unfollows por ejemplo).
Además, el plugin accede periodicamente a tu timeline, menciones y RTs realizados a ti y los guarda en una caché para que los puedas mostrar con una taglib en tus gsp.

Requisitos:

  • Quartz plugin 0.4.1 o superior.
  • Grails 1.2.0 o superior.
  • Tomcat Julli 6.0.16 o superior.

Y una cuenta de Twitter, claro.

El plugin incluye la librería twitter4j-core-2.1.7.jar (la última versión estable)

Instalación

grails install-plugin twitter-checker

Si no estas desplegando el War en un Tomcat, es posible que necesites el jar tomcat-juli-6.0.16. Si estás usando Grails 1.3+ puedes añadirlo en el fichero BuildConfig.groovy:

dependencies {
    runtime 'org.apache.tomcat:juli:6.0.16'
}

La instalación del plugin creará los siguientes archivos dentro de tu proyecto:

  1. controllers/twitterChecker/TwitterCheckerController.groovy
  2. views/twitterChecker/demo.gsp
  3. views/twitterChecker/index.gsp
  4. views/twitterChecker/_twitFromMe.gsp
  5. views/twitterChecker/_twitFromOther.gsp
  6. src/groovy/twitterChecker/DefaultTwitterCheckerListener.groovy

Configuración

1 Primero necesitas crear una aplicación en Twitter en esta dirección: http://dev.twitter.com/apps/new con estas opciones: “Default access type” a “read&write” y “Application type” a “client”. Una vez creada la aplicación, deberás apuntar el consumer key y el consumer secret.

2. Añade el siguiente fragmento en el archivo Config.groovy de tu aplicación Grails

grails.spring.bean.packages = ["twitterChecker"]
twitterChecker {
    oauth.consumerKey = "AQUI VA EL CONSUMER KEY DE LA APLICACION QUE HAS CREADO EN TWITTER"
    oauth.consumerSecret = "Y AQUI VAL EL CONSUMER SECRET"
    storageFolder = "/ruta/al/directorio/donde/twitter/checker/guardara/sus/archivos"
}
  • grails.spring.bean.package contiene el paquete donde está la clase DefaultTwitterCheckerListener.groovy. No modifiques este valor incluso si renombras la clase, solo es necesario modificarlo si mueves la clase de sitio.
  • outh.consumerKey and oauth.consumerSecret: pon aquí los valores consumer key y consumer secret de tu aplicación de Twitter.
  • storageFolder: el plugin necesita una ruta donde guardar 4 archivos binarios que se corresponden con los followers, menciones y RT.

3. Autoriza tu cuenta de Twitter con la aplicación de Twitter que acabas de crear.

  • Arranca ahora la aplicación Grails (ignora los errores de OAuth que verás en los logs) y visita la dirección del controlador TwitterCheckerController en tu navegador: http://localhost:8080/yourAppName/twitterChecker
  • Sigue las instrucciones, que son: obtener el nuevo pin (logarte en twitter, hacer click en “allow acces”), introducirlo en el formulario y hacer click en submit.
  • Si todo ha ido bien, la aplicación te mostrará un fragmento de código con los valores accountId, token y tokenSecret que deberás añadir en tu Congig.groovy

4. Reinicia tu aplicación y visita de nuevo TwitterCheckerController en tu navegador: http://localhost:8080/yourAppName/twitterChecker. Verás una página con tu timeline, menciones y RTs (si estás intrigado, puedes ver el contenido de esta página en views/twitterChecker/demo.gsp)

5. Una vez configurada tu aplicación con tu token y tokenSecret, puedes borrar el controlador TwitterCheckerController.groovy y las vistas twitterChecker/demo.gsp y twitterChecker/index.gsp. Pero no borres las vistas _twitFromMe.gsp y _twitFromOther.gsp, ya que son utilizadas por los taglibs (puedes modificarlas, pero no borrarlas)

Mostrar timeline, menciones y RTs

Para mostrar tu timeline, menciones y RTs en tu aplicación puedes usar estas tags (como puedes ver en la vista demo.gsp):

<twitterChecker:timeline max="10"/>
<twitterChecker:mentions max="200"/>
<twitterChecker:rts/>

(El parámetro max es opcional y puedes usarlo en cualquiera de las tres tags)

El plugin refrescará esta información cada 15 minutos y el taglib mostrará siempre una versión cacheada de estos datos, de esta manera se pueden utilizar tantas veces como se deseen estos taglib en tu aplicación. Se usarán las vistas _twitFromMe.gsp y _twitFromOther.gsp que están en tu propio proyecto, por lo que puedes modificarlas si lo necesitas.

Eventos

Cada 15 minutos, el plugin chequeará tu cuenta de Twitter en busca de nuevos followers, unfollows, menciones y RT. Puedes abrir la clase src/groovy/twitterChecker/DefaultTwitterCheckerListener.groovy que está copiada en tu propio proyecto y modificar los closures onNewFollowers, onUnfollows, onMentions y onRetweets que serán los que se ejecutarán cada vez que el plugin detecte un cambio en tu cuenta.

Puedes modificar cada cuanto tiempo el plugin chequeará tu cuenta de Twitter añadiendo estos valores en tu Config.groovy:

twitterChecker {
    checkTimelineEvery = 5  // 5 minutes
    checkMentionsEvery = 30 // 30 minutes
    checkRetweetsEvery = 30 // 30 minutes
    checkFollowersEvery = 120 // 2 hours
}

ATENCIÓN: Recuerda que Twitter limita el acceso a su Api a 350 peticiones por hora y aplicación. Cada vez que el plugin chequea tu timeline, menciones, rts y followers es una request, por lo que un valor de 15 minutos implica 16 peticiones en una hora. Bajar este tiempo puede incrementar drasticamente el número de peticiones a la hora. Para más información consulta: http://dev.twitter.com/pages/rate_limiting_faq

Usando la api the Twitter4J

El plugin proporciona el servicio TwitterCheckerService que actua igual que una clase twitter4j.Twitter ya preconfigurada gracias a la anotación @Delegate de Groovy. Es decir, este servicio tiene los mismos métodos que la clase twitter4j.Twitter (aunque si abrimos la clase no los veamos). Para ampliar información sobre los métodos de esta clase con los que enviar mensajes directos, publicar en el timeline, etc: http://twitter4j.org/en/javadoc-latest/core/twitter4j/Twitter.html

Además, el servicio TwitterCheckerService tienes estas nuevas propiedades: cachedMentions, cachedTimeline y cachedRts que serán usadas por las taglibs para renderizar las vistas.

Puedes usar este servicio desde cualquier controlador, por ejemplo:

class MyController {

    def twitterCheckerService

    def updateStatus = {
        // use the http://twitter4j.org/en/javadoc-latest/core/twitter4j/Twitter.html#updateStatus(java.lang.String) method
        def status = twitterCheckerService.updateStatus("Test from grails TwitterChecker plugin")
        ...
    }

    def readTimeline = {
        // use the cached version of the user timeline
        println twitterChecerService.cachedTimeline
        // get a new fresh version of the user timeline http://twitter4j.org/en/javadoc-latest/core/twitter4j/Twitter.html#getUserTimeline()
        def timeline = twitterCheckerService.userTimeline
        ...
    }
}

Crear un nuevo checker que consulte y cachee información de Twitter

Por ejemplo, si quieres mostrar en tu aplicación los resultados de buscar el tag #grailsx en Twitter, puedes crearte un nuevo job en Quartz que consulte esta información y la cachee para después mostrarla.

class CheckSearchQueryJob  {

    def yourOwnService // Servicio donde se desea guardar la información cacheada

    static triggers = {
        simple(name: 'CheckSearchQueryJob',
        repeatInterval: 15*60*1000) // Every 15 minutes
    }

    TwitterCheckerService twitterCheckerService
    def execute() {
        def resultQuery = twitterCheckerService.search(new twitter4j.Query("#grailsx"))
        yourOwnService.cachedQuery = resultQuery // Guardar la información en un servicio
    }
}

Después solo tienes que acceder al atributo yourOwnService.cachedQuery desde tus vistas.

Resolución de problemas

Si obtienes esta exepción:

Caused by: 401:Authentication credentials were missing or incorrect.
{"error":"Read-only application cannot POST","request":"\/1\/statuses\/update.json"}

Es porque tu aplicación es solo de lectura y no te permite actualizar tu estado ni enviar mensajes.

  1. Ve a http://dev.twitter.com, edit your app details y asegúrate de que se ha elegido “read-write” en access type.
  2. Visita tu cuenta de Twitter y revoca los permisos a tu aplicación en in http://twitter.com/settings/connections.
  3. En tu aplicación Grails, quita el token y tokenSecret actuales de tu Config.groovy, reinicia y vuelve a solicitar un pin para dar permisos a tu aplicación (es decir, repite todo el proceso de autorización).

La magia de Groovy: haciendo dinámico lo estático

PostedEn Groovy, Programación     Comments 2 comentarios
Jan
8

El otro día, en el seminario de Creación de DSLs con Groovy, un asistente me hizo una interesante pregunta. Me encontraba explicando cómo funciona el ExpandoMetaClass, el sistema que tiene Groovy para “sobreescribir” métodos de cualquier clase, incluso del JDK.En el siguiente código de la presentación se ve claramente lo que se quiere hacer:

Integer.metaClass.toString = {
    return "OPS!"
}
println 5.toString()

La explicación que estaba dando en ese momento decía algo así como “con este código, sobreescribimos el método toString de la clase Integer, de manera que cuando lo llamemos nos devuelva la cadena “OPS!”. Pero ojo, porque modificar el comportamiento de una clase del JDK no es una buena práctica porque bla bla bla”. Y en ese momento me interrumpieron (cosa que me gusta, porque significa que la gente está atenta y es curiosa) con esta pregunta: “pero ¿la sobreescritura de un método del JDK tiene efecto desde todas las clases, o solo durante el código donde se ejecuta?”. Y es una pregunta interesante porque para dar una respuesta con la máxima precisión posible es necesario adentrarse en cómo funciona Groovy por dentro. La respuesta corta es: si, tiene efecto en toda la máquina virtual, pero solo dentro del código de las clases de Groovy, nunca dentro de una clase Java. Pero para la respuesta larga no había tiempo, así que aprovecharé para responderla ahora con este post.

Groovy es un lenguaje empotrado (o embebido) en la JVM, por lo que cuando programamos en Groovy sabemos que el código resultante es 100% Java, ya que Groovy crea bytecode y genera clases que podemos usar desde Java con total libertad. Podemos usar interfaces Java desde Groovy (y viceversa), o hacer que dos clases, una en Java y otra en Groovy, hereden la una de la otra (o al revés). Hasta aquí todo correcto, sigamos.

Como la sintaxis de Groovy es casi idéntica a la de Java, podemos tener la sensación de que el código generado es el mismo que si hubiésemos programado la clase en Java (sin tener en cuenta las cosas nuevas que añade Groovy, como closures, etc). Pero sabemos que hay un poco de “magia”, la que hace que Groovy pueda acceder a variables y métodos que todavía no han sido creados en tiempo de compilación, pero que sabemos que posteriormente existirán en tiempo de ejecución. Cuando decimos que Groovy es dinámico o hablamos de Duck-typing, estamos hablando sin querer de esta “magia”, sin pararnos realmente a pensar como funciona, pues son las tripas internas de Groovy y, simplemente, nos fiamos.

¿Y cómo funciona realmente esta “magia”? ¿cómo hace Groovy para que, generando código 100% Java (que sabemos que tiene tipado estático) se convierta en tipado dinámico, cuando Java no lo es? Todas las clases compiladas y generadas por Groovy, y todas las que se usan desde Groovy, implementan siempre groovy.lang.GroovyObject, por lo que poseen los siguientes métodos:

    Object invokeMethod(String name, Object args);
    Object getProperty(String propertyName);
    void setProperty(String propertyName, Object newValue);
    MetaClass getMetaClass();
    void setMetaClass(MetaClass metaClass);

Los tres primeros métodos se encargan de interceptar todos los accesos de escritura y lectura de atributos de la clase, y de interceptar todas las llamadas a cualquier método que pueda poseer la clase, sin verificar que exista o no.

Así que, para que nos hagamos una idea, el código generado podría ser algo así (no es exactamente así, se ha simplificado con un código equivalente creado exclusivamente con fines didácticos para que lo entendamos. Si descompilamos una clase Groovy, veremos algo totalemente distinto)

Prueba.groovy

def objeto = new UnaClaseCualquiera()
objeto.variable = "saludo"
objeto.llamada()

Prueba.java (pseudo-clase resultante de compilar Prueba.groovy)

Object objeto = new UnaClaseNuestra();
objeto.setProperty("variable", "saludo");
objeto.invokeMethod("llamada", new Object[]{});

Como vemos, el código resultante es código Java 100%, tipado estático y que compila perfectamente. No importa si durante el código Groovy hemos usado un nombre de variable o método que exista o no, ya que en el código resultante Java no aparece explícitamente su acceso, sino que está encapsulado a través de estos métodos. La implementación de invokeMethod, por ejemplo, dependerá de muchos factores, pero podría ser la siguiente: usará reflexión para averiguar si la clase actual tiene un método con ese nombre que acepte los parámetros enviados (y con aceptar me refiero a número y tipo) y ejecutarlo; y si no lo encuentra, buscará un atributo de tipo Closure con ese nombre e intentará ejecutarlo, etc. Todas estas búsquedas sobre que método ejecutar (o qué atributo leer o escribir) se producen en tiempo de ejecución, produciendo el efecto de “código dinámico”, es decir, código cuyo comportamiento puede ser modificado en tiempo de ejecución.

Después hay otros dos métodos: getMetaClass() y setMetaClass() que nos permiten acceder (y modificar) el MetaClass relacionado con el objeto actual. El MetaClass contiene todos los atributos y métodos dinámicos que hemos añadido a la clase. De hecho, la implementación del método invokeMethod de la clase GroovyObjectSupport (de la que heredan todos los objetos del GDK de Groovy) es la siguiente:

public Object invokeMethod(String name, Object args) {
    return getMetaClass().invokeMethod(this, name, args);
}

Es decir, cualquier llamada a un método es delegada a su correspondiente objeto MetaClass, de manera que éste será el responsable de buscar si primero alguien ha añadido para esa clase un método dinámico (como el toString() para la clase Integer) y ejecutarlo antes. El efecto de esto es que estamos “sobrescribiendo” un método en tiempo de ejecución (el uso de las comillas es a propósito, ya que no existe una sobreescritura real).

Volviendo al ejemplo inicial, cuando hacemos esto:

Integer.metaClass.toString = { return "OPS!" }

Lo único que hacemos es añadir un closure en el objeto MetaClass de la clase Integer, de manera que cuando llamamos a nuestro método toString(), lo intercepte su MetaClass, encuentre el que acabamos de añadir y lo ejecute en vez de invocar al método toString() original del JDK. Por esta razón, esto solo funciona si la clase que ejecuta el toString() es una clase Groovy, no una Java. Una prueba de ello es el siguiente código:

Test.groovy

Integer.metaClass.toString = { return "OPS" }
println 5.toString()
println(new JavaTest().metodo(5))

JavaTest.java

public class JavaTest {
    public String metodo(Integer p) {
        return p.toString();
    }
}

El resultado será “OPS” y después “5″. Esto es así porque desde JavaTest, al estar creada directamente en Java, nos saltamos la llamada al invokeMethod y al MetaClass, que son los encargados de interceptar las llamadas, buscar y ejecutar los métodos nuevos añadidos en tiempo de ejecución y que sobreescriben a los originales del JDK.

De hecho, podemos corroborar esta afirmación viendo lo que hacemos de otra manera. Pensemos que en vez intentar “sobreescribir” el método toString() de Integer, lo que hacemos es añadir un método nuevo. Por ejemplo, añadamos el método toMelon() a la clase Integer desde Groovy y probémoslo:

Integer.metaClass.toMelon = {
    return "Melón"
}
println 5.toMelon()

Desde Java no solo no podemos llamarlo, sino que directamente no compilaría, pues el método toMelon no existe en la clase Integer del JDK.

Puede que todavía haya alguien que diga: “ok, todas las clases generadas por Groovy heredan de GroovyObjectSupport o implementan de alguna manera GroovyObject. Pero, ¿y las clases del JDK? ¿Cómo es posible acceder al atributo metaClass de la clase Integer, si este no existe?”. La respuesta es que desde Groovy nunca usamos clases del JDK, sino objetos que las encapsulan. Durante el proceso de compilación, Groovy se encarga de envolver en wrappers todos los tipos primitivos en sus propias clases. Por ejemplo, todos los ints o Integers que haya en nuestro código Groovy serán sustituidos por instancias de la clase IntWrapper, la cual si implementa GroovyObject. Incluso si usamos desde Groovy una clase Java nuestra, no la estamos usando directamente, sino que estamos accediendo a ella a través de un PojoWraper, el cual también implementa GroovyObject.

El encargado de hacer toda esta magia de verdad es el compilador de Groovy y la clase ScriptBytecodeAdapter, la cual os invito a que leáis y estudiéis, pues el verdadero código generado por Groovy no son más que llamadas a métodos de esta clase (ver un ejemplo aquí, o compruébalo tu mismo descompilando una clase Groovy)

Con esto espero haber dado un poco de luz a como funciona Groovy por dentro, como se resuelven los accesos cuando llamamos a métodos y como se “sobreescriben” en tiempo de ejecución. Espero poder más adelante explicar con detalle la generación de bytecode por el compilador de Groovy y las transformaciones AST. Mientras tanto, solo tenemos que recordar que la magia no existe, que todo son trucos. Y que Groovy usa un truco fantástico para engañarnos, y parecer dinámico cuando en realidad no lo es (desde el punto de vista de la JVM). Y que ese truco solo funciona dentro de las clases Java generadas a partir de clases Groovy, nunca desde clases Java escritas en Java.

Crónica de la Grails Exchange 2010 en Londres (parte 2)

PostedEn Crónicas, Groovy     Comments Comments Off
Dec
27

Ha pasado más de una semana desde que finalizó la Grails Exchange. Tenía el post a medio escribir desde el sábado que tenía que haber vuelto a Madrid, pero los aeropuertos de Londres no han funcionado con normalidad y hemos sido muchos los que nos hemos quedado casi hasta nochebuena allí atrapados. Yo al menos tuve suerte, el miércoles 22, y tras dos intentos fallidos, mi avión despegó y pude volver a tiempo, aunque me consta que ese mismo día hubo bastantes cancelaciones. Tras pasada nochebuena y navidad, por fin he tenido algo tiempo para terminar esta crónica de la Grails Exchange.

El segundo día de la Grails Exchange estuvo dedicado casi en exclusiva a Grails (ver la crónica del primer día aquí), fue un día muy productivo, con charlas muy interesantes y grandes figuras. A continuación un resumen de las ponencias más destacadas:

Keynote – In Search of the Grail of Developer Productivity

A Grails Roadmap Update

En esta keynote, Graeme Rocher comienza contando un poco la historia de Grails y cita algunos sitios interesantes desarrollados con esta herramienta como eHarmony, Northwestern Memorial Hospital y Hashable. Acto seguido pasa a hacer una demostración en vivo sobre el uso de Spring Insight con Grails desde SpringSource Tool. En este mismo blog ya hemos hablado antes sobre Spring Insight (posts y seminarios), así que es gratificante ver como Graeme apuesta por esta herramienta también para monitorizar aplicaciones Grails, ya que a nosotros también nos parece una herramienta muy buena de análisis y profilling.

Después pasa a comentar las novedades que lleva la versión 1.3 (la versión 1.3.6 fue liberada el miércoles, hacía tan solo 3 días) que son Groovy 1.7, JUnit 4, chaining named criteria y soporte para repositorios Maven. Nos cuenta que ha estado bastante ocupado trabajando en los plugins NoSQL para MondoDB, RedisRiak y Gemfire y una gran cantidad de nuevos módulos de autenticación para Spring Security. Y cita las novedades para Grails 1.4:

  • Actualización a Groovy 1.8, Hibernate 3.6 y Spring 3.1
  • Mejoras en el autocargado de clases al modificarlas en caliente (nos dice que no le gusta como está y que tiene que mejorarlo)
  • Nuevas funcionalidades para Gorm como migraciones, ingeniería inversa (que ya está disponible como plugin), herencia abstracta y un mejor soporte para tests.
  • Mejor manejo de los recursos estáticos (más adelante hay una ponencia de Marc Palmer sobre esto)
  • Cambio de Prototype por jQuery como framework Javascript por defecto.

Después continúa con la demo en vivo sobre el uso de criteria querys y named querys funcionando completamente con el plugin NoSQL inconsequential (usando un ConcurrentHashMap)

Finalmente comenta las nuevas mejoras que tendrá Grails 2.0, que saldrá en diciembre de 2011 como Gorm for REST (al salvar una clase de dominio con save(), invoca una llamada http PUT, y al leer hace un GET, etc. de manera transparente, al estilo como lo hace Ruby on Rails) y Scaffolding con Ajax con una nueva taglib para scaffolding.

Ver vídeo de la ponencia.

What’s hot in Grails land

En esta ponencia Peter Ledbrook hace un repaso a los plugins más interesantes y populares de Grails. Entre ellos cita:

  • Resources plugin, que se puede usar en combinación con zipped resources y cached resources (los tres del mismo autor, Marc Palmer, que después hará una ponencia específica sobre estos plugins) y cuyas características principales son:
    • Empaquetar recursos estaticos en modulos reutilizables entre GSPs.
    • Cachear y zipear los recursos para servir paginas más rápido.
    • Identificadores únicos de recursos a partir de su hash.
    • Añadir cache headers a los recursos estaticos. YSlow.
  • Spring Cache plugin que permite:
    • Cache de contenidos. Podemos usar en nuestros controladores las anotaciones @Cacheable(“x”) para activar la cache y @CacheFlush(“x”) para eliminarla (en un save por ejemplo)
    • Cache de metodos de servicios.
    • Cache de fragmentos de paginas, de taglibs, control de cabeceras.
  • Markdown plugin: un taglib que permite utilizar la sintaxis Wiki en tus gsps.
  • Bean Fields plugin: generación simplificada de formularios (obtiene automáticamente el tipo de input según el tipo del dato, visualiza los errores automáticamente):
    <bean:withBean beanName="form">
    <bean:field property="firstName"/>
    <bean:field property="lastName"/>
    <bean:field property="company"/>
    <bean:field property="email"/>
    </bean:withBean>
  • Reskin plugin que permite usar HTML5
  • Melody, un plugin de monitorización
  • Pretty time, un etiqueta  <prettytime:display date="${someDate}" /> que genera “right now”, “2 days ago”, or “3 months from now”
  • Itunes service, un plugin que se conecta a los servicios web de Apple de Itunes y permite hacer búsquedas.

Ver vídeo de la ponencia.

Design for simplicity

Glenn Saqui y Dave Scott, de sky.com, una compañía de entretenimiento y broadcasting de vídeo, nos cuentan la arquitectura de sus 7 portales que han realizado integramente con Grails y Groovy (98% de código es Groovy, 2% Java). Incluso los scripts de administración están escritos en Groovy. Tienen 6 millones de hits al día y más de 30 editores trabajando constantemente para añadir contenidos.
Solo usan un único war para todos sus portales, delegan los diferencias de configuración en archivos externos. Cachean todo lo posible, incluso cachean contenidos estáticos en los propios ordenadores clientes de los editores, mientras que para datos públicos, delegan los recursos en CDNs. Tienen pruebas funcionales de prácticamente todo y su primera regla es que todo sea lo más simple posible. Una ponencia que demuestra con un ejemplo real que el uso de Grails en servidor no penaliza (yo mismo defiendo esa idea en “¿se puede realizar una GRAN aplicación con Groovy y Grails?“)

Ver vídeo de la ponencia.

Introducing the new static resources framework for Grails

Aquí Marc Palmer, commiter de Grails, creador de Wecemm (un CMS  que se puede usar como aplicación independiente, o como plugin Grails para tu proyecto) y creador de los plugin static-resource, cached-resources y zipped-resources nos cuenta en que consisten estos tres plugins, que pasarán a formar parte del core de Grails en siguientes versiones.
Statis-resources es un plugin que permite definir los recursos (imagenes, css, javascript) de nuestras aplicaciones Grails en módulos, de manera que estos luego puedan ser usados desde nuestras páginas y layouts GSP. Soluciona el problema que supone que tanto la aplicación principal como cada uno de los plugins que esta usa posean cada uno sus propios css, javascript y recursos, dando lugar a lo que el llama “Optimizacion hell”: ¿quién (tu aplicación, el plugin A, el plugin B) es el que debe incluir los recursos y en que orden? Además, con este plugin podemos empaquetar nuestros estáticos fuera del archivo WAR para que puedan ser servidos desde un Apache o cualquier otro servidor HTTP, de esta manera podemos liberar a nuestro servidor de aplicaciones (o contenedor de Servlets) de la pesada tarea que es servir estáticos. Durante la ponencia, Marc muestra como utilizar y sacarle provecho, paso a paso, todos estos tres plugins.

Ver vídeo de la ponencia.

Grails Sans SQL

Graeme nos cuenta en esta ponencia que el futuro de las aplicaciones Web tiende a usar otros sistemas de almacenamiento distintos a las bases de datos relacionales. Grails incorpora de serie el acceso a un gran número de bases de datos diferentes con Gorm, gracias al uso que hace de Hibernate por detrás, así que es necesario llegar a otro tipos de manera de guardar nuestros datos que no sean tablas, relaciones, columnas y filas. El reto de Graeme es que los programadores de Grails puedan usar todas estas nuevas bases de datos NoSQL sin usar Apis específicas, solo con Gorm.
Primero hace un repaso sobre los diferentes tipos de bases de datos NoSQL:

  1. Document Stores (CouchDb y MongoDb)
  2. Column Family Stores (Cassandra, Bigtable)
  3. Grapth Tree (Neo4J, JCR)
  4. Map structures (Redis, Riak, Gemfire)

Y nos presenta Inconsequential: una abstracción sobre Gorm que soporta Redis, Gemfire, Riak, MongoDb y ConcurrentHashMap (actualmente está trabajando en Cassandra, CouchDb y JCR) y pasa a la práctica con una demo de Gorm con Redis: creando un proyecto desde cero y arrancando un servidor local de Redis (arranque instantáneo) y una consola para consultar el contenido de la “base de datos”. Es necesario indicar en el mapping de nuestras clases de dominio los campos por los que vamos a realizar consultas con index:true. Redis es un sistema de almacenamiento de pares clave/valor y permite almacenar tipos de datos ricos: strings, lists, sets y sorted set. Los datos se van guardando en memoria y posteriormente se van volcando a disco. Permite replicación master/slave replicación y tiene un rendimiento excelente (+100.000 lecturas/escrituras por segundo). La demo consiste en operaciones de creación, modificación, búsqueda y borrados sobre Redis usando solamente clases de domínio y Gorm.

La segunda demo consiste en realizar una aplicación en Grails con scaffolding usando Gemfire. Como nota adicional en este motor de base de datos NoSQL, es posible utilizar el espacio de nombres cq dentro de todas las clases de dominio con el que hacer búsquedas contínuas. Este tipo de búsquedas se realizan en background y ejecutan un Closure como evento cada vez que se encuentran valores definidos en la propia consulta (al guardar o sincronizar entre servidores). La tercera y última demo consiste en reutilizar la aplicación sin modificar el código simplemente desinstalando el plugin de Gemfire, instalando el de MongoDb y reiniciando. La conclusión final es que el soporte para base de datos NoSQL en Grails está bastante avanzado, al menos de manera básica, para un número considerable de sistemas y que poco a poco se irán añadiendo más.

Crónica de la Grails Exchange 2010 en Londres

PostedEn Crónicas, Groovy     Comments Comments Off
Dec
17

Durante hoy jueves 16 y mañana 17 se está celebrando en Londres la Grails Exchange 2010.

Dos días llenos de ponencias interesantes en el edificio de Skillmater, donde se puede ver en directo hablar a las primeras figuras del ecosistema Groovy y hacer contactos interesantes.

Gran ambiente, comida regular (lo siento, todos sabemos que el Reino Unido no es famoso por su gastronomía) y una conexión wi-fi estupenda es una buena definición de la Grails Exchange en pocas palabras. Para las ponencias me tendré que alargar un poco más, pues fueron muchas y todas bastante interesantes. Aquí va un resumen de las principales:

Keynote – Groovy, State of the Union

Como ceremonia de apertura, Guillaume Laforge hace una introducción a la historia de Groovy. Comentando un gráfico con la evolución del número de descargas de Groovy al mes, nos enseña como la adquisición de G2One y la liberación de la versión 1.6 de Groovy tuvieron los mayores picos de descargas. Pero el record sin duda han sido las 185000 descargas en un solo mes durante la salida de Groovy 1.7. Toda esta evolución da bastante confianza y presagia un gran futuro para Groovy y todo su ecosistema para las siguientes versiones.

Después repasa las mejoras que se han añadido a la versión 1.7 como:

  • Multiple asignements (a,b) = [b,a] para hacer swapping, por ejemplo.
  • Soporte para clases anónimas y anidadas. Aunque con algunas pequeñas mejoras, como que las clases anónimas no necesitan que las variables externas sean final y la creación automáticas de clases o interfaces con un solo método a partir de Closures.
  • Los power asserts, gracias al creador de Spock.
  • Anotaciones en imports, packages y la posibilidad de incluir Closures como parámetros en cualquier anotación.
  • Grab, que permite la descarga de clases desde repositorios de jars, como Maven, durante la compilación y ejecución de clases o scripts.
  • La personalización de la coerción a boolean con solo sobreescribir el método boolean asBoolean()

Después explica cual es el plan para las siguientes versiones:

  • Optimización en el rendimiento.
  • Soporte para JSON nativo.
  • GContracts: @Invariant, @Requires, @Ensures
  • Closure composition, crear closures con otros. Por ejemplo, closure1 << closure2 supone que una llamada a closure1(x), se ejecute realmente closure1(closure2(x))
  • Closure memoization o caché de resultados para Closures. Dado un mismo conjunto de parámetros de entrada, guarda la salida y la devuelve sin ejecutar otra vez el codigo.
  • Trampoline, idea sacada de los lenguajes funcionales (Clojure y Scala tambien la tienen), sirve para evitar los StackOverflowException en las llamadas recursivas a closures y métodos cuando se llaman demasiadas veces (más información sobre trampoline en el blog de Václav Pech)
  • Nuevas transformaciones AST: @Log, @Field, @PackageScope, @InheritConstructor, @IndexedProperties, @AutoClone, @AutoExternalize, @ThreadInterrupt
  • Modularizar groovy.
  • Mejorar soporte para DSLs con GEP-3, eliminando puntos y parentesis totalmente. Ver un ejemplo en el blog de Guillaume.

Sobre la optimización: Groovy es particularmente lento en manipulaciones aritméticas y manejo de primitivos debido a lo conversión automática de tipos (BigDecimal), boxing/unboxing y la sobrecarga de operadores matemáticos. El peor caso conocido es la función de fibonacci, que en Groovy 1.7.5 tarda 25131 ms, y su equivalente en Java 1110 ms, esto es hasta 22x mas lento. Debido a las optimizaciones con enteros que se han hecho en la versión 1.8-beta3, esta misma función tarda en calcularse 1871 ms, solo un 68% más lento (es decir, antes 22.64x y ahora 1.68x), lo cual supone un gran avance.
Lo siguiente será optimizar los doubles y mejorar el acceso a los arrays. La alineación de Groovy con JDK7 no será hasta la versión Groovy 1.9 (todavía queda bastante…), y los Closures hasta JDK8

Ver vídeo de la ponencia y presentación.

Rich Grails UIs with Canoo RIA Suite

Dierk Koenig, de Canoo, nos muestra en directo como funciona su suite para creación de aplicaciones RIA ligeras. Ultra Light Client es un framework para crear aplicaciones Swing en el que todo se programa y se ejecuta en el servidor. Y gracias a esto podemos usar Grails y Groovy para crear aplicaciones Swing, lo cual lo hace muy interesante. Las aplicaciones generadas se pueden ejecutar como un Applet o desde Java web start. Arrancan muy rápido, pues el cliente tiene siempre el mismo código: lo necesario para conectarse al servidor y que éste le diga que componentes Swing se deben crear y que eventos se deben propagar. El funcionamiento después es simple: una vez generados los componentes en cliente, cada evento generado invoca código en el servidor. Desde ahí, los posibles cambios se propagan de nuevo en la capa cliente.
El ejemplo empieza creando una aplicación muy básica en Grails con 4 clases de dominio. Despues instala el plugin para Grails ULC Plugin y genera un scaffolding de solo lectura para acceder a todas las entidades en un applet con Swing. Es interesante ver como la carga de datos se hace bajo demanda (se nota sobre todo cuando hay un listado con 2000 elementos: según se va desplazando se van cargando poco a poco los resultados)
ULC es una herramienta de pago en la que trabajan Hamlet D’arcy (committer de Groovy, autor del capítulo “AST Transformations” de la segunda edición de “Groovy in Action”), Andres Almiray (committer de Groovy y creador de Griffon) y el propio Dierk Koenig, autor principal del libro Groovy in Action. Menudo pedazo de equipo que tiene Canoo.

Ver vídeo de la ponencia

Enter the Gradle

El creador de Spock, Peter Niederwieser, da una charla práctica sobre Gradle. Gradle es un sistema para construir aplicaciones Java (además de Groovy, Scala, Web apps y OSGi). Proporciona un DSL y una librería Java que se pueden usar para crear scripts. Comenta que no es un framework de builds, es un lenguaje extensible para construir builds, que no es lo mismo (a diferencia de Ant, con Gradle puedes programar), y es declarativo (le dices qué hacer y el se encarga del cómo). Finalmente acaba la demo creando, a partir de varios scripts Ant, sus equivalentes en scripts Gradle, y su integración con Maven.

Ver vídeo de la ponencia.

Testing dynamic websites with GEB: a newbie’s perspective

Tomas Lin (@tomaslin), que se casa el próximo martes (felicidades!), nos explica en su charla su experiencia haciendo tests funcionales sobre sites con Geb. Este tipo de tests se encargan de navegar, hacer clicks en enlaces y submit de formularios para testear aplicaciones web, incluso con Ajax. Durante la charla nos explica como simular las acciones de un usuario con Webdriver, y después procesar el DOM resultante para ver si es válido. Para esto Geb proporciona un DSL una sintaxis igual que la de jQuery. Una ponencia bastante entretenida e interesante, sin duda GEB parece muy potente, incluso para hacer crawling y bots.

Ver vídeo de la ponencia.

High volume and scalable Ajax with Grails

David Dawson en su charla nos explica como hacer que nuestras aplicaciones con un refresco intensivo vía Ajax sean escalables usando long polling. Para esto nos enseña varios ejemplos con jQuery en la parte cliente y en la parte servidor Continuations (sólo para Jetty), Comet (Tomcat) y Atmosphere (para cualquier contenedor de Servlets). La idea es bastante simple: si un cliente tiene que refrescar su estado y hace una petición al servidor cada 10 segundos ¿porque no mantener solo una conexión abierta contra el servidor esperando ese resultado? de cara al cliente el resultado es el mismo o incluso más rápido, ya que la información llega inmediatamente. Y en el servidor solo tenemos que mantener las conexiones abiertas en un pool y enviar el resultado a todas en cuanto se reciba. El cliente, cuando reciba el resultado (al segundo o al cabo de una hora), lo mostrará y abrirá una nueva petición. Los ejemplos y el código mostrados en la charla son completamente prácticos, sencillos y, sobre todo, que funcionan (se ve la conexión Ajax que abre jQuery esperando indefinidamente en Firebug).

Ver vídeo de la ponencia.

Los chicos de skillmater son unas máquinas y los vídeos están listos apenas acaban las ponencias, por lo que ya podéis verlos todos aquí. Mañana el resto.

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

PostedEn Groovy, Programación     Comments 3 comentarios
Dec
8

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.

Crónica del Coderetrat 2010 en Madrid

PostedEn Crónicas, Groovy     Comments 3 comentarios
Oct
6

Qué es

El pasado sábado 2 de este mes de octubre asistí a mi primer Coderetreat. En el anuncio de agilismo.es no se decía claramente lo que se iba a hacer, tan solo una agenda con sesiones de trabajo y retrospectivas, pero nada más. Como no sabía lo que era un Coderetreat ni tenía claro si se iban a dar charlas o si se iba a programar decidí apuntarme y probar.

¿Y qué es un coderetreat? no lo tengo del todo claro, pero viene a ser un reunión de desarrolladores en los que se juntan para programar en parejas haciendo TDD, intentado resolver un problema concreto, compartir experiencias y aprender. Se hacen iteraciones (normalmente 6) de 40 minutos con 15 minutos de retrospectiva después de cada una.

La organización del Coderetreat de este sábado corría a cargo de agilismo.es y Autentia, que trajeron a Enrique Comba (@ecomba), uno de los autores intelectuales del Manifiesto por la Artesanía del Software y co-fundador de Agile-Spain como maestro de ceremonias.

Qué hicimos

Llegué a la sala de actos del hotel donde se celebraba la reunión a las 9:00 y me encontré, como en todos estos saraos, algunas caras conocidas y muchas nuevas. Un poco de networking-desayuno y empezamos, estaba incluso impaciente pues no sabía exactamente que íbamos a hacer.

En la presentación conocí a Enrique. Es un personaje carismático y un poco malvado (luego veréis porqué), así que nos dejamos llevar por su manera de hablar tranquila y relajada y nos explicó que teníamos que hacer. Programaríamos 40 minutos y cuando oyéramos la alarma de su móvil, borraríamos el código (sin excepción) y nos pondríamos de pie. Hizo, además, una breve encuesta a mano alzada con preguntas del tipo ¿cuántos de vosotros hacéis pair programming? ¿cuántos conocéis TDD? ¿cuántos practicáis TDD alguna vez? ¿cuántos prácticas TDD siempre?. Finalizada la presentación, nos sentamos en parejas, abrimos nuestros portátiles y, tras decidir quién de los dos empezaba a programar y qué lenguaje utilizábamos, tuvimos 40 minutos para desarrollar un reto. Este consistía en hacer el juego de la vida de Conway, un autómata celular basado en las siguientes reglas (que Germán tuvo la buena voluntad de escribirlas en la pizarra):

Las células nacen o mueren según el número de células vivas adyacentes.

  1. Una célula con menos de 2 vecinos muere.
  2. Una célula con más de 3 vecinos muere.
  3. Una célula con 2 o 3 vecinos, vive hasta la siguiente generación.
  4. Una célula muerta con 3 vecinos, revive.

Charlando, haciendo pruebas y programando se me pasaron los 40 minutos volando con Jon (el de la derecha en esta foto), un simpático phpero al que le apetecía probar con Groovy. Suena la alarma de Enrique y borramos todo el código hecho. No nos hace mucha gracia, al fin y al cabo es nuestro trabajo, pero no pasa nada, lo borramos, nos levantamos y hacemos una retrospectiva todos de pie de 15 minutos. Comentamos las diferentes aproximaciones que hemos hecho y Enrique nos pregunta el nombre de las clases que habíamos creado. Salen cosas tan dispares como tablero, matriz, universo, célula, estado, vecino, vecindario, muerte, vida, parrilla y otras muchas que no recuerdo ahora.

Cambiamos de pareja y volvemos a la carga. Esta vez me pongo con Alberto Peña (@plagelao) y repito con Groovy como lenguaje de programación. Con más decisión y, gracias a la experiencia de la iteración anterior, conseguimos avanzar lo suficiente para que pasaran casi todas las pruebas menos una ¡ya casi estábamos!, pero toca otra vez la campana y hay que borrar otra vez el código.

Viendo la luz

Tras la retrospectiva, es en ese momento es cuando me doy cuenta de que llevaba toda la mañana trabajando con una mentalidad totalmente equivocada: programando deprisa e intentado aportar soluciones que resolvieran el reto lo más rápido posible (¡solo 40 minutos!) al completo no es, para nada, el espíritu ni el objetivo de un coderetreat. Si quisíeramos hacer el juego de la vida, nos darían más tiempo y no borraríamos el código. Pero aquí no se persigue un fin, no se persigue una solución ideal ni tener el problema resuelto, sino todo lo contrario. Se persigue el medio, el enriquecimiento durante la programación, y se desecha el fin: el código se borra implacablemente tras cada iteración, dejándolo vivo solamente en nuestra memoria el tiempo suficiente para poder comentarlo en la retrospectiva y se vuelve a empezar. No importa si tu implementación fue brillante, el lenguaje que usaste, lo rápido que funcionase o si pasaban todas las pruebas. Se anda el camino por el placer de andar, no para llegar a ningún sitio: el verdadero fin es programar, usando cada vez un enfoque diferente, razonando en voz alta con un compañero distinto, en un reto diferente, cada vez.

Así que a partir de aquí cambié de mentalidad, me olvidé de resolver el problema y orienté el resto del día de otra manera: probaría otros lenguajes y otras maneras de resolver el reto. La siguiente iteración buscaría a alguien que programara en otro lenguaje que no fuera ni Groovy ni Java y lo haría todo de otra manera. Y me encontré a este chico, cuyo nombre no recuerdo, que usaba C#. Pero esta vez Enrique añadió unas cuentas reglas nuevas: ahora no se podía usar ninguna clase o entidad que representara una célula y teníamos que orientar la solución a las reglas del juego en sí mismas, y así lo hicimos (o lo intentamos). Por supuesto, al hacer un planteamiento tan diferente no nos dio tiempo a nada, y en la restrospectiva Enrique nos sorprendió con un engaño digno de un auténtico ilusionista: nadie nos dimos cuenta de que la iteración había durado ¡solo 20 minutos! todos pensábamos que había sido muy corta, pero por el hecho de habernos visto obligados a usar un enfoque distinto, pero nadie se dio cuenta que, simplemente, había durado la mitad. Buena jugada Enrique, si señor.

Confusión total

Cambiamos de pareja de nuevo y ahora si tenemos 40 minutos para la iteración, pero nos propone un gran desafío: no podemos usar clases, así que todo el código que necesitemos debe estar dentro de la prueba unitaria. Primero deberemos escribir el assert, después el código para pasarlo y cuando sea realmente necesario, podremos refactorizar y crear una clase. Nos advirtió que iba a ser muy difícil y para hacerlo más difícil todavía, nos invitó hacer cada test con un máximo de 4 líneas (sí podíamos). Confiados y motivados, me puse manos a la obra con Kini (@kinisoftware). Pero resultó no ser difícil, sino que directamente llegó un momento que no sabíamos ni qué hacer. Enrique se pasó por nuestro sitio para ayudarnos, nos dijo “¿me permitís?”, se puso al teclado, borró todo nuestro código (ante nuestra mirada atónita, claro) y tecleo algo parecido a:

void testVida() {
    boolean estaVivo = true;
    assertTrue(estaVivo);
}

Kini y yo, intentando comprender que es lo que quería Enrique que hiciéramos

Y nos miró satisfecho. Me recordó a la escena en la que Morpheo lucha contra Neo en Matrix y le dice “¿acaso crees que lo que respiras ahora es aire?”. Kini y yo nos miramos como sospechando el uno del otro y nos acabásemos de conocer ahí mismo y dijimos “venga vale, a ver si podemos seguir a partir de aquí”, pero nos duró poco. Intentamos baby-steps, haciendo tests muy básicos que siempre pasaban por el simple hecho de que, al tener que programar dentro de cada prueba el código necesario para pasarla, crear un test nuevo más no hacía que fallaran los anteriores, como suele suceder cuando compartes el código entre todos los tests. Así que no sabíamos en qué momento empezar a programar de verdad y refactorizar. Y así estuvimos, estrujándonos el coco durante 40 minutos de auténtica confusión, y se acabó, gracias a dios, la iteración y empezamos otra retrospectiva. Para colmo, creo recordar que en esta iteración estaba prohibido ¡usar ifs! Enrique parecía contento y sonreía sin parar al ver nuestras caras de desconcierto, un auténtico diablo malvado se esconde detrás de Enrique: creo que todos le odiamos en ese momento un poquito (es broma Enrique, sabes que te queremos ¡y nos encanta sufrir!)

Divirtiéndonos

La siguiente iteración fue algo más relajada, ya sin estar tan condicionados como en la anterior con las diabólicas reglas de Enrique, en esta solo se nos pidió que enfocáramos el desarrollo a modelar las reglas del juego de la vida. Me senté con Jorge Jimenez (@semurat), al que ya conocía de Twitter y tenía ganas de programar con él. Fue una iteración muy divertida ya que nos estuvimos riendo la mayor parte del tiempo (debió ser general, porque recuerdo a Kini gritar con los brazos en alto en un momento de euforia mientras programaba con José Manuel Beas …). Esta vez Jorge se dejó llevar por mi loca idea de plantear las reglas de una manera funcional, al estilo cálculo Lambda.

int fib(0) { return 1; }
int fib(1) { return 1; }
int fib(int n) { return fib(n-2) +
                 fib(n-1); }

La función de Fibonacci implementado en un pseudocódigo Java funcional. Algo así queríamos hacer Semurat y yo con el juego de la vida.

Y así estuvimos los 40 minutos, triturándonos un poco los sesos, creando reglas en un sistema que nos acabábamos de inventar y haciendo tests. Por supuesto, no acabamos ni de lejos, pero nos lo pasamos muy bien.

La última iteración, ya muy, pero que muy cansados, lo que hicimos fue repetir con el primer compañero que tuvimos cada uno ese día, de manera que pudiéramos comparar lo que habíamos aprendido cada uno por el camino durante el Coderetreat y lo contrastáramos. El enfoque en esta última iteración era pensar en el juego de la vida desde un punto de vista temporal, trabajando las generaciones y no las reglas. Así que busqué a Joan y decidimos empezar de nuevo, pero haciendo el juego de la vida con Javascript y las pruebas unitarias con QUnit, todo un reto para lo cansados que estábamos al final del día. Para acotar el problema, decidimos inventarnos una regla muy sencilla para el juego de la vida: una celula vive si tiene una célula viva a su derecha, e implementarla en un sistema que nos generase la matriz de células en función de una generación x dada en el tiempo. Y todo esto en Javascript, casi nada vamos.

La kata

Para rematar ante de irnos, una de las sorpresas del día fue que iban a regalar una licencia de IntelliJ IDEA ¿cómo? ¿una licencia de mi IDE favorito? ¡tenía que conseguirla! pensé, pero para ello teníamos que ganárnosla, y no nos lo iban a poner fácil. El reto consistiría en prepararnos la kata de String Calculator en 30 minutos (al final creo que fue casi una hora, no estoy seguro, perdí la noción del tiempo) y luego saldríamos en público a hacerla. Nos presentamos tres valientes: Jose Manuel Beas, Alfredo Casado y yo mismo. Xavi Gost estuvo a punto de hacerla directamente en vivo sin preparársela, pero al final nos dejó con las ganas. Hacer una kata no es ninguna tontería: tienes que salir con tu portátil y programar en directo, con un proyector, delante de mucha gente, y te puedes poner nervioso, sobre todo si… algo falla.

El primero que salió fue Jose Manuel Beas, que hizo su kata en Java, con un TDD muy bueno y narrando cada uno de los pasos que iba haciendo, mostrando como fallaban los tests, implementando y refactorizando después. Sin embargo, no tuvo el tiempo suficiente para preparársela entera y la dejó a la mitad. Y es que el cansancio a esas horas ya hacía mella en todos nosotros (¡las katas hay que hacerlas a primera hora, no a última!). Aplausos, votaciones y el siguiente a la palestra, yo mismo. Gracias a que usé Groovy, que permite programar mucho más con menos líneas, conseguí acabar mi kata completa durante la hora de entrenamiento anterior. Pero durante la realización de la misma en vivo, en uno de los primeros puntos, apareció un error que no me atreví a corregir con tanta gente mirando y directamente me planté. Mi falta de experiencia en las katas hizo que no supiera gestionar bien mis nervios, y me vine abajo en el primer error. Y es que una cosa es programar y otra muy distinta hacerlo en público, y para esto último hay que entrenar, y mucho. Votaciones, buen flow pero bajo TDD, tengo que entrenarlo más. La siguiente corrió a cuenta de Alfredo Casado, que hizo una kata muy, muy divertida: llegó un momento que todos nos estábamos riendo de su peculiar manera de narrar la kata. Pero al igual que los demás, cuando iba por la la mitad, le apareció un error y se plantó, así es que ninguno de los tres conseguimos acabar. Me imagino que, cuando todos los que salimos dejamos la kata por la mitad, es porque no debe ser nada fácil terminarla: está claro que hay que entrenar y practicar. Tras las votaciones, Alfredo salió victorioso y se fue a casa con una nueva licencia de IntelliJ IDEA ¡felicidades Alfredo! (que mejor momento para abandonar Netbeans :-D)

Y esta es mi versión personal de la kata String Calculator que hice el sábado. Es mejorable, sin duda: no usa expresiones regulares, falla en algunos casos (por ejemplo si se usan asteriscos como delimitadores) y el TDD usado es malísimo, pero es la que me salió en ese momento: http://groovyconsole.appspot.com/script/262001. Para ejecutarla solo hay que hacer click en “Edit in console” y después en “Execute script”

Fin

Seguramente la gente se quedó, hubo cañas o cena, pero personalmente estaba muy cansado, así que dejé a Israel Alcazar (me quedé con las ganas de programar con él, para la próxima) en el tren mientras charlamos en el coche y me fui a casa. Eso sí, con la sensación de que llevaba una semana trabajando sin parar y una sonrisa de oreja a oreja. Me metí en la cama, dormí 12 horas y soñé con células que nacían y morían…

Otras crónicas de asistentes:

Más información:

Recortando el currículum y el primer empleo

PostedEn Yo, programador     Comments 8 comentarios
Aug
29

Homer una vez tuvo que leer un currículum que tenía cuatro páginas.

De vez en cuando, como casi todo el mundo, me gusta actualizar el currículum y añadir lo último en lo que he estado trabajando o lo nuevo que he aprendido. Según dicen algunas normas no escritas, lo suyo es que el currículum no pase de dos páginas, o directamente nadie lo leerá. Así que, si durante toda nuestra vida laboral no hacemos más que añadir y añadir cosas, llega un momento en el que, después de doce años trabajando, tu currículum puede llegar a ser aburridamente largo. Y hay que meter tijera para reducirlo, por supuesto.

Por donde empezar está claro: en tecnología, cuanto más antiguo es un trabajo, menos relevancia tiene hoy en día. Así que tu primer empleo, después de unas cuantas sesiones reductoras, pasa de ser una larga descripción, para convertirse, año tras año, en una simple frase que casi da hasta pena dejarla. Y en ese momento piensas ¿debería directamente eliminarlo? Pues no, yo no quiero quitar mi primer trabajo porque le tengo mucho cariño. Y es que, aunque nada de lo que usaba por aquel entonces se use ya ahora, aprendí a trabajar en una oficina, a tener un jefe, un horario y a que las vacaciones no duraban 4 meses, sino 22 días laborables. Y como me apetece hablar un poco ello, a modo de historia del abuelo cebolleta, hoy contaré como fue mi primer trabajo.

Si, yo tuve uno de estos.

Junio de 1998, era la época del rincón del vago, los móviles Nokia 5110 y la PlayStation, los monitores de 14″ con culo y los Pentium II con 128Mb, el inicio de la burbuja puntocom y la salida a bolsa de terra.es. Internet llevaba ya algunos años en España con cosas tan penosas como Infovia y no existía infojobs o jobsket para encontrar empleo, ni nada parecido. Así es que tuve que buscar mi primer trabajo como seguramente hicieron nuestros padres: mirando en el periódico (de papel, me refiero; en concreto el segundamano) y llamando por teléfono desde casa (casi nadie de mi edad teníamos móvil). Llevaba ya algunos años programando en Clipper por mi cuenta con libros en casa, así que probé suerte y llamé a la única oferta que había de “Programador Clipper”. Y como en el carné de conducir, que aprobé todo a la primera; al primer sitio que llamé, les gusté y me contrataron. Por aquel entonces había una gran demanda de programadores, pues había que adaptar todas las aplicaciones para evitar el efecto 2000 y también para que aceptaran la nueva moneda que se avecinaba, el euro.

La empresa donde entré a trabajar se llamaba Teleinformática (que fue comprada por Azertia, que fue comprada por Soluziona, que fue comprada por Indra) y su principal cliente era el BBV (que todavía no se había fusionado con Argentaria).

Me incorporé a un equipo de diez programadores que desarrollaban aplicaciones de banca electrónica. En aquellos tiempos los bancos no tenían páginas web tan buenas como ahora, así que tenían que crear aplicaciones para que sus clientes (generalmente empresas) pudieran enviar operaciones al banco (a través de un modem) para hacer transferencias, consultar movimientos y todas estas cosas que ahora hacemos desde internet a diario.

La aplicación estrella se llamaba SIETE: una aplicación de escritorio desarrollada en Clipper y que corría sobre MS-DOS. Entonces Windows 95 era relativamente joven y, aunque ya había un departamento que creaba la misma aplicación para Windows en Delphi, se mantenían las dos versiones. Poco a poco el departamento de Windows creció y el de MS-DOS desapareció, pero eso es otra historia.

Empecé a interesarme en Clipper en el 90, mis padres me compraron todos estos libros en el corte inglés (tuve una adolescencia muy dura). Ahora los guardo como un tesoro (que solo yo puedo apreciar, claro). Pincha en la foto para verla un poco más grande.

Clipper era un lenguaje procedural, no orientado a objetos, con un sistema integrado muy cómodo para manejar base de datos, pues estaba basado en dBase III. No teníamos potentes IDEs como ahora, programábamos con editores prehistóricos como QEdit, Aurora y otros más que no recuerdo. Compilábamos con scripts en BAT que tardaban minutos en generar un ejecutable. Tampoco teníamos control de versiones, así que usábamos una carpeta compartida entre todos en un servidor remoto y avisábamos cuando alguien tenía que tocar algo para no pisarnos los fuentes.

No había internet, ni correo electrónico, ni nada por el estilo, así que las tareas las definía tu jefe de proyecto, las estimaba con Microsoft Project, las imprimía y te las daba en un papel donde ibas tachando las que ibas haciendo. La única manera de “comunicación” era compartir carpetas y copiar archivos, y los disquetes de 3.5″ claro. Ni comparación con ahora, que no podemos trabajar sin internet o correo (ya sea corporativo o gmail/hotmail/etc), buscar documentación o ejemplos o tutoriales o lo que sea, vamos.

QEdit

Programando como machos con el QEdit. Era duro, pero peor era el Edit...

Aurora

Los profesionales usábamos Aurora, ¡con sintaxis coloreada!

No había patrones, ni buenas prácticas ni metodologías ágiles. Te daban cientos de fuentes caóticos que habían sido tocados por decenas de personas antes. Y había que buscarse la vida. Al final, al cabo del tiempo, le cogías el truco, pero era bastante duro, pues te pasabas la mayor parte del tiempo intentando descifrar lo que había hecho el programador anterior. Por supuesto no existían las pruebas unitarias ni nada parecido, pero había algo que no fallaba: un departamento de control de calidad exclusivo para probar, que pasaban cientos de baterías de pruebas y hasta que no se pasaban todas, no se liberaba una versión. Así que al final, entre todos y con mucho esfuerzo, sacábamos el trabajo y conseguíamos hacer funcionar esa endemoniada aplicación que después correría en los PCs de cientos de clientes del BBV.

Y así pase dos años y medio, primero con Clipper y luego con Delphi, hasta que a finales del año 2000 me empezó a picar la curiosidad por un lenguaje nuevo y que parecía bastante interesante porque se podían construir aplicaciones para internet: Java. Pero eso también es otra historia.

Así es que cuando miro mi currículum y veo esa última frase en el apartado de experiencia que pone “1998-2000: Programador en Clipper de aplicaciones en banca electrónica”, algo dentro de mi me dice que ya ha sufrido suficientes recortes, y que no merece la pena borrar dos años de mi vida para ganar dos líneas de espacio. Así es que así se quedará, para siempre.

¿Y tú? ¿Cómo fue tu primer trabajo?

Artículos relacionados: Al principio, todo era mágico

Mac OS: escribir en unidades NTFS

PostedEn Software     Comments 2 comentarios
Jun
21

El soporte de Mac OS para escritura en unidades NTFS viene desactivado por defecto. Este es un truco para habilitarlo que he probado satisfactoriamente en Snow Leopard.

  1. Renombrar el binario /sbin/mount_ntfs por /sbin/mount_ntfs.orig

    Desde un Terminal puedes utilizar este comando (te pedirá password de root)

    sudo mv /sbin/mount_ntfs /sbin/mount_ntfs.orig
    
  2. Crear un script llamado /sbin/mount_ntfs con el siguiente contenido (usa tu editor de texto favorito):
    #!/bin/sh
    /sbin/mount_ntfs.orig -o rw "$@"
    
  3. Dar permisos de ejecución al fichero que acabamos de crear. Puedes utilizar estos comandos desde el terminal (pedirá password de root)
    sudo chown root:wheel /sbin/mount_ntfs
    sudo chmod 755 /sbin/mount_ntfs
    

No requiere reiniciar. Ahora ya puedes usar esa unidad USB en NTFS llena de música que también usas en el PC con Windows que tienes en casa escondido. :D El truco por supuesto no es mío, está sacado del foro de Mac Rumors.

Crónica de la GR8conf 2010 en Copenhague

PostedEn Crónicas, Groovy     Comments 1 comentario
May
28

Los pasados 19 y 20 de Mayo tuve la oportunidad de asistir en representación de Paradigma Tecnológico, la empresa donde trabajo, a la GR8 European Conf en Copenhague, la versión europea de la GR8, una conferencia que trata exclusivamente sobre Groovy y otras tecnologías creadas con este lenguaje como Grails, Griffon y Gradle.

El recinto de acogida fue la IT University, ahí pasamos todo el día, horas de la comida y cena incluidas. Pese a que la wifi no resistió todo el tráfico de los asistentes, en general diré que el sitio, la organización y la comida fueron bastante buenos. Además, al volcán islandés Eyjafjalla le debe gustar también Groovy, porque esa semana nos dio a todos los asistentes un respiro y se pudo volar con normalidad a la ciudad.

Fueron solo dos días y muchas ponencias, así que los organizadores tuvieron que ingeniárselas para que diera tiempo a todo, dando como resultado una agenda bastante apretada: incluso a la hora de comer había una pequeña charla de 20 minutos sobre algún tema. Además, el primer día hubo Hackergarten night coding, así que los que no tuvimos suficiente con las charlas (o sea, todos), nos pudimos quedar hasta la hora que quisimos dentro del recinto para programar algún plugin (o lo que sea) con alguno de los líderes de Groovy, Grails, Gradle o Griffon. Más adelante comentaré la experiencia en el Hackergarten, pero en resumen diré que fue de lo más interesante, aunque agotador (acabámos a las once la noche).

Pero lo mejor de la conferencia ha sido, sin duda, que el nivel técnico de todos los ponentes (y del público también, dadas las preguntas que se hacían durante las charlas) ha sido muy muy alto. Supongo que tener que viajar hasta Copenhague a una conferencia que trata sobre un tema tan especializado como el ecosistema Groovy, ha hecho que la proporción de expertos respecto a gente “normal” haya sido más acusada.

Más información:

Groovy on the way to success

En esta primera ponencia, Philippe Delebarre y Raffaele Cigni, de la Oficina Europea de Patentes (EPO) nos cuentan su problemática situación actual y como la han solucionado. Su oficina gestiona actualmente más de 140.000 patentes al año, y su sistema informático es una gran aplicación host basada en Cobol muy antigua que se está quedando obsoleta: cada vez hay más patentes que tramitar y sus procesos son cada vez más lentos. Por dos veces han intentado migrar sus sistemas, pero sin éxito alguno. Primero un ET y después un ESB: las dos soluciones o eran muy caras, o muy difíciles de mantener, con grandes ficheros XML de configuración, etc.
Su solución final ha consistido en la elaboración de un lenguaje propio de dominio (DSL) al que han bautizado como DFP (data flow process) con el que crean procesos. Es un lenguaje muy simple, intuitivo, fácil de usar y de mantener. A su alrededor, han creado todo una plataforma que es capaz de leer y procesar estos ficheros DFP, por lo que su trabajo de mantenimiento consiste en crear nuevos procesos o modificar los existentes, y desplegarlos en la plataforma que han diseñado, responsable de procesar todos sus DFP. Con esto han conseguido una forma barata de migrar su sistema aumentando la velocidad de procesamiento de las patentes: ahora están listas en varios días en vez de semanas (hay que tener en cuenta que una patente suelen requerir correcciones manuales, pero el sistema desarrollado contempla el rechazar alguna patente si le falta algún dato, etc).

Esquema de la plataforma de procesamiento de patentes

Mi conclusión tras ver la ponencia es que no solo de Grails viven las aplicaciones empresariales: Groovy es un excelente lenguaje de scripting que, junto con un DSL bien diseñado, puede agilizar la creación y mantenimiento de aplicaciones de procesamiento automatizado de datos.

Quickie: Grails update

En una breve exposición de apenas 20 minutos, Graeme Rocher nos cuenta el estado de Grails en la actualidad y nos cita algunos sitios importantes desarrollado con este framework como la tienda online Walmart, una aplicación 2.0 para la gestion de tareas llamada Manymoon, la página de la universidad Northwestern, y un buscador de ¡baños públicos! llamado Sitorsquat.com, entre otros. Como nota destacable, nos cuenta que se ha mejorado el soporte de Grails para Eclipse en el nuevo SpringSource Tool y nos adelanta su roadmap:

Grails 1.2 ha mejorado considerablemente su rendimiento

  • Mejoras sustanciales en el rendimiento
  • Pluggable test framework: poder insertar nuevos framework de test como pluggins
  • Global constraints/mappings: constraints globales que afectan a todos los objetos de dominio
  • Soporte Gorm para NoSQL
  • Soporte para despliegue de aplicaciones cloud
  • Integración con Gemfire RabbitMQ

Y para Grails 2 en septiembre con grandes cambios.

  • Mejorar la integración con aplicaciones ricas de escritorio (RIA)
  • Mejoras en el sistema de plugins (basado en Osgi), despliegue de plugins en caliente
  • Múltiples datasources (¡bien!)
  • Database migration e ingeniería inversa (creación de clases de dominio a partir del modelo de datos)
  • Arranque más rápido (supongo que por los problemas que tiene Grails al desplegarse sobre Google App Engine)

En resumen, Graeme nos cuenta que Grails 2 va a ser muy diferente y que el cambio mayor de versión esta justificado. Esperamos ansiosos su salida, que estima entre septiembre y final de año (la verdad es que no recuerdo bien la fecha).

Grails Internals – Demystifying the Magic

Grame continúa después con una presentación bastante extensa (y que me es imposible resumir) sobre como funciona el arranque de Grails, los class loaders implicados, el BootStrap, etc. Acaba con la creación de una aplicación de ejemplo básico y la depuración, línea a línea, del código de Grails al recibir una petición http: para ello inserta un par (bueno, unos cuantos al final) de puntos de ruptura en clases clave del código, como GrailsWebRequestFIlter y UrlMappingsFilter, intentando explicar todos los pasos y procesos que toman parte de la petición. Muy interesante e instructivo.

Graeme explicando la secuencia de una petición HTTP en Grails

Gaelyk, a lightweight Groovy toolkit for Google App Engine

Durante la comida, Guillaume Laforge, en unos breves 20 minutos, nos resume el funcionamiento de Gaelyk, un framework ligero para el desarrollo de aplicaciones Groovy para Google App Engine. Gaelyk no es más que un conjunto de clases que añaden dinámicamente a los Groovlets y Groovy Templates los atributos y métodos necesarios para acceder cómodamente a las APIs que nos ofrece Google para acceder a sus servicios de Xmpp, BigTable (memcache, blob y datastore), email, images, etc. La verdad es que esta presentación me pilló comiendo, así que no puedo contar más.

Flying with Griffon

La presentación de Andres Almiray, el creador de Griffon consiste primero en una introducción donde explica qué es y cómo funciona Griffon y después en el desarrollo, en directo, de una pequeña aplicación de ejemplo en Swing con Griffon.

Griffon es un framework de desarrollo, muy parecido en concepto y arquitectura a Grails (de hecho, comparten código), para la elaboración de aplicaciones MVC con Swing, Groovy y Java. Al igual que Grails, posee un comando para la creación de proyectos, generación de clases, empaquetado de la aplicación e instalación de plugins. De la misma manera que lo hace Grails, el tener por separado controladores, modelos y vistas hace que el desarrollo sea mucho más cómodo y mejor estructurado. Sobre todo para la elaboración de las vistas, donde existe un DSL propio con el que generar todo el código Swing, pero sin tener que sufrir escribiéndolo. Además, podemos utilizar la anotación @Bindable en nuestros beans para que cualquier modificación en los atributos del modelo se transmitan directamente a las vistas y viceversa, sin tener que programar manualmente toda la gestión de estos eventos del patrón Obverser de Swing, con sus event listeners y demás parafernalia. Por supuesto, esto solo es posible gracias a Groovy sus transformaciones AST.

Andres preparándose para dejar al público atónito...

Esta presentación fue, para mí, una de las mejores, y ahora voy a explicar por qué: hace más de un año que uso Flex y Adobe Air en mi trabajo diario para hacer aplicaciones de escritorio. Y estoy muy contento, tanto por el lenguaje de desarrollo como por los resultados finales obtenidos. Swing siempre me ha parecido la parte más aspera de Java: aunque use un IDE para la elaboración de ventanas y componentes, la cantidad de código necesaria para construir una aplicación es simplemente desproporcionada, lo que hace que programar Swing acabe siendo una tarea poco agradable. Y esta ha sido la principal razón por la que, hace ya más de un año, cuando tuvimos que decidir qué tecnología usar para crear una aplicación de escritorio para un proyecto, nos hayamos decantado por Flex y Adobe Air en vez de Java y Swing, pese a ser Java el lenguaje con el que más cómodo nos encontramos (simplemente porque es el que más usamos a diario) y haber sido Flex/Adobe Air, en su momento, nuevos para nosotros.

Este precedente me sirvió para apreciar más todo el trabajo que ahorra Griffon en el desarrollo de aplicaciones Swing en comparación con Java. La prueba de ello fue cuando Andres empezó a hacer su demo, la programación de una aplicación con Griffon. Esta aplicación consistía en un pequeño cliente que se conectaba a una cuenta de Twitter (usando login y password) para listar todos sus followers. Todo programado desde cero, paso a paso y en directo, editando el código, compilando, corrigiendo errores y probando. El resultado final no tenía más de 10 clases y el código era compacto y fácil de entender. Había creado una aplicación desde cero, con una estructura básica coherente, perfectamente funcional, y ejecutable desde un Java Web Start, un applet o aplicación de escritorio. Hacer lo mismo con Java habría llevado, sin duda, muchísimo más tiempo.

Por ejemplo, esto es una vista Swing hecha con Griffon:

application(title:'gr8', pack:true, locationByPlatform:true {
    busyComponent(busy: bind{ model.busy }) {
	panel {
	   borderLayout()
	   panel(constraints: NORTH) {
	      gridLayout(rows: 3, cols: 2)
	      label 'Username:'
	      textField columns: 20, text: bind('username', target: model)
	      label ' Password:'
	      passwordField columns: 20, text: bind('password', target: model)
	      label ''
	      button 'Login', actionPerformed: controller.login
	   }
	   scrollPane(constraints: CENTER) {
	        table {
	            tableFormat = defaultTableFormat(columnNames: ['Id', 'Name'])
	            eventTableModel(source: model.followers, format: tableFormat)
	            installTableComparatorChooser(source: model.followers)
	        }
	    }
	}
    }
}

Para acabar la presentación, Andres anunció en directo la liberación de la versión 0.3.1 de Griffon, donde incluye, principalmente, una guía completa y documentación de referencia para el programador: http://dist.codehaus.org/griffon/guide

Mi conclusión es, tras acabar la demo, que Griffon es al desarrollo de aplicaciones de escritorio, lo que Grails es al desarrollo web: una manera de hacer lo mismo, pero más fácil, muchísimo más rápido, con menos código (y errores) y, sin duda, mucho más divertido.

  • Presentación de la ponencia de Griffon en Slideshare.
  • Descarga el código fuente de Gritter (197kb), la aplicación desarrollada por Andrés durante la conferencia.

El post acaba aquí, pero hubo muchas más ponencias interesantes, así que… continuará…

Categorías