Uso de DSL para minimizar la complejidad.

Jorge Rodriguez
Continuum
Published in
3 min readDec 16, 2008

--

El objetivo de un DSL tal como lo define Martin Fowler es ser un lenguaje de programación con el puntual propósito de resolver un tipo de problema específico (a diferencia de un lenguaje de propósito general). Ejemplos de DSL son CSS, SQL o HQL (Hibernate Query Language).

Esta entrada no es para introducir los lenguajes de dominio específico, existen buenas referencias en la web, como el sitio de Martin Fowler con algunos artículos sobre DSL e incluso un libro. Esta entrada es para contar que nos motivó a usar DSL en un proyecto.

Se trata de un “catálogo de servicios”. Hay servicios de diferente naturaleza (Web Services, MQ, Stored Procedure, REST, etc). Al registrar un nuevo servicio necesitamos agregar metadata sobre las operaciones que pueden ejecutarse. La metadata puede ser usada por autómatas para generar invocaciones dinámicas de los diferentes servicios. Por ejemplo, un servicio de ruteo en una arquitectura ESB puede leer la metadata de un servicio MQ para saber en que cola colocar el mensaje y si además debe colocar información de contexto extra, etc.

En la forma clásica del diseño de la aplicación (el catálogo), uno pudiera crear un mantenedor de servicios donde la metadata es separada en objetos (Operaciones, Parámetros, Resultado, Excepciones, PreCondiciones, PostCondiciones, etc.) y usar algun CRM como Hibernate para generar la persistencia. Por otro lado tener una capa de servicios que permita generar la metadata desde estas operaciones (quizás usar flexjson para serializar a JSON el árbol de objetos que retorne Hibernate de la definición de los hbm (hibernate mapping). Pero esta es la vía complicada que nos obligan a tomar lenguajes antinaturales y antiexpresivos como java y todas las APIs y frameworks que se han gestado a su alrededor.

El diseño de lenguajes de programación como Ruby permite escribir código como:

class Comment < ActiveRecord::Basebelongs_to :postvalidates_precence_of :body, :email, :authorend

Este código es un DSL escrito en Ruby en una forma natural (un comentario pertenece a un post y debe tener al menos body, email y autor).

En vez de usar un árbol de objetos complejos para definir la metadata y complicarnos la existencia con implementaciones CRM o código JDBC complejos, nuestro diseño se basó en las siguientes consideraciones:

  1. Usa un DSL interno para definir la metadata.
  2. El lenguaje usado para crear el DSL fue Javascript por ser dinámico (lenguajes dinámicos son mejores para escribir DSL), por ser expresivo, por ser sencillo; y principalmente porque puede ejecutarse de forma nativa en la web (donde corren la mayoría de las aplicaciones hoy en día).
  3. La notación usada para escribir la especifcación del DSL es JSON porque “…It is easy for humans to read and write. It is easy for machines to parse and generate…” y (personalmente por estar cansados de parsear XML).
  4. El DSL se inserta tal como viene en la columna de metadata.
  5. El cliente de los servicios de persistencia crea la metadata (siguiendo la especificación del DSL).
  6. El cliente de los servicios de persistencia es responsable de parsear el DSL en busca de datos (Por ejemplo el servicio de ruteo del ESB es reponsable de extraer la cola donde colocar el mensaje). En el caso de usar Javascript, el parseo es nativo por usarse JSON. Para el caso de Python[1] o Ruby[2] puede usarse un parser JSON (es sencillo por ser lenguajes dinámicos). En el caso de Java puede usarse Rinho para dar soporte Javascript y parsear en forma natural el DSL.

La especificación del DSL para el catálogo aún esta en proceso de definición. Actualizaré esta entrada con ejemplos del DSL y códigos de parseo cuando este listo.

Plus: Un excelente ejemplo del uso de DSL y Metaprogramming puede ser encontrado en este blog y su inspiración en esta librería.

[1].- SimpleJson o The Standard Python Library

[2].- JSON Implementation for Ruby.

--

--