© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Introducción a Groovy
2© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Acerca del presentador
Desarrollador Java desde 1996 Fan de Groovy desde 2006 dado que a veces Java
estorbaba Miembro del equipo Groovy desde Agosto 2007 Fundador de proyectos como JideBuilder,
GraphicsBuilder, WingSBuilder, Grapplet y Json-lib
3© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Agenda
Qué es Groovy? De Java a Groovy Características I (cerca de casa) Características II (explorando el vecindario) Características III (al infinito y mas allá!) Groovy & Spring
4© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Que es Groovy?
Groovy es un lenguage ágil y dinámico para la Máquina Virtual de Java
Basado en los conceptos base del lenguage Java, incluye características inspiradas en otros lenguages como Python, Ruby y Smalltalk.
Habilita características de programación modernas con una curva de aprendizaje prácticamente plana para desarrolladores Java
Soporta Lenguages de Dominio Específico y otras carcaterísticas de syntaxis corta
5© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Que es Groovy?
Simplifica el ciclo de pruebas dado que soporta pruebas unitarias y mocking desde el inicio.
Se integra sin problemas con cualquier objecto y/o librería Java existentes
Compila directamente a código byte (igual que Java) puede ser usado virtualmente en cualquier lugar donde Java puede serlo también
© 2008 Andres Almiray; disponible bajo CC-SA 2.5
De Java a Groovy
7© 2008 Andres Almiray; disponible bajo CC-SA 2.5
HolaMundo en Java
public class HelloWorld { String name;
public void setName(String name) { this.name = name; } public String getName(){ return name; }
public String greet() { return “Hello “+ name; }
public static void main(String args[]){ HelloWorld helloWorld = new HelloWorld() helloWorld.setName(“Groovy”) System.err.println( helloWorld.greet() ) }}
8© 2008 Andres Almiray; disponible bajo CC-SA 2.5
HolaMundo en Groovy
public class HelloWorld { String name;
public void setName(String name) { this.name = name; } public String getName(){ return name; }
public String greet() { return “Hello “+ name; }
public static void main(String args[]){ HelloWorld helloWorld = new HelloWorld() helloWorld.setName(“Groovy”) System.err.println( helloWorld.greet() ) }}
9© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Paso 1: Adios a lo obvio
Toda clase, método, campo en Groovy tiene acceso público a menos de que se especifique lo contrario
';' es opcional al final de línea en la mayoría de los casos
10© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Paso 1: Resultado
class HelloWorld { String name
void setName(String name) { this.name = name } String getName(){ return name }
String greet() { return "Hello "+ name }
static void main(String args[]){ HelloWorld helloWorld = new HelloWorld() helloWorld.setName("Groovy") System.err.println( helloWorld.greet() ) }}
11© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Paso 2: Adios a lo ceremonioso
Neal Ford proclama que el debate estático vs dinámico es en realidad ceremonia vs esencia
Según la convención JavaBeans, cada propiedad requiere de un par de métodos (get/set)
El método main() siempre require de String[] como parámetro
Imprimir a consola es muy común, acaso existe alguna manera mas corta?
12© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Paso 2: Resultado
class HelloWorld { String name
String greet() { return "Hello "+ name }
static void main( args ){ HelloWorld helloWorld = new HelloWorld() helloWorld.setName("Groovy") println( helloWorld.greet() ) }}
13© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Paso 3: Tipos dinámicos
La palabra reservada def se usa cuando no es necesario indicar el tipo específico de una variable, método o campo (es como var en JavaScript)
Groovy averiguará el tipo correcto en tiempo de ejecución, esto habilita entre otras cosas lo que se conoce como duck typing
14© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Paso 3: Resultado
class HelloWorld { String name
def greet() { return "Hello "+ name }
static def main( args ){ def helloWorld = new HelloWorld() helloWorld.setName("Groovy") println( helloWorld.greet() ) }}
15© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Paso 4: Usar interpolación de variables
Groovy permite la interpolación de variables a través de GStrings (similar a como lo hace Perl)
Basta con rodear una expresión con ${} en cualquier String
16© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Paso 4: Resultado
class HelloWorld { String name
def greet(){ return "Hello ${name}" }
static def main( args ){ def helloWorld = new HelloWorld() helloWorld.setName("Groovy") println( helloWorld.greet() ) }}
17© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Paso 5: Adios a otras palabras reservadas
La palabra return es opcional en muchos de los casos, el valor de retorno será el valor de la última expresión evaluada en el contexto
La palabra def no es necesaria cuando se trata de métodos estáticos
18© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Paso 5: Resultado
class HelloWorld { String name
def greet(){ "Hello ${name}" }
static main( args ){ def he new HelloWorld() helloWorld.setName("Groovy") println( helloWorld.greet() ) }}
// OJO versiones anteriores del plugin de Groovy para Eclipse
// requieren que exista el método main definido de la siguiente
// manera//// static void main( String[] args )
19© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Paso 6: POJOs con esteroides
Los POJOs (o POGOs en Groovy) tienen un constructor por omisión que acepta un Map, dando la impresión de usar parámetros con nombres
Los POGOs suportan la notación de arreglo (bean[prop]) o la notación de objeto (bean.prop) para acceder a sus propiedades (lectura/escritura)
20© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Paso 6: Resultado
class HelloWorld { String name
def greet(){ "Hello ${name}" }
static main( args ){ def helloWorld = new HelloWorld(name:"Groovy") helloWorld.name = "Groovy" helloWorld["name"] = "Groovy" println( helloWorld.greet() ) }}
21© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Paso 7: Groovy soporta scripts
A pesar de que Groovy compila a código byte, soporta programas tipo script, los cuales también se compilan a código byte
Todo Script permite definir clases en cualquier parte
Todo script soporta definición de paquetes (package) puesto que al fin y al cabo también son clases Java
22© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Paso 7: Resultado
class HelloWorld { String name def greet() { "Hello $name" }}
def helloWorld = new HelloWorld(name:"Groovy")println helloWorld.greet()
23© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Venimos desde aquí...
public class HelloWorld { String name;
public void setName(String name) { this.name = name; } public String getName(){ return name; }
public String greet() { return "Hello "+ name; }
public static void main(String args[]){ HelloWorld helloWorld = new HelloWorld() helloWorld.setName("Groovy") System.err.println( helloWorld.greet() ) }}
24© 2008 Andres Almiray; disponible bajo CC-SA 2.5
... hasta acá
class HelloWorld { String name def greet() { "Hello $name" }}
def helloWorld = new HelloWorld(name:"Groovy")println helloWorld.greet()
© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Características I (cerca de casa)
26© 2008 Andres Almiray; disponible bajo CC-SA 2.5
El lema es ...
Java es Groovy, Groovy es Java
Groovy ofrece una curva de aprendizaje sencilla para desarrolladores Java. Puedes empezar con sintaxis Java y moverte poco a poc a la sintaxis Groovy
98% de código Java es código Groovy, virtualmente podrías renombar un archivo *.java a .groovy y compilaría
27© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Problemas comunes
La sintaxis de Groovy no es un super-conjunto exacto de la sintaxis de Java dado que no soporta
Inicializadores literales de arreglos int[] arreglo = { 1,2,3 }
definición de clases internas instanciar clases internas no estáticas
A.B ab = instanciaA.new B()
28© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Características I - JDK5
Groovy soporta anotaciones (JSR 175) iguales a las de Java, es mas, es el segundo lenguage en la JVM que las soporta.
hasta el momento no es definir anotaciones con Groovy
Groovy soporta Enums también Por último también tiene habilitado el soporte de
tipos genéricos, iguales a los de Java.
29© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Características I - JDK5
Es posible hacer uso de número de argumentos variables (varargs) mediante dos formas
notación triple punto (JDK5) último argumento es de tipo Object[]
30© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Varargs en acción
class Calculator { def addAllGroovy( Object[] args ){ int total = 0 for( i in args ) { total += i } total } def addAllJava( int... args ){ int total = 0 for( i in args ) { total += i } total }}
Calculator c = new Calculator()assert c.addAllGroovy(1,2,3,4,5) == 15assert c.addAllJava(1,2,3,4,5) == 15
© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Características II (explorando el vecindario)
32© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Miscelaneos Parámetros con valor por omisión (PHP) Parámetros con nombre (Ruby), en realidad no
hay tales, pero se puede reusar el truco del constructor por omisión de los POGOs)
Sobrecarga de operadores através de convención de nombres+ plus()
[] getAt() / putAt()
<< leftShift()
33© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Closures
Closures pueden ser interpretadas como bloques de código reusable, probablemente las hayas visto en otros lenguages como JavaScript o Ruby
Closures substituyen a las clases internas en la mayoría de los casos
Groovy permite “forzar el tipo” de una Closure a una interface de 1 solo método (proxy)
Una closure tendrá un parámetro por omisión llamado it si es que no se defined parámetros para la misma
34© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Ejemplos de Closures
def greet = { name -> println “Hello $name” }greet( “Groovy” )// prints Hello Groovy
def greet = { println “Hello $it” }greet( “Groovy” )// prints Hello Groovy
def iCanHaveTypedParametersToo = { int x, int y -> println “coordinates are ($x,$y)”}
def myActionListener = { event -> // do something cool with event} as ActionListener
35© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Currying
Currying es una técnica de programación que transforma una función (o closure) de número de parámetros m a otra función con número de parámetros n, donde m > n, es decir reduce el número de parámetros, el valor de cada parámetro reducido queda fijado y no puede cambiarse
36© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Currying en acción
// un closure con 3 parámetros, el tercero es opcional dado// que define un valor por omisióndef getSlope = { x, y, b = 0 -> println "x:${x} y:${y} b:${b}" (y - b) / x}
assert 1 == getSlope( 2, 2 )def getSlopeX = getSlope.curry(5)assert 1 == getSlopeX(5)assert 0 == getSlopeX(2.5,2.5)// prints// x:2 y:2 b:0// x:5 y:5 b:0// x:5 y:2.5 b:2.5
37© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Iteradores por doquier
Asi como en Ruby, puedes hacer uso de iteradores prácticamente en cualquier contexto
Los iteradores dependen del poder que otrogan las closures, básicamente todos soportan el uso de closures como parámetros
Los iteradores literalmente dejan obsoletos a las operaciones de ciclos
38© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Iteradores en acción
def printIt = { println it }// 3 ways to iterate from 1 to 5[1,2,3,4,5].each printIt1.upto 5, printIt(1..5).each printIt
// compare to a regular loopfor( i in [1,2,3,4,5] ) printIt(i)// same thing but use a Rangefor( i in (1..5) ) printIt(i)
[1,2,3,4,5].eachWithIndex { v, i -> println "list[$i] => $v" }
// list[0] => 1// list[1] => 2// list[2] => 3// list[3] => 4// list[4] => 5
© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Características III (al infinito y mas allá!)
40© 2008 Andres Almiray; disponible bajo CC-SA 2.5
La palabra reservada as
Permite “Groovy casting”, es decir, convertir un valor de tipoA a tipoBdef intarray = [1,2,3] as int[ ]
Permite forzar (coerce) un closure a una implemnetación anónima de una interface de un solo método
Permite forzar (coerce) un Map a una implementación de interface, clase abstracta o concreta
Permite crear alias en sentencias de importación
41© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Algunos ejemplos de as
import javax.swing.table.DefaultTableCellRenderer as DTCR
def myActionListener = { event -> // do something cool with event} as ActionListener
def renderer = [ getTableCellRendererComponent: { t, v, s, f, r, c -> // cool renderer code goes here }] as DTCR
// Nota esta técnica es similar a crear objetos en JavaScript
// con la notación JSON
42© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Nuevos operadores
?: (elvis) - un refinamiento del operador ternario
?. referencia segura – permite navegar un grafo de objetos sin temor a NPE
<=> (spaceship) – compara dos valores
* (spread) – expande el contenido de una lista
*. (spread-dot) – aplica el método a todos los elementos de una lista
43© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Navegando grafos de objetos
GPath es a objetos lo que XPath es a XML
*. y ?. son bastante útiles en esta situación
Escribir expresiones Gpath es muy sencillo dado que los POGOs aceptan notación de punto y arreglo
44© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Ejemplos de GPath
class Person { String name int id}
def persons = [ new Person( name: 'Duke', id: 1 ), [name: 'Tux', id: 2] as Person]
assert [1,2] == persons.idassert ['Duke','Tux'] == persons*.getName()assert null == persons[2]?.nameassert 'Duke' == persons[0].name ?: 'Groovy'assert 'Groovy' == persons[2]?.name ?: 'Groovy'
45© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Metaprogramación
Puedes agregar métodos y propiedades a un objeto en tiempo de ejecución
Puedes interceptar llamadas a métodos o acceso de propiedades (similar a AOP pero sin tanto problema)
Esto significa que Groovy ofrece un concepto similar a las clases abiertas en Ruby, es mas Groovy extiende clases finales como String e Integer
46© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Ejemplo con categorías
class Pouncer { static pounce( Integer self ){ def s = “Boing!" 1.upto(self-1) { s += " boing!" } s + "!" }}
use( Pouncer ){ assert 3.pounce() == “Boing! boing! boing!"}
47© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Ejemplo con Metaclases
Integer.metaClass.pounce << { -> def s = “Boing!" delegate.upto(delegate-1) { s += " boing!" } s + "!“}
assert 3.pounce() == “Boing! boing! boing!"
© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Groovy y Spring
49© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Varias Alternativas
Compilar el código Groovy a código byte Usar el módulo lang para referencia un
archivo/script groovy Insertar un script en la definición del contexto de
aplicación (XML)
50© 2008 Andres Almiray; disponible bajo CC-SA 2.5
1. Compilar Groovy
El compilador de Groovy puede ser invocado de distintas maneras
comando groovyc mediante una tarea de Ant (Groovyc) mediante Gmaven, plugin para Maven2 Usando Gant (Groovy + Ant) plugins para IDEs (Eclipse, IDEA, NetBeans)
51© 2008 Andres Almiray; disponible bajo CC-SA 2.5
2. El módulo lang
Requiere el uso del schema spring-lang Se recomienda usar ApplicationContext, también
se puede usar BeanFactory pero hay mas trabajo manual que realizar
La Inyección de Dependencias funciona de la misma manera
52© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Referencia a clase Groovy
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/langhttp://www.springframework.org/schema/lang/spring-lang-2.5.xsd">
<lang:groovy id="messenger" script-source="classpath:Messenger.groovy">
<lang:property name="message" value="Hola Mundo!" />
</lang:groovy>
<bean id="bookingService" class="x.y.DefaultBookingService">
<property name="messenger" ref="messenger" />
</bean>
</beans>
53© 2008 Andres Almiray; disponible bajo CC-SA 2.5
3. Scripts en línea
Requiere las mismas características que la opción anterior
Útil para crear implementaciones de clases ayundates como validadores
54© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Ejemplo
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/langhttp://www.springframework.org/schema/lang/spring-lang-2.5.xsd">
<lang:groovy id="messenger">
<lang:inline-script>
class GroovyMessenger implements Messenger { String message }
</lang:inline-script>
<lang:property name="message" value="Hola Mundo!" />
</lang:groovy>
</beans>
© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Preguntas y Respuestas
56© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Información adicional
Groovy, guías, ejemploshttp://groovy.codehaus.org
Groovy Eclipse Pluginhttp://groovy.codehaus.org/Eclipse+Plugin
Noticias Groovyhttp://aboutgroovy.comhttp://groovyblogs.orghttp://groovy.dzone.comhttp://groovy.org.es
Mi blog sobre Groovy/Java/Swinghttp://jroller.com/aalmiray
© 2008 Andres Almiray; disponible bajo CC-SA 2.5
Gracias!
Top Related