DSL + UML = Pragmatic Modeling

 

DSL + UML = Pragmatic Modeling es el título de un artículo de Cameron Skinner, General Manager del Visual Studio Ultimate team, en el
que relata la sintonía que intenta alcanzar Microsoft en cuanto a filosofía de
modelado y lo absurdo de las discusiones UML vs. DSL.

En cuanto a esto, a lo absurdo del tema UML vs. DSL, el mejor que
conozco es uno titulado: “UML or DSL: Which bear is best?”.
En este se relata el gran paso que supone Visual Studio 2010 en la convivencia
entre UML y DSLs en el mundo Microsoft, quedando bien delimitada la estrategia
que a lo largo de tantos artículos nos habían mostrado.

No obstante, pasando al lado más práctico del asunto, hemos
visto ejemplos de cómo generar código desde los modelos UML de modo similar a
como lo hacíamos con los DSLs de DSL Tools, gracias al Visualization and
Modeling Feature Pack, pero no es tan fácil encontrar ejemplos prácticos de
cómo manejar esta convivencia que comentamos entre modelos UML y DSLs.

Un buen ejemplo para experimentar sobre esto me llegó a las
manos gracias a Pedro J. Molina, un experto en modelado y generación de código
que realizó su tesis sobre modelado de interfaces de usuario. Podéis visitar su
página en castellano y en inglés.
Fruto de su investigación desarrolló CUIP (Conceptual User Interfaces
Patterns), un metamodelo para la definición de interfaces de usuario, cuyo
prototipo está implementado con DSL Tools. Dicho prototipo se compone realmente
de dos metamodelos: M8, un metamodelo de entidades de negocio y BizUI, que
define los patrones CUIP. Ambos metamodelos están relacionados, de modo que si
en M8 tenemos Facturas y Clientes, en BizUI podremos definir una interfaz
Population de Facturas, que representará un listado de Facturas, o una interfaz
Service de Clientes, que representará un formulario para dar de alta un
cliente.

Al igual que en la mayoría de estas soluciones, se hace uso
de un DSL similar a los diagramas de clases de UML como base del modelado. Es
el pequeño truco que se usaba para suplir a UML en aplicaciones de modelado en
Visual Studio previas a la incorporación de UML. Incluso una de las plantillas
para generar DSLs en DSL Tools era (y sigue siendo) un diagrama de clases muy
similar al de UML. Sin embargo, con la llegada de Visual Studio 2010, esto
podría empezar a cambiar.

Mi idea inicial con CUIP era sustituir M8 por un diagrama de
clases de UML, con todas las ventajas que esto supondría, y relacionarlo con
BizUI, el DSL de interfaces de usuario por medio del ModelBus. El ModelBus es
otra de las grandes novedades de Visual Studio 2010. Básicamente consiste en
una plataforma que nos permite referenciar elementos de modelo entre diferentes
modelos, independientemente de si corresponden al mismo metamodelo o a metamodelos
diferentes.

Como veremos, si bien ModelBus es realmente útil para
realizar estas labores entre DSLs, cuando intentamos atravesar la frontera y
aventurarnos con los nuevos modelos UML, el tema se nos escapa de las manos.

Vayamos por partes, antes de meternos con UML probaremos el
ModelBus para relacionar elementos de M8 y BizUI. En concreto intentaremos
asignarle a cada UI definida en BizUI una clase de M8.

El proceso se compone de dos partes.

El primero es habilitar el ModelBus en el metamodelo origen de
la relación, en este caso M8. En esta imagen podemos ver dicho metamodelo:

Simplemente botón derecho sobre el diseñador, elegimos el
comando ‘Enable ModelBus’ y seleccionamos la opción de exponer nuestro DSL al
ModelBus.

El resultado será un nuevo proyecto en nuestra solución con
un adaptador para consumir las referencias a cualquier elemento de dicho
metamodelo.

Para poder usar este metamodelo, con sus recién creados adaptadores, instalamos el DSL transformando las plantillas de la solución, generándola y ejecutando el vsix
que obtenemos en el proyecto DslPackage.

