Introduccion A Groovy

Preview:

DESCRIPTION

Presentación introductoria a Groovy en la primera reunión de la comunidad Springhispano.org

Citation preview

© 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!