Transformando métodos complexos em closures

Salve Groovystas,

Peço desculpas pelo tempo sem posts. Espero que isso não se repita… pois tenho bastante coisa para escrever e com isso pretendo criar a rotina de postar semanalmente.

Em alguns momentos nos deparamos com métodos que devido sua complexidade são difíceis de refatorar.
Recentemente, passei pelo seguinte problema de desempenho:
No sistema existe um método complexo que precisava ser chamado de dentro de um loop e isso sobrecarregava o processamento da funcionalidade em questão.
Devido à urgência desta tarefa, o melhor recurso encontrado neste momento foi a utilização do “memoize()”.
Este é um resumo sobre memoize para facilitar o entendimento:

//Problema: Quando temos um loop e dentro dele temos uma determinada
//lógica que precisará ser executada em todas as iterações;
(1..10).each{println  "este numero é ${it+5*(10-1)}"}

//Solução: Podemos otimizar nosso código inserindo nossa lógica dentro
//de uma closure, onde ao final desta chamamos o método memoize().
c = {println "este numero é ${it+5*(10-1)}"}.memoize()

//Por fim, chamamos esta closure de dentro do loop para que apenas a primeira
//interação seja 100% processada, pois nas próximas a parte repetida desta
//logica ficará em cache apenas sofrendo alteração de parâmetro.
(1..10).each(c)

Esse foi apenas um resumo, um exemplo rápido para não jogarmos termos novos sem explicação no post, mas em breve pretendo escrever exclusivamente sobre esse recurso que já me salvou varias vezes.

Mas, para nossa infelicidade, esta complexidade estava dentro de um método. Logo este precisou virar uma closure.

Imagine que estamos lidando com um método que é frequentemente alterado, como um cálculo de tarifa ou algo parecido e que é chamado por varias outras classes. Nesta situação, se alterássemos este método para uma closure, isso implicaria em um preenchimento desnecessário da PermGem, sem contar que iriamos inserir o memoize(), que seria um recurso desnecessário para a maioria dos casos. Logo estaríamos concertando de um lado para provavelmente estragar de outro.

Chega de revira volta!!! Vamos para o Show me the code!

Neste caso podemos utilizar “reference.&”, que recupera toda a lógica de um determinado método e a transforma em uma closure.

class SizeFilter {
    Integer limit
    boolean filter (String value) {
        return value.length() <= limit
    }
}

SizeFilter six = new SizeFilter(limit:6) //#1 Construtor

SizeFilter five = new SizeFilter(limit:5) //#1 Chamada

Closure smallerSix = six.&filter //#2 Associando o método à closure

def words = ['long string', 'medium', 'short', 'tiny']

assert 'medium' == words.find (smallerSix) //#3 Chamando a closure

assert 'short' == words.find (five.&filter) //#4 Passando a closure diretamente

Lembrando que os recursos fornecidos, raramente são para todas as situações. Logo, nada como uma boa análise antes de sairmos codificando.

Por fim, algo que chamou muito minha atenção, foi o fato de o “reference.&” também trabalhar em cima do polimorfismo conforme exemplo abaixo:

class MultiMethodSample{
    int mysterMethod(String value){
        return value.length()
    }
    int mysterMethod(List list){
        return list.size()
    }
    int mysterMethod(int x, int y){
        return x+y
    }
}

MultiMethodSample instance = new MultiMethodSample()
Closure multi = instance.&mysterMethod

assert 10 == multi ('string arg')
assert 3  == multi (['list', 'of', 'values'])
assert 14 == multi (6, 8)

Como podemos notar, o processamento da closure muda quando alteramos os parâmetros.

Espero ter ajudado com a dica e até os próximos posts.

Anúncios

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: