Grails - Destaques
...para quem já sabe Java
Douglas de Oliveira Mendes
Grails - Destaques
Baseado no livro "Programming Grails" de Burt
Beckwith
Groovy + Spring + Hibernate + "Convention
over configuration" + ...
Esta apresentação é mais focada na diferença do código-fonte, mas saiba que
Grails juntou muito bem frameworks bastante utilizados pela comunidade Java
(especialmente Spring e Hibernate).
Graças ao dialeto Groovy e à prática de "convenção sobre configuração" o
resultado é um código-fonte bem mais conciso.
Vamos ao que interessa...
"Reflection" fácil de usar
String methodName = …
def value = person."$methodName"(1, 2)
String propertyName = …
def otherValue = person."$propertyName"
Mapas são LinkedHashMap
...ao invés de java.util.HashMap para assim
manter a ordem dos elementos.
def map = [red:1, blue:2]
Se precisar de outro tipo de mapa é só
instanciar como é feito no Java.
Getters e setters
Basta acessar a propriedade diretamente. Ex.:
cliente.nome
O getter vai ser invocado quando estiver lendo
o valor e o setter quando estiver atribuindo um
novo valor.
Getters e setters
Não é necessário (mas é permitido e serão
chamados se existirem) implementar métodos
getters e setters. Ex.:
void setNome(String nome) {
this.nome = nome.trim();
}
Debaixo do capô
AST Browser
JD-GUI
Para entender o código gerado.
Closure
Pedaço de código que pode ser atribuído a uma
variável. Pode ser passado como parâmetro e
invocado dentro de métodos.
Lembra uma classe anônima porém sem
precisar implementar uma Interface. Nota: eles
podem acessar variáveis não "final" fora de seu
escopo.
Closure
Ex.:
def hello = { println "hello" }
hello()
Closure
É um jeito prático de implementar interfaces
sem precisar definir todos os métodos (útil em
testes por exemplo):
def conn = [
close: { -> println "closed},
setAutoCommit: { boolean autoCommit -> println "autoCommit:
$autoCommit" }
] as java.sql.Connection
Closure
Trabalhando com parâmetros:
def add { int x, int y -> x + y }
getMaximumNumberofParameters()
getParameterTypes()
Loops
int count = someCalculation()
for (int i = 0; i < count; i++) {
…
}
Loops
someCalculation().times {
…
}
Loops
for (i in 0..someCalculation() - 1) {
…
}
Comparando objetos
O sinal "==" funciona diferente do Java pois ele
compara os valores.
Para saber se ambas as referências apontam
para o mesmo objeto, utilizar:
foo.is(bar)
Invocação de método de acordo com
tipo to parâmetro
void close(Connection c) {
…
}
void close(Object o) {
...
}
Invocação de método de acordo com
tipo to parâmetro
No Java este código invocaria close(Object):
Object connection = createConnection();
close(connection);
No groovy seria chamado o close(Connection)
porque seria resolvido em Runtime.
Groovy Strings
Multilinhas (com três aspas):
def name = "Carl Sagan"
def texto = """
Caro $name,
Não esqueça de alimentar os gatinhos."""
'this' funciona para acesso estático
ex.:
private static final Logger LOG = Logger.getLogger(this)
Metaprogramming
Adicionando um método:
List.metaClass.removeRight = {
int index -> delegate.remove(delegate.size() - 1 - index)
}
Metaprogramming
É possível sobrescrever métodos como:
- invokeMethod
- getProperty
- setProperty
- methodMissing
- propertyMissing
Metaprogramming
Ex. de sobrescrita do invokeMethod:
def methodMissing(String methodName, args) {
println "papagaio - $methodName"
}
Operadores: ?.
Acesso null-safe (se "person" for null o valor
atribuído será null ao invés de dar
NullPointerException):
String name = person?.name
Operadores: ?:
?: é operador "Elvis" que encurta ternários. Você já fez algo
assim em Java?
Integer qtd = qtdParam ? qtdParam : 10
Com grails você pode fazer assim:
Integer qtd = qtdParam ?: 10
Operadores: *.
*. é o "spread". Se você quer todos os nomes de
clientes de um array você pode fazer assim:
String[] nomes = clientes*.nome
Operadores: .@
Como já vimos, ao acessar "cliente.nome" o método
getNome (ou setNome se for atribuição) é chamado
automaticamente.
Se desejar evitar por exemplo o getNome e acessar
diretamente a propriedade, utilize o operador .@. Ex.:
cliente.@nome
Operadores: as
Facilita escolha do tipo de estrutura de dados. Por ex. criar
um Set ao invés de um List:
def things = ['a', 'b', 'b', 'c'] as Set
assert things.getClass().simpleName == 'HashSet'
assert things.size() == 3
Operadores: in
Similar a chamar o método "contains":
assert 1 in [1, 2, 5]
Operadores: .&
Permite tratar um método como um closure
(podendo assim passar a referência do método
como parâmetro). Ex.:
def add = new MathUtils().&add
add(x, y)
Operadores: sobrecarga
Basta implementar os respectivos métodos:
a + b -> a.plus(b)
a++ -> a.next()
a << b -> a.leftShift(b)
...
Groovy "demais"...
def foo = bar(5, true) // o que é "foo"??
def fazAlgo() {...} // O que fazAlgo retorna? É void? Por que
não declará-lo como void?
def fazAlgo = {} // Definir métodos como closure ao invés
da declaração normal pode fazê-lo ficar de fora de
interceptações como por exemplo quando o Spring está
marcando os métodos como transacionais.
Linguagem dinâmica permite mais
bugs...
int hc = someObject.hashcode()
Se o método na verdade se chama hashCode só saberemos
na hora que o código for executado, não quando for
compilado. Testes deveriam nos prevenir destes casos.
As anotações @TypeChecked e @CompileStatic ajudam
nestes casos e melhoram desempenho do código porém há
perda de flexibilidade (por ex. metaprogramming).

Grails - Destaques (para quem já sabe Java)

  • 1.
    Grails - Destaques ...paraquem já sabe Java Douglas de Oliveira Mendes
  • 2.
    Grails - Destaques Baseadono livro "Programming Grails" de Burt Beckwith
  • 3.
    Groovy + Spring+ Hibernate + "Convention over configuration" + ... Esta apresentação é mais focada na diferença do código-fonte, mas saiba que Grails juntou muito bem frameworks bastante utilizados pela comunidade Java (especialmente Spring e Hibernate). Graças ao dialeto Groovy e à prática de "convenção sobre configuração" o resultado é um código-fonte bem mais conciso. Vamos ao que interessa...
  • 4.
    "Reflection" fácil deusar String methodName = … def value = person."$methodName"(1, 2) String propertyName = … def otherValue = person."$propertyName"
  • 5.
    Mapas são LinkedHashMap ...aoinvés de java.util.HashMap para assim manter a ordem dos elementos. def map = [red:1, blue:2] Se precisar de outro tipo de mapa é só instanciar como é feito no Java.
  • 6.
    Getters e setters Bastaacessar a propriedade diretamente. Ex.: cliente.nome O getter vai ser invocado quando estiver lendo o valor e o setter quando estiver atribuindo um novo valor.
  • 7.
    Getters e setters Nãoé necessário (mas é permitido e serão chamados se existirem) implementar métodos getters e setters. Ex.: void setNome(String nome) { this.nome = nome.trim(); }
  • 8.
    Debaixo do capô ASTBrowser JD-GUI Para entender o código gerado.
  • 9.
    Closure Pedaço de códigoque pode ser atribuído a uma variável. Pode ser passado como parâmetro e invocado dentro de métodos. Lembra uma classe anônima porém sem precisar implementar uma Interface. Nota: eles podem acessar variáveis não "final" fora de seu escopo.
  • 10.
    Closure Ex.: def hello ={ println "hello" } hello()
  • 11.
    Closure É um jeitoprático de implementar interfaces sem precisar definir todos os métodos (útil em testes por exemplo): def conn = [ close: { -> println "closed}, setAutoCommit: { boolean autoCommit -> println "autoCommit: $autoCommit" } ] as java.sql.Connection
  • 12.
    Closure Trabalhando com parâmetros: defadd { int x, int y -> x + y } getMaximumNumberofParameters() getParameterTypes()
  • 13.
    Loops int count =someCalculation() for (int i = 0; i < count; i++) { … }
  • 14.
  • 15.
    Loops for (i in0..someCalculation() - 1) { … }
  • 16.
    Comparando objetos O sinal"==" funciona diferente do Java pois ele compara os valores. Para saber se ambas as referências apontam para o mesmo objeto, utilizar: foo.is(bar)
  • 17.
    Invocação de métodode acordo com tipo to parâmetro void close(Connection c) { … } void close(Object o) { ... }
  • 18.
    Invocação de métodode acordo com tipo to parâmetro No Java este código invocaria close(Object): Object connection = createConnection(); close(connection); No groovy seria chamado o close(Connection) porque seria resolvido em Runtime.
  • 19.
    Groovy Strings Multilinhas (comtrês aspas): def name = "Carl Sagan" def texto = """ Caro $name, Não esqueça de alimentar os gatinhos."""
  • 20.
    'this' funciona paraacesso estático ex.: private static final Logger LOG = Logger.getLogger(this)
  • 21.
    Metaprogramming Adicionando um método: List.metaClass.removeRight= { int index -> delegate.remove(delegate.size() - 1 - index) }
  • 22.
    Metaprogramming É possível sobrescrevermétodos como: - invokeMethod - getProperty - setProperty - methodMissing - propertyMissing
  • 23.
    Metaprogramming Ex. de sobrescritado invokeMethod: def methodMissing(String methodName, args) { println "papagaio - $methodName" }
  • 24.
    Operadores: ?. Acesso null-safe(se "person" for null o valor atribuído será null ao invés de dar NullPointerException): String name = person?.name
  • 25.
    Operadores: ?: ?: éoperador "Elvis" que encurta ternários. Você já fez algo assim em Java? Integer qtd = qtdParam ? qtdParam : 10 Com grails você pode fazer assim: Integer qtd = qtdParam ?: 10
  • 26.
    Operadores: *. *. éo "spread". Se você quer todos os nomes de clientes de um array você pode fazer assim: String[] nomes = clientes*.nome
  • 27.
    Operadores: .@ Como jávimos, ao acessar "cliente.nome" o método getNome (ou setNome se for atribuição) é chamado automaticamente. Se desejar evitar por exemplo o getNome e acessar diretamente a propriedade, utilize o operador .@. Ex.: cliente.@nome
  • 28.
    Operadores: as Facilita escolhado tipo de estrutura de dados. Por ex. criar um Set ao invés de um List: def things = ['a', 'b', 'b', 'c'] as Set assert things.getClass().simpleName == 'HashSet' assert things.size() == 3
  • 29.
    Operadores: in Similar achamar o método "contains": assert 1 in [1, 2, 5]
  • 30.
    Operadores: .& Permite tratarum método como um closure (podendo assim passar a referência do método como parâmetro). Ex.: def add = new MathUtils().&add add(x, y)
  • 31.
    Operadores: sobrecarga Basta implementaros respectivos métodos: a + b -> a.plus(b) a++ -> a.next() a << b -> a.leftShift(b) ...
  • 32.
    Groovy "demais"... def foo= bar(5, true) // o que é "foo"?? def fazAlgo() {...} // O que fazAlgo retorna? É void? Por que não declará-lo como void? def fazAlgo = {} // Definir métodos como closure ao invés da declaração normal pode fazê-lo ficar de fora de interceptações como por exemplo quando o Spring está marcando os métodos como transacionais.
  • 33.
    Linguagem dinâmica permitemais bugs... int hc = someObject.hashcode() Se o método na verdade se chama hashCode só saberemos na hora que o código for executado, não quando for compilado. Testes deveriam nos prevenir destes casos. As anotações @TypeChecked e @CompileStatic ajudam nestes casos e melhoram desempenho do código porém há perda de flexibilidade (por ex. metaprogramming).