You are on page 1of 5

Patrones de Implementacin para la Creacin de un Lenguaje Especfico de

Dominio Interno (LEDI)


Resumen El presente artculo expone los patrones de implementacin que se emplean para la construccin de Lenguajes
Especficos Dominio Interno (LEDI), los cuales son: Encadenamiento de Mtodos, Funciones Anidadas y Secuencia de
Funciones. Cada uno de ellos presenta una sintaxis particular que puede ser apta para el tipo de LEDI que se desea construir.
Por tanto, dentro del texto se realizar un anlisis de los mismos, donde se expone su estructura y comportamiento respectivo.
Del mismo modo, se presenta un cuarto patrn denominado Cierres Anidados, en este apartado se realiza una breve explicacin
del concepto llamado Bloque o Blocks el cual es empleado por el lenguaje de programacin Ruby y es fundamental para la
implementacin de este patrn. Los patrones ya mencionados fueron estudiados en [1], dando como resultado la CREACIN
DE UN LED EMBEBIDO EN RUBY PARA EL MODELADO DE PROBLEMAS DE OPTIMIZACIN, el cual fue el producto final de
tesis de Maestra referenciada.

Palabras Claves Cierres Anidados, Encadenamiento de mtodos, Funcin anidada, Lenguajes Especficos de Dominio
Interno, Secuencia de funciones.

Implementation Patterns for Creating an Internal Domain Specific Language


(IDSL)
Abstract This article discusses the deployment patterns that are used for building Domain-Specific Languages Internal (IDSL),
which are: Chain of methods, nested functions and sequence of functions. Each has a particular syntax that may be suitable for the
type of IDSL to be built. Therefore, in the text analysis of the same, where its structure and respective behavior exposed is
performed. Similarly, a fourth pattern called Nested Closures, this section is a brief explanation of the concept called Block or Blocks
which is used by the Ruby programming language and is essential for the implementation of this pattern is performed is presented.
The aforementioned patterns were studied in [1], resulting in the "CREATING AN EMBEDDED IN RUBY LED MODELING FOR
OPTIMIZATION PROBLEMS", which was the final product referenced Master's thesis.
Keywords Domain Specific Language, Function Sequence, Method Chaining, Nested Function, Nested Closures.

