segunda-feira, 16 de março de 2009

Groovy e a magia do invokeMethod

Estava eu discutindo com meu amigo André Ribeiro Gonçalves sobre o Groovy e sua simplicidade.

Durante a discussão começamos a trocar idéias sobre um recurso muito interessante da linguagem:
A possibilidade de interceptar a chamada de um método não existente de um objeto e fazer com que o mesmo faça algo de útil.
Como nós dois adoramos programação concorrente, o primeiro exemplo que nos veio a mente foi o de passar o processamento de um método de síncrono para assíncrono utilizando apenas convenção de código, escondendo assim a criação de um Runnable para encapsular o método e tornando isso algo mais transparente.
Ao final da discução o seguinte código foi criado, o mesmo é bem simples e é somente uma prova de conceito, mas é excelente pra mostrar a idéia.
E vocês, também acham isso fascinante?
   class A {

    def b( String name ){
        for( int i=0; i<15; i++ )
            println( name + i ) 
    }

    def invokeMethod( String name, args ){
        if( name.endsWith("Async") ){
            name = name.substring( 0, name.size()-5 );
            def m = A.metaClass.getMetaMethod(name, args)
            if( m == null ){
                println( "1. Nothing to do! No method definition found!" )
                return
            }
            def t = { 
                println( "Invoking $name in asyn way" )
                m.invoke(this,args)
            } as Runnable
            def t1 = new Thread(t)
            t1.start()
        }
        else {
           println( "2. Nothing to do! No method definition found!" )
        }
    }


}

def a = new A()

a.Async("t1")
a.c()
a.cAsync("t2")
a.b("name")
a.bAsync("t3")
a.bAsync("t4")
a.bAsync("t5")
a.bAsync("t6")
a.bAsync("t7")
a.bAsync("t8")
a.bAsync("t9")
a.bAsync("t10")
a.bAsync("t11")
a.bAsync("t12")
a.bAsync("t13")
a.bAsync("t14")
a.bAsync("t15")