El segundo paso consiste en consumir los elementos expuestos
en el ModelBus por el M8.

Para ello, vamos al metamodelo que referenciará a M8, en
este caso BizUI:

 

Para definir las referencias a los elementos de M8 creamos propiedades de tipo
ModelBusReference. En nuestro ejemplo, definimos una propiedad llamada Class
en el elemento InteractionUnit (clase base de las UIs) que hará referencia a la
clase sobre la que está definida dicha interfaz de usuario.

Mediante esta propiedad podremos asignar, por ejemplo, una
clase Factura, creada en un modelo M8, sobre una UI Population creada en BizUI,
mediante el enlace sólido y persistente que nos proporciona ModelBus.

Una vez definidas las referencias instalamos el DSL como
hicimos con M8.

Con ambos metamodelos instalados, procedemos a probar las referencias
creadas en instancias de modelos de M8 y BizUI. Creamos un proyecto de prueba y añadimos
un modelo de cada tipo:

 

A continuación abrimos el M8 y añadimos un par de clases de
prueba:

 

Guardamos el modelo M8 y creamos el modelo de interfaces de
usuario:

 

 

Para definir la propiedad Class de las UIs, por ser de tipo
ModelBusReference, disponemos de un editor especial que nos permite definir
fácilmente el vínculo entre modelos que relacionará las UIs de BizUI y sus correspondientes clases de M8.
Simplemente indicamos el modelo que queremos referenciar, y qué elemento en
concreto dentro de ese modelo.

 

 

En este caso, por ejemplo, hemos definido que
FacturaPopulation del modelo Facturacion.bizui referencia al elemento Factura de Facturacion.m8, así como
ClientePopulation, ClienteInstance y ClienteMasterDetail referencian al
elemento Cliente.

Una vez que tenemos ambos modelos relacionados, podremos
acceder a sus elementos y navegar por las propiedades ModelBusReference de uno
a otro gracias a los adaptadores.

Esto nos facilita un gran número de tareas arduas pero
frecuentes en los proyectos de modelado como validaciones cruzadas entre
metamodelos, definición de modelos multidiagrama o accesos a diferentes modelos
en plantillas de generación de código. (Para esto último necesitamos generar un
adaptador especial para el contexto de las T4, tal como se indica en este
artículo)

Por último volvemos a la cuestión que nos planteábamos
inicialmente… ¿por qué no usar UML en lugar de DSLs “pseudo-UML” como M8?

Pues sí, podemos hacerlo. Simplemente agregamos un proyecto
de modelado a nuestra solución de ejemplo, y le agregamos un diagrama de clases
al que llamamos Facturacion.classdiagram:

 

En Facturacion.classdiagram definimos las clases Factura y
Cliente, al igual que hicimos en M8:

Volvemos a nuestro modelo Facturacion.BizUI y modificamos las
propiedades Class de los elementos UI, para que apunten a las clases de nuestro
nuevo modelo UML. Simplemente volvemos a abrir el editor de ModelBusReference,
y elegimos el elemento de Facturacion.classdiagram que queremos referenciar en
cada caso:

 

 

 

De este modo obtenemos nuestro modelo Facturacion.bizui con
las referencias correspondientes al diagrama de clases de UML
Facturacion.classdiagram:

 

 

Hasta aquí todo fácil. Esto nos permitiría desechar DSLs como M8 que solapan contextos
en los que UML nos da completa expresividad y crear una convivencia “sana” con
DSLs que aporten donde realmente UML no llega, como es el caso de BizUI.

Pero como casi todo en la vida, esto tampoco es perfecto. Si
las referencias entre DSL y DSL mediante el ModelBus y los adaptadores nos
proporcionaban infinidad de ventajas en cuanto a generación de código,
validación de modelos, etc., en el caso de DSL – UML dichas ventajas no están
tan accesibles. El problema viene del hecho de que no podemos generar
adaptadores al ModelBus para modelos UML. Esto nos lo tendría que proporcionar
Microsoft y, por ahora, no tienen planes de hacerlo, como bien nos comentó en
este foro Alan Cameron Wills.
Ojalá cambien de opinión… estaremos expectantes 😀