1. Introduccin
Al hablar de Lenguajes de Programacin usualmente
la primera referencia que se hace se suele dirigir a los
que son ms conocidos, ya sean lenguajes de tipado
esttico (como Java, C++, C#, C, etc.) o lenguajes de
tipado dinmico (como PHP, JavaScript, Grooby, Phyton,
Perl, Ruby, etc.). Por otro lado, en la actualidad existen
frameworks que facilitan la construccin de aplicaciones,
muestra de ello se tiene a Hibernate, JQQQ, QueryDSL
o Jequel, los cuales buscan brindar al usuario una va
ms amigable y fcil de interactuar con su motor de
base de datos. Tambin se tiene a JQuery y
CoffeeScript, orientados a mejorar la experiencia con
JavaScript y por ltimo, uno de los ms populares Ruby
on Rails, orientado a la web [1].
Al analizar dichos frameworks, estos presentan una
sintaxis que es similar al lenguaje sobre el cual actan,
por ejemplo Ruby on Rails posee sintaxis perteneciente
a Ruby y JQuery hace uso de la sintaxis que posee
JavaScript, es en este contexto en el cual se hace
referencia a los Lenguajes Especficos de Dominio
Interno.

radica en que su semntica y la gramtica de las


instrucciones que ellos poseen no estn enmarcadas en
la terminologa y contexto de un dominio especfico [1].
Estos lenguajes al ser enmarcados dentro del contexto
de los Lenguajes Especficos de Dominio (LED) pasan a
ser llamados lenguajes anfitriones puesto que sern
empleados en la construccin de un nuevo lenguaje, el
cual entra en la categora de LEDI. En otras palabras,
tomando como ejemplo a Ruby on Rails (conocido
tambin como RoR), Ruby sera el lenguaje anfitrin y
RoR sera el LEDI.
Por tanto, un LEDI es aquel que usa la infraestructura
de un lenguaje de programacin existente (tambin
llamado lenguaje anfitrin) para construir la semntica
de un dominio-especfico [3], tal como se observa en la
Figura. 1.

2. Los lenguajes de propsito general y su relacin


con los LEDI
Cuando se habla de Lenguajes de Propsito General,
se puede hacer referencia a Java, C++, C#, C, PHP,
JavaScript, Grooby, Phyton, Perl, Ruby, etc. Es decir,
son aquellos lenguajes cuya caracterstica principal

Figura 1. Implementacin de un LED Interno utilizando


un lenguaje anfitrin existente y la infraestructura que el
ofrece [3].

Al decir que un LEDI hace uso de la infraestructura


del lenguaje anfitrin, se est haciendo referencia a
componentes tales como analizador lxico, analizador
sintctico, analizador semntico, etc. Es decir, todo
aquello que conforma y hace parte de un lenguaje de
programacin. Por tal motivo, un LEDI tambin puede
ser llamado Lenguaje Especfico de Dominio Embebido,
refirindose al hecho que el LEDI al utilizar la
infraestructura de un lenguaje anfitrin tambin estar
ligado a las restricciones de ste, por lo tanto, cualquier
expresin que se utilice debe ser un expresin legal en
el lenguaje anfitrin.
De tal forma, para crear un LEDI se debe construir
una arquitectura empleando el lenguaje anfitrin de
forma que sustente al Lenguaje de Domino Especfico.
Dicha arquitectura constar de diversos Mdulos
(empleando trminos propios de Ruby) que prestarn
determinada tarea, por ejemplo el Mdulo Analizador de
Expresiones Matemticas, tal como se implement en
[1].
3. Patrones de implementacin para un LEDI
Existen diferentes patrones de implementacin para
un LEDI, donde cada uno posee una estructura
particular (sintcticamente hablando), por lo tanto es
necesario evaluar cul es el tipo de sintaxis que se
requiere para el lenguaje a construir.
Martin Fowler
implementacin:

[8]

presenta

cuatro

tipos

de

Encadenamiento de mtodos (Method Chaining)


Funcin anidada (Nested Function)
Secuencia de funciones (Function Sequence)
Cierres Anidados (Nested Closures)
Encadenamiento de mtodos (Method Chaining)

El Encadenamiento de Mtodos, tambin llamado


interfaz fluida (fluent interface) es quizs el patrn ms
utilizado en la implementacin de un LEDI [3].
Bsicamente este patrn permite al usuario expresarse
de forma natural, utilizando los trminos propios del
dominio en una secuencia coherente.
A continuacin, a modo de ejemplo se muestra un
LEDI empleando el Encadenamiento de Mtodos
(Figura. 2). Este fragmento de cdigo se sita en el
contexto de un Domino de Problema enfocado a las
computadoras, donde por medio del Encadenamiento
de Mtodos se describe la configuracin de un
computador
a
travs
de
las
instrucciones
proporcionadas por el lenguaje (se utiliza Java para la
sintaxis).

Figura 2. Encadenamiento de Mtodos [8].

Como se puede observar en la figura, este patrn


consiste en permitir realizar llamadas sucesivas a
diferentes mtodos que irn encadenados en una
secuencia lgica, de forma que puedan describir el
Dominio aplicado a determinada situacin. En el ejemplo
se muestra la construccin de un computador que posee
un procesador (processor) con dos ncleos (cores(2))
con una velocidad de 2500 (speed(2500)) y una
arquitectura i386 (i386). Del mismo modo, el
computador posee dos discos (disk), el primero con un
tamao estandar y el segundo con un tamaa de 75
(size(75)), velocidad de 7200 (speed(7200)) y de tipo
sata (sata). El aspecto que presenta este patrn es muy
similar al Patrn de Diseo Constructor.
Para implementar el Encadenamiento de Mtodos es
necesario cambiar la forma tradicional en cmo se
construye un mtodo. Dentro del contexto que se
presenta en el ejemplo, se debe crear un Modelo que
represente el Dominio del Problema, para esto se crea
una Clase que refleje tal Domino y dentro de esta se
deben declarar los mtodos que conforman el LEDI.
Estos mtodos al ser la sintaxis a travs por la cual el
usuario interacta con el lenguaje deben tener nombres
que tengan significado propio y que al ser llamados de
forma secuencial puedan modelar el Dominio. Tal como
se observa en el ejemplo.
Observe el mtodo speed(), generalmente cuando se
desea agregar o asignar un valor dentro de una clase el
mtodo debera tomar el nombre setSpeed(), pero como
se mencion anteriormente el nombre de las funciones
deben ser significativos dentro del contexto del Domino
de forma que al encadenar los mtodos estos puedan
expresar un conocimiento coherente del mismo. Dicho
esto, el Encadenamiento de Mtodos puede violar
varias reglas que son comunes en el diseo de API [8].
Del mismo modo, no solo los nombres de los mtodos
deben cambiar sino tambin su implementacin.
Siguiendo el ejemplo anterior, en Java usualmente un
mtodo set se implementa de la siguiente manera:

Figura 3. Definicin de un mtodo segn Java [8].

Sin embargo, aplicando el Encadenamiento de Mtodos


al cdigo anterior tomara la siguiente forma:

Figura 4. Definicin de un mtodo aplicando


Encadenamiento de Mtodos [8].

Note que se ha hecho uso de la instruccin this, esta


se necesita puesto que el mtodo que es usado para el
encadenamiento debe retornar un objeto, el cual
permitir continuar con la cadena.
Funcin anidada (Nested Function)

Figura 5. Funciones Anidadas [8].

El patrn de Funcin Anidada se compone de una


combinacin de funciones que invocan a otras funciones
como argumentos de alto nivel [8]. Esto significa que
debe existir una funcin padre (tal es el caso la funcin
computer, como se muestra en la Figura 5) que encierra
o agrupa a otras funciones, las cuales son parmetros
de ella, esta sintaxis es similar a la que presentan
lenguajes como Scheme o Prolog.
Del mismo modo, las funciones que son utilizadas en
los parmetros de la funcin padre cumplen la tarea de
retornar su resultado en un formato vlido, de tal forma
que la funcin padre puede ensamblarlos dentro de su
respuesta. As pues, la secuencia de evaluacin de la
sintaxis que presenta este patrn, inicia por las
funciones que sirven como argumentos y por ltimo la
funcin padre.

Considere el caso donde desea configurar un


computador que posea un Disco con tamao de 150 Gb
y una velocidad de 7200 MB/s, tradicionalmente se
empleara la funcin disk de la siguiente manera,
disk(150). Sin embargo, empleando este tipo de llamado
no es posible saber dentro de la sintaxis a cual
parmetro corresponde al tamao o a la velocidad del
Disco. Sin embargo, empleando el patrn de Funcin
Anidada la misma instruccin podra tener la siguiente
interpretacin disk(size(150), speed(7200)). Esta
tcnica, la cual est orientada a mejorar la expresividad
de cualquier instruccin ya sean en el contexto de un
LEDI o en una programacin tradicional es llamada
azcar sintctica, trmino empleado por Martin Fowler.
No obstante, este patrn presenta desafos cuando se
requiere que las funciones posean parmetros
opcionales. Por tanto, al escoger el lenguaje anfitrin es
necesario conocer si este permite declarar la funcin
con parmetros por defecto (esto es permitido tambin
en PHP), lo cual es una buena aproximacin para
resolver la funcionalidad requerida.
Un enfoque alternativo consiste en seleccionar un
lenguaje anfitrin que soporte Mapas Literales (Literal
Map) [8], lo cual conduce a tener en cuenta al lenguaje
de programacin Ruby. En Ruby, los Mapas Literales
tambin son llamados Hash los cuales son estructuras
de datos con la forma llave/valor. De tal manera, el
ejemplo anterior se representara como disk(size: 150,
speed:
7200)
o
su
equivalente
disk(:size=>150,speed=>7200).
De esta forma, antes de seleccionar el patrn de
Funcin Anidada es conveniente analizar la direccin de
lectura de las instrucciones que se desean presentar,
tenga en cuenta que al implementar esta tcnica el
usuario debe iniciar la lectura e interpretacin de la
instruccin empezando por los argumentos ms internos
y devolvindose hasta llegar a la funcin principal o
funcin padre. Por otro lado, si lo que se desea es
ofrecer al usuario un lenguaje que presente una
secuencia de instrucciones que se pueda leer de
izquierda a derecha las tcnicas de Encadenamiento de
Mtodos y Secuencia de Funciones son una mejor
opcin [1].
Secuencia de funciones (Function Sequence)

Figura 6. Secuencias de Funciones [8].

Este patrn produce una combinacin de llamadas a


funciones como una secuencia de instrucciones [8],
donde no existe algn dato que pueda relacionarlas. Es
decir, tanto en el patrn de Encadenamiento de
Mtodos como en el de Funciones Anidadas existe un
dato u objeto que se va construyendo a media que la
instruccin (o sea, el LEDI) expresada va siendo
analizada. En el caso del Encadenamiento de Mtodos
cada mtodo debe retornar un objeto para as continuar
con la cadena, y en las Funciones Anidadas cada
funcin que es utilizada como argumento de la funcin
de alto nivel tambin debe retornar algn tipo de dato.
Por otro lado, como se puede ver en la sintaxis de la
Figura. 6 las funciones son llamadas individualmente de
modo que no existe algn dato que permita una relacin
entre ellas. Sin embargo, al comenzar toda instruccin
del LEDI empleando este patrn es necesario llamar
una funcin padre o funcin vaca (en este caso
computer()) la cual es catalogada como una funcin
global, no obstante es necesario conocer si el lenguaje
anfitrin permita declarar mtodos con esta
caracterstica.
Una funcin global puede ser usada un cualquier
parte de la arquitectura, simplemente haciendo
referencia al archivo donde ha sido creada. Sin
embargo, adoptar esta prctica trae la desventaja que al
ser un elemento que ha sido declarado como global
significa que es visible desde cualquier parte, perdiendo
su encapsulamiento. Una opcin para evitar esto es a
travs del uso de namespacing (lo cual debe ser una
cualidad del lenguaje anfitrin) donde por medio de ste
se reduce el alcance o mbito de accin de dicha
funcin permitiendo un mayor control sobre su visibilidad
dentro de la arquitectura que sustenta al LEDI. En este
escenario Ruby se adapta a dicha necesidad puesto que
por medio de sus Mdulos (modules) es posible
implementar el namespacing [9].
As mismo, otro componente importante al
implementar este patrn es la necesidad de utilizar
Variables de Contexto (Context Variables) las cuales
permite guardar el contexto requerido durante el anlisis
gramatical de la instruccin [8].
Como ya se mencion, las Funciones Anidadas al no
estar relacionadas es necesario contar con un
mecanismo que permitan realizar el anlisis de la
secuencia de instrucciones, capturando el dato u objeto
que est siendo construido por la funcin en ejecucin y
guardndolo en una variable que refleje este contexto
durante el anlisis para ser accesible posteriormente por
la siguiente funcin que conforma la instruccin
expresada; esta tcnica es llamada Variable de
Contexto. Cabe mencionar que la Variable de Contexto
ir asumiendo un nuevo valor a medida que transcurre
el anlisis de las funciones.

Por ltimo, a pesar de existir esta tcnica, el empleo


de Secuencia de Funciones es el patrn menos til en la
combinacin de llamadas a funciones para utilizar en un
LED [8], ya que al utilizar una Variable de Contexto para
efectuar el seguimiento del proceso de anlisis es en
realidad una tarea demandante, la cual puede llevar a
construir un cdigo que es difcil de comprender y
propenso a errores.
Cierres Anidados (Nested Closures)
Para poder definir este patrn, es necesario referirse
en primera instancia al concepto de Clusula o Closures
(cabe aclarar que en este artculo no se hace una
profundizacin en el tema pero s se tocar los
conceptos bsicos para entender en cierto modo el
funcionamiento del patrn de Cierres Anidados). Las
Clausulas son conocidas tambin con los nombres de
lambdas, bloques o funciones annimas y es una
caracterstica que poseen ciertos lenguajes de
programacin (como Lips, Smalltak y Ruby).
Un Clausula es un bloque de cdigo que puede ser
asociado a una funcin, donde este bloque puede ser
invocado o no dentro de la misma. Los bloques son
delimitados por llaves ({}) o por las palabras clave do y
end. La llave de apertura ({) o la palabra clave do deben
estar en la misma linea que el mtodo de invocacin [2].
Para una mejor interpretacin de esta definicin observe
el siguiente fragmento de cdigo (Figura 7):

Figura 7. Definicin de un bloque empleando sintaxis


del lenguaje de programacin Ruby [8].

Como se puede observar en este ejemplo, se est


definiendo las caractersticas que debe tener un
procesador, tal como se ha realizado en los anteriores
patrones. En este caso el mtodo padre que inicia la
cadena es processor (para aquellos que no estn
acostumbrados a la sintaxis en Ruby, este lenguaje
permite en ciertos casos obviar el empleo de los
parntesis en la invocacin de mtodos, por lo tanto
cores y i386 tambin son mtodos) el cual tiene
asociado un bloque delimitado por las palabras clase do
y end, tal como se dijo anteriormente. Del mismo modo,
este bloque es un fragmento de cdigo que contiene el
llamado a los mtodos cores y i386, de esta forma
processor puede hacer una invocacin al bloque dentro
de la funcin empleado la palabra reservada call, tal
como se muestra a continuacin (Figura 8):

Figura 8. Invocacin de un bloque dentro de un mtodo


definido [8].

En el fragmento anterior (2) se puede observar la


definicin del mtodo processor que tiene como
argumento el parmetro block antecedido por el carcter
ampersan (&), esto significa que a travs de la sintaxis
&block, el mtodo recibe como argumento el bloque
definido, donde este es llamado por medio de la funcin
call (block.call). Por lo tanto, processor es libre de hacer
uso o no del bloque asociado a este.
Ahora, retomando el contexto de los LEDI una forma
usual de pensar acerca de los Cierres Anidados es
como una mejora de los patrones de Encadenamiento
de mtodos, Secuencia de funciones y Funcin
Anidada [8]. Al observar el fragmento de cdigo de (1)
se puede notar que en ste se renen los patrones de
implementacin Secuencia de funciones y Funcin
Anidada, donde en vez de pasar dos funciones como
argumentos de processor a ste se le pasa solamente
un solo argumento en forma de Cierre Anidado el cual
contiene dos mtodos (cores y i386) que tiene la forma
del patrn de Secuencia de funciones.
Una de las ventajas de emplear como lenguaje
anfitrin a Ruby yace en la utilizacin de Clausulas
combinadas con la Metaprogramacin que ofrece el
lenguaje. Esto se puede observar en [1], donde por
medio de la implementacin del mdulo RestrictionBuild
se logr analizar el bloque asociado con el mtodo
subject_to (como se muestra en Figura 9) y de esta
forma crear por medio de la tcnica llamada Definicin
Dinmica de Mtodos [10] aquellos mtodos que son
parte de la sintaxis del LEDI implementado.

Durante el proceso de investigacin y anlisis de


cada uno de los patrones presentados se recalca
frecuentemente la necesidad de contar con un lenguaje
anfitrin que se ajuste a las necesidad del patrn a
escoger, esto significa que no siempre el lenguaje de
programacin que se est acostumbrado a manejar es
el ms apto. Del mismo modo, los nombres de los
mtodos que conformaran la sintaxis del LED deben
poseer un significado que sea representativo dentro del
Dominio, esto conducir a que dicho mtodo solo tiene
sentido dentro de la instruccin del LED y no de forma
aislada.
5. Referencias
[1]

A. Rodas Vsquez, Definicin De Una Arquitectura Utilizando


Lenguaje De Modelado Unificado (UML), En La Implementacin De
Un Lenguaje Especfico De Dominio Embebido (LEDE): Creacin De
Un Led Embebido En Ruby Para El Modelado De Problemas De
Optimizacin, M.S. thesis. Universidad Tecnologa de Pereira.
Risaralda, 2015.

[2]

D. Flanagan and Y. Matsumoto, The Ruby Programming Language. Ed.


California: O'Reilly, 2008.

[3]

D. Ghosh, DSLs in Action. Ed. Stamford: Manning, 2010.

[4]

E. Evans, Domain-Driven Design: Tackling Complexity in the Heart of


Software. Ed. Addison Wesley, 2003.

[5]

J. Rubin and D. Chisnell, Handbook of Usability Testing, ed 2nd. Wiley,


2008.

[6]

K. Beck, Implementation patterns. Addison-Wesley, 2007.

[7]

L. Carlson and L. Richardson, Ruby Cookbook. OReilly, 2006.

[8]

M. Fowler, Domain Specific Languages. Ed. Boston: Addison Wesley,


2011.

[9]

P. Cooper.,Beginning Ruby From Novice to Professional, ed 2nd . Ed


New York: Apress, 2009.

[10] P. Perrotta, Metaprogramming Ruby. The Pragmatic Programmers;


2010
[11] R.C Martin, Clean Code. Prentice Hall, 2008.

Figura 9. Modelado de un funcin de optimizacin


empleando el LEDI construido en [1].

4. Conclusiones

[12] R. Fourer, D. M. Gay and B. W. Kernighan, AMPL A Modeling


Language for Mathematical Programming, 2da ed. 2003.
[13] J. de Lara and E. Guerra. Domain-Specific Textual Meta-Modelling
Languages for Model Driven Engineering, Modelling Foundations and
Applications, pp. 259-274, 2012.

You might also like