Groovy
En este apartado, se va a profundizar en los aspectos más relevantes de Groovy mediante descripciones y ejemplos. No se puede considerar este apartado como un manual de usuario de Groovy, más bien como un pequeño tutorial de introducción a éste potente lenguaje de scripting.
En algunos de estos ejemplos se hará una comparativa directa con Java con el objetivo de demostrar la disminución de código entre uno y otro.
- Primeros pasos: “Hola Mundo”
Queremos que Groovy imprima por pantalla una cadena de caracteres con la información “Hola Mundo”. Gracias a la compatibilidad de Groovy con el lenguaje Java se podría implementar este problema de la misma manera que lo haríamos en Java, pero al ser un lenguaje de Scripting no sería necesaria la creación de una clase, con solo introducir la instrucción de imprimir por pantalla sería suficiente.
public class HolaMundo{
public static void main(String[] args){
System.out.println(“Hola Mundo”);
}
}
-----------------------------------------------
println “Hola Mundo”
La diferencia de cantidad de código es abrumadora, pero existen otras implementaciones con el mismo objetivo.
class HolaMundo{
def hiWorld(name){
“Hola ${name}”
}
}
def hW = new HolaMundo()
println hW.hiWorld(“Mundo”)
Con esta implementación podemos observar algunas de las características de Groovy:
- El valor de retorno no es específico, por lo que usamos la palabra reservada def (muy parecida a la palabra var de JavaScript)
- No es necesario utilizar la palabra reservada return, la última sentencia ejecutada determina el valor de retorno.
- La cadena de caracteres no es un java.lang.string, se trata de un GString. Los GStrings permiten la evaluación de expresiones, al igual que con Perl.
- Tipos de datos
Groovy soporta todos los tipos de datos de Java, sin primitivos, y además define listas y mapas como tipos básicos, así como los arrays y hashs de Perl y PHP. Erealidad las listas son en el fondo java.util.ArrayList y los mapas java.util.HashMap, por lo que se podrán utilizatodos los métodos ya conocidos en Java relacionados conlistas y mapas. Además, Groovy permite que los índices llaves sean manipulados a través del operador ‘[]’, y en elcaso de los mapas también mediante ‘.’.
<-- Números -->
def x = 12
def y = 10.0e4
<-- Caracteres y Strings -->
def c = “a”
def s = “hi World!”
<-- Listas y Mapas -->
def list = [1,2,3,4]
def map= [“Jon”:”Matthers”, “1”:”Mark”]
<-- Rangos -->
def rg = (0..9)
<-- Impresión de rangos -->
rg.each{num -> print num}
Como podemos observar, la definición de variables en Groovy no implica una definición primitiva, el contenido de la variable especifica el tipo de dicha variable. En la última descripción, podemos observar el método de recorrido de los rangos, el cuál puede ser aplicado en más tipos de variables, además nos introduce en un nuevo concepto de Groovy, que ha sido adoptado por la nueva implementación de Java 7, las closures.
- Closures
Una closure se podría describir como un bloque de código reutilizable, que retiene la información entorno donde fueron definidos.
Esta forma de trabajo es muy parecida a JavaScript, ya que es muy parecido a la definición de una función anónima en un script. Las closures pueden recibir parámetros, puesto que los tipos de Groovy son opcionales, sólo es necesario escribir el nombre del parámetro. El uso de closures es tan común, que si no se ha definido un parámetro específico de todos modos estará disponible una variable it que representa el valor del parámetro.
Esta forma de trabajo es muy parecida a JavaScript, ya que es muy parecido a la definición de una función anónima en un script. Las closures pueden recibir parámetros, puesto que los tipos de Groovy son opcionales, sólo es necesario escribir el nombre del parámetro. El uso de closures es tan común, que si no se ha definido un parámetro específico de todos modos estará disponible una variable it que representa el valor del parámetro.
def printOut = {item -> print item}
(0..9).each(printout)
-----------------------------------------------
def printOut = {print it}
(0..9).each(printout)
La implementación de las closures implica un gran avance en el mundo de la programación, ya que no es necesario crear un nuevo método fuera del actual pudiendo utilizar las variables locales del actual.
- Expresiones regulares
Como muchos lenguajes de scripting, Groovy también ofrece la posibilidad de utilizar expresiones regulares, es decir, declarar y utilizar dichas expresiones sin necesidad de construcciones complexas o añadir sintaxis adicionales a las construcciones básicas del lenguaje.
Basta con declarar la expresión de búsqueda entre barras diagonales y usar uno de los tres operadores disponibles:
Basta con declarar la expresión de búsqueda entre barras diagonales y usar uno de los tres operadores disponibles:
- =~ búsqueda de ocurrencias
- ==~ coincidencias
- ~ patrón
def text = “At school, Harry had no one. Everybody know
that Dudley’s gang hated that odd Harry
Potter” + “ in his baggy old clothes and
broken glasses, and nobody liked to disagree
with Dudley’s gang.”
matcher = (text =~ /Harry Potter/)
-----------------------------------------------
matcher = (text ==~ /Harry/)
-----------------------------------------------
matcher = (text ~ /H.*y/)
- POJOs to POGOs
En los últimos años Sun a dominado el sector de JavaBeans gracias al resurgimiento de los POJOs (Plain Old Java Objects), es decir, un subconjunto de la convención JavaBeans. Los POJOs son un subconjunto puesto que los JavaBeans deben notificar cualquier cambio que se realice en alguna de sus propiedades, mientras que los POJOs no lo hacen. Spring y Hibernate no dudaron sobre las ventajas de uso, y no tardaron en incorporarlo en su implementación. El único pero que tenían los POJOs era su complicada implementación, este apartado fue resuelto gracias a que algunos Ambientes de Desarrollo Integrados (IDE) comenzaron a proporcionar herramientas para generar este tipo de código.
Pero los POGOs van más allá, simplemente con declarar las propiedades según la convención, los métodos de acceso se generarán. Dichas propiedades se declaran con tipo y nombre, sin modificador de acceso, ya que de tenerlo dejan de ser una propiedad para pasar a ser un campo.
La creación de POGOs implica una definición de un POGO propiamente dicho, la definición de cómo mínimo 1 propiedad y campos. En el momento de la creación descubrimos otra de las ventajas de Groovy, en el momento de la llamada al constructor mediante un mapa extendido debido a que Groovy anexa un constructor por omisión a los POGOs. En el momento del acceso a campos se puede realizar mediante el operador ‘.’ o ‘[]’ lo cuál hace que parezca que se ha roto la encapsulación del POGO, pero en realidad es todo lo contrario, ya que existe la posibilidad de obtener y modificar el valor de un campo mediante el operador ‘.@’ que tampoco rompe la encapsulación.
Pero los POGOs van más allá, simplemente con declarar las propiedades según la convención, los métodos de acceso se generarán. Dichas propiedades se declaran con tipo y nombre, sin modificador de acceso, ya que de tenerlo dejan de ser una propiedad para pasar a ser un campo.
La creación de POGOs implica una definición de un POGO propiamente dicho, la definición de cómo mínimo 1 propiedad y campos. En el momento de la creación descubrimos otra de las ventajas de Groovy, en el momento de la llamada al constructor mediante un mapa extendido debido a que Groovy anexa un constructor por omisión a los POGOs. En el momento del acceso a campos se puede realizar mediante el operador ‘.’ o ‘[]’ lo cuál hace que parezca que se ha roto la encapsulación del POGO, pero en realidad es todo lo contrario, ya que existe la posibilidad de obtener y modificar el valor de un campo mediante el operador ‘.@’ que tampoco rompe la encapsulación.
class Person{
String name #Property
String firstName #Property
private int id #Field
String toString() {“${name} ${firstName}”}
}
Person person = new Person(name:’Matthew’, firstName:’McMag’)
assert “Matthew McMag” == person.toString()
person.firstName = “McGam”
assert “Matthew McGam” == person.toString()
person[‘firstName’] = “McMag”
assert “Matthew McMag” == person.toString()
assert person.name == “Matthew”
assert person.@name == “Matthew”
assert person.completName == “Matthew McMag”
try{
assert person.completName == “Matthew McMag”
}match(MissingFieldException e){
println “Error, completName isn’t a field
}
Gracias a los POGOs podemos descubrir otra de las peculiaridades de Groovy, es el segundo lenguaje, después de Java, que soporta anotaciones, aunque el soporte para tipos genéricos aún está en desarrollo.
class Person{
@BoundProperty String name
@BoundProperty String firstName
}
- Desarrollo web con Groovy
Como pequeña introducción en el desarrollo web con Groovy antes de las definiciones y ejemplos de Grails, introduciremos el sustituto de los Servlets de Java por los Groovlets. La simplicidad de código y la posible inclusión de tags de html en el mismo código en Groovy representa grandes ventajas que los Servlets no disponen. A continuación introducimos un ejemplo de un Groovlet ya que es la forma más sencilla de entender este tipo de implementación.
import java.util.DateLeer más...
if (session == null) {
session = request.getSession(true);
}
if (session.counter == null) {
session.counter = 1
}
println """
<html>
<head>
<title>Groovy Servlet</title>
</head>
<body>
Hello, ${request.remoteHost}: ${session.counter}! ${new Date()}
</body>
</html>
"""
session.counter = session.counter + 1