No meu artigo anterior
comentei sobre a importância de se escrever um código mais fluente,
legível e auto-explicativo. Muitas vezes são com pequenas ações que
podemos melhorar este aspecto sobre o código que escrevemos. Estas
pequenas ações são caracterizadas com um design bom, coeso e pouco
acoplado, bons nomes de classes e métodos, variáveis com nomes
significativos e código fluente, é claro.
Criar código fluente e claro pode ser especialmente desafiador. É fato
que certas linguagens facilitam ou dificultam esta tarefa e Java não é a
linguagem mais fluente do mundo, mas existem alternativas. No artigo anterior eu ensinei a criar uma DSL com Java sem nenhum framework e com bastante fluência.
Hoje quero comentar sobre a linguagem dinamica Groovy, que é a
referência padrão de linguagens dinâmicas para a JVM. Existem outras
bem funcionais e interessantes como JRuby, BeanShell, Jython, Scala e
tantas outras. Em especial hoje vou falar de Groovy. Por que? Porque como desenvolvedor Java este foi o primeiro contato com
linguagens dinâmicas sobre a JVM. Vejo de uma forma muito natural que, nos dias de hoje, o
desenvolvedor busque outras soluções que não sejam
unicamente dentro da linguagem Java. Mas de certa forma é muito claro
para mim que utilizar a JVM é um ótima idéia, usar linguagens dinâmicas
que rodam em cima da JVM e têm integração com Java e os principais
Frameworks existentes em Java com Spring e Hibernate é melhor ainda. E este é o caso do Groovy.
Groovy é um linguagem que roda em cima da JVM, então é claro e óbvio
que ela não é a linguagem mais performática do mundo, mas muitas vezes
o problema está em outro lugar, na persistência, no servidor, enfim…
não é o fato de a linguagem ser interpretada que deixa o seu uso inviável.
Por sinal, o Groovy pode ser usando tanto interpretado como um script ou
pode ser compilada pelo groovyc e rodar como uma class Java normal.
Java é OO e Groovy também. Porém o Groovy é híbrido e você pode
programar de forma procedural, o que de fato é muito útil para
construção de scripts e na própria produtividade.
Groovy possui várias vantagens, entre elas:
- Suporte nativo a Closures
- DRY
- Duck Typing
- GStrings
- Suporte nativo a Mapas e Listas
- Novas funcionalidades na API do Java
- Sobrecarga de operadores
- Operações Null-safe
Suporte nativo a Closures
Closures
são uma espécie de função mas livre de variáveis. Você pode passar
variáveis para um closure mais isso não está previamente definido na
assinatura da closure (comparando com um método), estas variáveis ficam
no corpo da implementação da closure. A idéia de Closures não é nada
nova, é de 1960,que por sinal já estava presente em linguagens como o
Lisp.
def somar = { va , vb -> <br /> println va + vb <br /> } <br /><br /> somar 1, 2O código acima mostra um exemplo simples de Closure em Groovy. Se
você executar este código no groovyConsole, por exemplo, vai aparecer 3
no console como resultado.
DRY
Don’t Repeat Yourself é um conceito bem interessante que as
novas soluções vêm implementado. Este conceito se baseia em limitar a
duplicação em todos os sentidos. Em Java sofremos muito com isso quando
usamos diversos frameworks baseados em XML (ex: clássico Spring,
Hibernate, Struts, web.xml, etc..). Mas este conceito não se aplica
apenas à parte de configuração. Este conceito aparece no The Pragmatic Programmer.
Bom, se você não leu este livro ainda, não perca tempo, compre agora e
leia o quanto antes. Neste caso, foco em DRY porque isto leva a um
código mais legível também e isso também foi incorporado ao Groovy.
package com.blogspot.diegopacheco.javapain;<br /><br />public class Pessoa{<br /><br /> private String nome;<br /> private Integer idade;<br /><br /> public Pessoa(){<br /><br /> }<br /><br /> public Pessoa(String nome,Integer idade){<br /> this.nome = nome;<br /> this.idade = idade;<br /> }<br /><br /> public String getNome(){<br /> return nome;<br /> }<br /><br /> public void setNome(String nome){<br /> this.nome = nome;<br /> }<br /><br /><br /> public Integer getIdade(){<br /> return idade;<br /> }<br /><br /> public void setIdade(Integer idade){<br /> this.idade = idade;<br /> }<br /><br /> public String toString(){<br /> return "Nome:" + nome + ", idade: " + idade;<br /> }<br /><br /> }
Este é um típico código que escrevemos em Java. Não vou entrar em
discussões mais DDD, modelo anêmico e tudo mais, isso é assunto para
outros artigos. Mas, mesmo com DDD, ainda existe a possibilidade de não
existirem validações e código de negócio nesta classe. Muitas vezes
fazemos métodos getters and setters, mas sem código dentro.
Este código acima é Java, mas funciona perfeitamente em Groovy. Porém em Groovy poderíamos fazer algo assim:
public class Pessoa{<br /><br /> def String nome;<br /> def Integer idade;<br /><br /> public Pessoa(){<br /><br /> }<br /><br /> public Pessoa(String nome,Integer idade){<br /> this.nome = nome;<br /> this.idade = idade;<br /> }<br /><br /> public String toString(){<br /> return "Nome:" + nome + ", idade: " + idade;<br /> }<br /><br />}<br /><br />Pessoa p = new Pessoa();<br />p.setNome("Diego Pacheco");<br />p.setIdade(25);<br />System.out.println(p);
Ok. Mas cadê os getters e setters? Isso compila? Roda sem levantar
Exceptions? Sim, compila e roda sem exceptions, funciona exatamente
igual ao código anterior, porém não precisamos escrever os códigos de
getters e setters, já que não temos regras nem validações lá. Isso pode
ficar ainda melhor, veja o outro código Groovy abaixo:
public class Pessoa{<br /><br /> def nome, idade;<br /><br /> public String toString(){<br /> return "Nome:" + nome + ", idade: " + idade;<br /> }<br /><br />}<br /><br />p = new Pessoa(nome: "Diego", idade: 25);<br />println p
Cadê o código dos construtores? Como que isso funciona? O Groovy
resolve estas questões para nós, tirando algumas coisinhas chatas da
linguagem Java e nos dando mais produtividade e legibilidade. Mas, vamos
melhorar mais? É possível?
public class Pessoa{<br /><br /> def nome, idade;<br /><br /> String toString(){<br /> "Nome: ${nome} idade: ${idade}"<br /> }<br /><br />}<br /><br />p = new Pessoa(nome: "Diego", idade: 25)<br />println p
Cadê o return? Onde estão as concatenações de Strings
usando o operador “+”? Bom, quanto ao return ele é opcional, o Groovy
assume que a última coisa que você escreveu é o retorno. Quanto às
Strings, talvez quem já foi programador PHP, como eu, possa entender
melhor. Este é o recurso chamado de GStrings. Que tal um pouco mais? Vamos lá, então.
class Pessoa {<br /> def nome, idade;<br />}<br /><br />Pessoa.metaClass.toString = {<br /> return "Nome: ${nome} idade: ${idade} . executou"<br />}<br /><br />println new Pessoa(nome: "Diego", idade: 25).toString()
Agora a classe Pessoa só tem atributos, desta vez estou adicionado um
método a uma classe existente (Pessoa) em tempo de execução. Eu estou
implementado o método toString e, acreditem, funciona. Como é possível?
Este é o Duck Typing em ação. Vamos ver mais…
def toString = { nome, idade -><br /> println "${nome} - ${idade}"<br />}<br /><br />toString "Diego", 25
Agora eu peguei o mesmo código que estava em uma classe e simplifiquei
mais ainda. Como? Colocando todo o código em uma Closure. Outra coisa
legal é que o “;” e os “(” e “)” são opcionais, pode colocar ou não que
vai funcionar.
Duck Typing
Na programação fortemente tipada, como é o caso do
Delphi, C e Java, ganhamos com algumas coisas mas perdemos em
flexibilidade, e muitas vezes o código é mais massivo e menos legível. Você costuma ter que escrever mais para dizer as suas intenções à
linguagem. Com tipagem forte, os métodos de um objeto são definidos
pelas sua classe superior (herança) e suas interfaces (além dos próprios
métodos) e isto é fixo, de certa forma. Com o Duck type isto depende do
estado corrente do objeto. Isso mesmo, pode ser que em determinado momento um objeto
Pessoa tenha 10 métodos e, em outro, tenha 15.
GStrings
É outro recurso fantástico do Groovy que dá muita
produtividade e simplicidade ao nosso código. Este é o recurso de ter
String no stilo PHP. Você usa o operador “$” com “{}” e pode colocar
uma variável ou expressão complexa dentro das chaves e ele resolve isso
tudo dentro da mesma String. Vamos ver mais um exemplo de código:
def x = 10;<br />println "Hoje eh: ${new java.util.Date().toString()} - ${x}"
Como você pode ver neste código, estou usando uma classe do Java no meio
da GString e também resolvendo uma variável Groovy. Neste caso, a
legibilidade do código fica muito maior também, mais simples e mais
divertido. 🙂
Suporte nativo a Mapas e Listas
Mais um grande recurso do
Groovy. Acredito que o próprio subtítulo já explique por si só o que
isso significa, mas vamos ver alguns códigos em Groovy para sentir na
prática o que eu estou falando.
def lista = [1,2,3,4,5,"Diego",'D',true,new Object(),{}]<br />lista.each {<br /> println it<br />}
No código acima estamos criando uma lista sem ter que instanciar uma
classe diretamente, isso é feito pelo Groovy. Depois, estou usando o
método each que a lista tem e passo um closure para que ele execute a
cada item que existe na lista. A variável implícita *it* representa a
variável corrente, neste caso o elemento da lista que está sendo iterado.
def lista = [1,2,3,4,5,"Diego",'D',true,new Object(),{}]<br /><br />lista += 6 // adiciona o item 6 a lista<br />lista -= 1 // remove o item 1 da lista <br />lista << 7 // adiciona o item 7 a lista<br /></p><p><br />lista.findAll { it == "Diego" }.each {<br /> println it<br />}
Neste código, eu adiciono e removo itens da lista, no final faço
um código para procurar na lista um elemento chamado “Diego”,
percorro este resultado e imprimo na tela no final. Vamos ver o
suporte a mapas agora.
def mapa = [1: "Diego", 2: "Bruna", 3: "Pog"]<br />mapa.each{ k, v -><br /> println "Chave: ${k} - valor: ${v}"<br />}
Neste código criei um mapa e adicionei as chaves 1, 2 e 3 com os
valores Diego, Bruna e Pog. Depois usei a função each e percorri todo o
mapa mostrando as chaves e valores. Vamos ver mais algumas coisas de
mapas de forma diferente agora:
def mapa = [1: "Diego", 2: "Bruna", 3: "Pog"]<br /><br />mapa += [4: "teste"]<br /><br />mapa.each{<br /> println "Chave: ${it.key} - valor: ${it.value}"<br />}
Adiciono um item ao mapa de maneira muito fácil e igual a da
lista e desta vez percorro o mapa com o *it* implicito do
Groovy.
Novas funcionalidades na API do Java
Bom, algumas coisas vocês já
viram, como os métodos *each*, *findAll*. Existem outros métodos bem
úteis, como, por exemplo, quando você trabalha com File existe o método
eachFile para percorrer todos os Files de um File pai. Confira também
as seguintes formas de loop:
array = (0..4).toArray()<br /> x = 0<br /> for ( i in array ) {<br /> x += i<br /> }<br /><br /> x = 0<br /> for ( i in [0, 1, 2, 3, 4] ) {<br /> x += i<br /> }Outra coisa legal é o Switch para Strings, confira o código Groovy abaixo:
String nome = "Diego"<br />switch(nome){<br /> case "joao":<br /> println "teste 1"<br /> break<br /> case "Diego":<br /> println "teste 2" <br /> break<br />}Operadores
É um dos recursos mais fantásticos do
Groovy. Com isso, a legibilidade e \ fluência ficam em alta mesmo. Isso
pode ser feito não apenas com números, mas com qualquer classe. Veja o
código abaixo:
class Pessoa{<br /> def nome, namorado<br /><br /> def leftShift(n){<br /> namorado = n<br /> }<br /><br /> def mostrarDados(){<br /> println "Nome: ${nome} Namora: ${namorado.nome}"<br /> }<br />}<br /><br />def p1 = new Pessoa(nome: "Diego")<br />def p2 = new Pessoa(nome: "Bruna")<br /><br />p1 << p2<br />p1.mostrarDados()Operações Null-safe
Quem gosta de ver um bom NPE (Null Pointer
Exception) na tela? A solução para isso é fazer diversos ifs para
testar o estado dos objetos antes de acessar seus métodos e propriedades. Porém, com Groovy isto não é necessário, pois existe um
operador para isso, basta colocar o “?” na frente que tudo se resolve.
class Pessoa{<br /> def show = {<br /> println "groovy show"<br /> }<br />}<br /><br />def p = new Pessoa()<br />def x = null<br /><br />p.show()<br />x?.show()
Bom, pessoal, e ainda existe muito mais a se falar. O legal do Groovy é isso,
estas novas funcionalidades, facilidades, integração com Java. Basta
colocar um jar na sua aplicação e pronto você já pode aproveitar tudo
isso.
Fiz uma apresentação sobre este assunto, confira no meu slide-share:
View more presentations from Diego Pacheco.







