DSLs con Groovy
miércoles 05/09/2007
¿Qué es un DSL?DSL significa "Domain Specific Language", o "Lenguaje específico de Dominio". Un DSL es un minilenguaje de programación que permite representar el conocimiento de un campo específico. Por ejemplo, puedo querer un DSL para representar de forma sencilla las reglas de negocio de una aplicación para tomar decisiones en el entorno financiero, o un analizador sintáctico de texto. También se utilizan para generar configuraciones específicas, como los ficheros hbm de Hibernate, o simplemente para generar XML de forma sencilla. ¿Y por qué no hacer eso con un lenguaje "de verdad" como Java o Groovy? Simplemente, porque si quiero representar las reglas de una aplicación financiera en Java, necesito conocer tanto el entorno financiero como las reglas para trabajar con Java. Un DSL específico tendrá muchas menos reglas, su sintaxis estará adaptada al objetivo que permite, y podré, por ejemplo, pedir a un experto en economía que escriba las reglas por mí.
¿Por qué dicen que Groovy es bueno para escribir DSLs?
El hecho de que Groovy sea un lenguaje dinámico da mucha libertad a la hora de crear estructuras que se adapten a un contexto particular. Posee ciertas características que lo hacen muy apropiado para crear Lenguajes Específicos de Dominio:- Los constructores (Builders) permiten utilizar lenguajes con una estructura de arbol marcada, como un DSL para generar interfaces Swing:
gui = swing.frame(title:'Test 2', size:[400,200]) {
panel(layout:new FlowLayout()) {
panel(layout:new FlowLayout()) {
for (name in ["Tom", "Dick", "Harry", "Bill"]) {
checkBox(text:name);
}
}
panel(layout:new FlowLayout()) {
comboBox(items:["Red", "Green", "Blue", "Orange"],
selectedIndex:2);
}
}
}
gui.show();
- En Groovy puedo añadir métodos a cualquier objeto, usando Categorías o Metaclases. Incluso puedo hacerlo con números, para escribir cosas como "4.veces", o "24.horas"
- La mayoría de los operadores se pueden sobrecargar, para escribir cosas como "cuenta += 200.euros", o "4.dias + 12.horas"
- Cuando pasamos un Mapa en groovy como parámetro a un método, el código se lee igual que si los parámetros tuvieran nombre: "mover(x:2.metros,y:15.metros)"
- También podemos crear nuestras propias estructuras de control utilizando Closures: "enTransaccion {...}", "siSaldoPositivo {...}"
- También puedo añadir dinámicamente métodos y propiedades dinámicas (que no existen, pero que puedo monitorizar e intervenir cuando se invoquen) implementando GroovyObject o creando una Metaclass.
Un ejemplo popular: GORM

Si tengo una clase Usuario así:
class Usuario {
Date fechaNacimiento
String nombre
String apellidos
}
con GORM puedo hacer consultas mediante métodos dinámicos:
def lista = Usuario.findByNombre("Paco")
def lista = Usuario.findByNombreNotNull()
def lista = Usuario.findByNombreLike("Pa%")
def lista = Usuario.findByFechaNacimientoBetween(fecha1,fecha2)
def lista = Usuario.findByNombreLikeOrApellidoLike("P%","L%")
Obviamente estos métodos no existen en la clase Usuario, pero GORM los añade dinámicamente e intercepta la llamada desde nuestro código, para convertirlo en una consulta Hibernate.
Conclusión
Bueno, hasta aquí nuestro repaso a los DSLs con Groovy. Espero que si no tenías claro lo que es un DSL te haya servido para aclarar conceptos, y si ya conocías el tema te haya interesado cómo se implemente en Groovy.
Más información: http://groovy.codehaus.org/











