CREACIÓN DE DSLS CON GROOVY
por Alberto Vilches http://albertovilches.com
Twitter: @albertovilches
INTRODUCCIÓN ¿QUÉ ES UN DSL?
QUÉ ES Y PARA QUÉ SIRVE
• DSL = Domain Specific Language
• Resuelve un tipo particular de problema
• Definición
• Modelado
• Representación
• Comunmente llamados mini lenguajes
QUÉ NO ES
• Lo opuesto a un DSL es: • General Purpose Language (como Java o Erlang)
• General Purpose Modeling Language (como UML)
• No se puede usar para programar/modelar cualquier cosa
• No necesariamente Turing Completo
XML, EL ANTEPASADO DEL DSL EN JAVA
• ejb-jar.xml
• Define la estructura para desplegar EJBs en SA
• struts-config.xml
• Mapea las acciones y forms del fw MVC Struts
• spring-config.xml
• Define cómo crear e inyectar objetos en LC Spring
CARACTERÍSTICAS DE UN DSL
• Sintaxis específica
• Limitados en ámbito y capacidad
• Pequeños y simples
PORQUÉ SON ÚTILES
• Contextuales
• Más expresivos = más claros
• Mejor usar varios DSL que un único GPL
CUANDO USARLOS
• Lógica o reglas de negocio cambian a menudo
• Solución separada del resto del código de la aplicación
TIPOS DE DSL
• Externos
• Los usamos día a día desde hace tiempo
• Internos
• Viven entre nosotros
TIPOS DE DSL: EXTERNOS
Cómo definen su formato y sintaxis:
Aprovechan una sintaxis existente como XML…
…o poseen su propio compilador/interprete…
…o son diseñados con una herramienta
EJEMPLOS DE DSLS EXTERNOS
Cascading Style Sheet
EJEMPLOS DE DSLS EXTERNOS
Script Apache Ant (XML)
EJEMPLOS DE DSLS EXTERNOS
• Structured Query Language
• Expresiones regulares
Patrón para buscar emails
EJEMPLOS DE DSLS EXTERNOS
DSL Dominio Uso
SQL BBDD Consulta y manipulación
Expresión regular
Cadenas de texto Búsqueda por patrones
CSS Estilo (fuentes, colores, tamaños, etc)
Cambiar la presentación de un HTML
Ant Recursos (clases y otros ficheros)
Compilación y generación de artefactos JAR,WAR
TIPOS DE DSL: INTERNOS
• Se hospedan en un GPL para describirlos
• Aprovechan el compilador/intérprete
• Reutilizan parte de la sintaxis
• Como anotaciones u otras ventajas (¡Groovy!)
• Heredan las limitaciones del lenguaje anfitrión
DSLS INTERNOS GRAILS
Config.groovy / DataSource.groovy
DSLS INTERNOS GRAILS
UrlMappings.groovy
DSLS INTERNOS GRAILS
Criteria, Hibernate, SQL
DSLS INTERNOS GRAILS
GORM
QUE HACE FALTA PARA CREAR UN DSL
QUÉ DEFINE UN DSL
• Contexto
• El dominio está implícito porque…
• … sistema, autor y lector saben de qué se está hablando
• Estructura, gramática, sintaxis es:
• Reducida fluida agrupada encadenada
SINTAXIS FLUIDA
• Primera aproximación
“Method chaining”
Todos los métodos devuelven this
METHOD CHAINING
• Javascript jQuery
METHOD CHAINING
• Javascript jQuery
• Contextual, ligeramente extensible
METHOD CHAINING
• Apache Commons CLI
METHOD CHAINING
No vale siempre (aunque es mejor que nada)
• No es fácil anidar • Todo en una misma línea
EJEMPLO: SIN CONTEXTO
• ¿Construcción o reutilización de recursos? • ¿Importa el orden? ¿Qué hago si falla?
EJEMPLO: METHOD CHAINING
• Único objeto, única línea, único contexto • ¿Control de errores y recursos?
SOLUCIÓN: DSL
• DSL
API vs DSL
QUIERO CREAR UN DSL
¿INTERNO...? ¿EXTERNO…?
DSLS EXTERNOS
• Jet Brains Metra Programming System http://www.jetbrains.com/mps/index.html
• Eclipse Modeling Framework Project http://www.eclipse.org/modeling/emf/
• Microsoft DSL Tools Visualization&Modeling SDK http://code.msdn.microsoft.com/DSLToolsLab
• XML
• ANTLR http://www.antlr.org/
DSLS INTERNOS
• No todos los lenguajes lo permiten facilmente
• Metraprogramación es esencial
• Ruby
• Groovy
CARACTERÍSTICAS DE GROOVY
(QUE LO HACEN IDEAL PARA CREAR DSLS)
GROOVY
• Lenguaje dinámico para JVM
• Atributos y métodos se resuelven en Runtime
• Meta Object Protocol (MOP)
• Genera clases 100% Java
• Sintaxis Java
+ sintaxis específica para colecciones
+ otras ideas de Ruby, Python, Smalltalk
• Closures, scripts, sobrecarga operadores, MOP, Gstrings, Categorías, metaClass
SCRIPTS
COLECCIONES
ALGUNAS MEJORAS
Getters Setters
Constructores con mapas
Paréntesis y corchetes Opcionales
No primitivos
EXPANDOMETACLASS
• Se pueden añadir métodos/atributos a cualquier clase
• ¡Incluso reescribir! • y mucho más..
CATEGORIES
• Sobreescritura de métodos temporal
SOBRECARGA DE OPERADORES
CALL() SHORTHAND
• Se puede invocar a cualquier objeto como si fuera un método
• Solo es necesario implementar call()
MOP
• Se pueden capturar las llamadas a métodos que no existen
CLOSURES
Java
Groovy
CLOSURES
• Variables invocables como métodos
• Atributos invocables como métodos
CLOSURES
• Owner: instancia donde se crea el closure • Delegate: contexto donde se ejecuta el closure
• Por defecto es la misma (delegate = owner)
CLOSURES
• El contexto por defecto es owner • Accediendo a variable de owner funciona
CLOSURES
• El contexto por defecto es owner • Accediendo a variable de otro sitio NO funciona
CLOSURES
• Contexto nuevo (delegate): config • Accediendo a variable del contexto SI funciona
CLOSURES
• With simplemente cambia el contexto
ESTRUCTURAS PERSONALIZADAS
• En un método dado, si el último parámetro es un closure, se puede dejar fuera del paréntesis que engloba los parámetros de la llamada
COMO CREAR UN DSL
MI PRIMER DSL
MI PRIMER DSL
MI PRIMER DSL
DSL EN UN SCRIPT
src/script.groovy
PERO…
PERO…
PERO…
PERO…
BUILDER SUPPORT
• Los builders procesan DSLs mediante eventos • La clase BuilderSupport nos permite crear nuestros
propios builders
• Admite cualquier nombre de método y combinación de parámetros
BUILDER SUPPORT
ALGUNOS BUILDERS
MARKUP BUILDER
SWING BUILDER
JMX BUILDER
• Creando un cliente JMX
• Exportando un objeto mediante JMX
ANT BUILDER
ALGUNOS FRAMEWORKS Y HERRAMIENTAS CON SU PROPIO
DSL
GANT
• http://gant.codehaus.org/
GRIFFON
• http://griffon.codehaus.org/
EASYB
• http://www.easyb.org/download.html
GRADLE
• http://gradle.org/
GMETRICS
• http://gmetrics.sourceforge.net/
SPOCK
• http://code.google.com/p/spock/
¿HACEMOS UNO?
¡GRACIAS!
PREGUNTAS