Skip to content

ATL en lugar de MediniQVT

Hace unos días que decidí dejar MediniQVT de lado, pues da más problemas que soluciones, y al ver ATL realmente no veo ninguna ventaja a usar el “estándar”.

De las principales ventajas es que ATL tiene buen soporte.

Laboratorio de Ensayos Académicos

Voy a plantear un esquema que me encantaría se haga realidad, aunque es un cambio realmente loco (revolucionario??), pero que lo veo como una forma de cambiar el mundo para bien 🙂

Cada vez que voy a una conferencia, o cada vez que leo papers, o incluso cuando los escribo, creo que los casos de estudio no son lo suficientemente buenos como para garantizar nada de lo que se escribe o propone.

La calidad de los artículos no es buena en general, el sistema de revisión por pares existente creo que generalmente no es suficiente, ya que el que revisa no tiene capacidad para verificar correctamente los estudios realizados, no?

Cómo hacemos en el software para mejorar la calidad?: teniendo un equipo de pruebas independiente capaz y experto en realizar pruebas.

De ahí me puse a pensar cómo se podría aplicar algo de esto al ambiente académico.

Se podría pensar en tercerizar los casos de estudio?

O sea, que uno cuando escribe los artículos se preocupe y ocupe de ejemplos de uso, cosas de laboratorio. Luego, solicitar a un LEA (laboratorio de ensayos académicos) que le haga un caso de estudio correspondiente.

Cómo me lo imagino:

  • expertos en casos de estudio
  • contactos con empresas para poder poner en práctica en las empresas los casos de estudio
  • contactos con las universidades para ofrecer sus servicios
  • contactos con las empresas que publican y organizadores de congresos

Se podría encargar también de mejorar la transferencia de la academia a la industria.

Se podría llegar a “obligar” a los autores a que incluyan un experimento para poder publicar, para que tenga validez de un caso de estudio real, y no como los que generalmente se presentan.

Cada autor tendría que negociar y convencer a los LEA de su propuesta, para que estos tengan interés en invertir tiempo en llevar su propuesta a la práctica.
Barreras:

  • lograr compromiso de todas las posibles partes
  • para que las organizaciones que hacen congresos y los journas les interese esto, entonces tiene que ser un negocio en el que ganen más dinero …

Se que no tengo capacidad para intentar un cambio de este estilo, por eso intentaré transmitirlo a otros que creo que están más cerca de lograr algo así.

Hay muchas cosas que creemos que están bien porque las conocimos así, pero pensemos en realidades alternativas, y pensemos objetivamente “si esto lo hubiera conocido así, en lugar de como lo conocí, sería mejor o peor?”.

Gracias por leer 🙂

Empezando con Máquinas de Estado y Diagramas de Secuencia en UML

Últimamente he podido avanzar bastante tanto con QVT como con MofScript, generando a partir del diagrama de clases UML una serie de clases junit ejecutables. Para darle mayor inteligencia a los test cases generados, la idea es generar no solo un diagrama de clases, sino también máquinas de estado con el comportamiento esperado del sistema en base a su estructura (considerando las operaciones CRUD como posibles acciones de esa máquina de estados).

 

Entonces estoy investigando sobre State Machines y Sequence Diagrams en UML, y por ahora iré dejando referencias que me han resultado útiles por acá:

Del foro de Eclipse sobre UML resultan útiles estas discusiones:

Y acá algo de Diagramas de Secuencia:

[MediniQVT] Procesar atributos de una clase excluyendo relaciones

Esto me dio bastante trabajo sacarlo, más que nada por la poca documentación de MediniQVT aplicado a UML.

 

En el where de una relación hago esto

 

where {
       myclass.ownedAttribute->forAll (att|
                       if not (att.type.oclIsTypeOf(uml::Class)) 
                       then 
                             auxiliarRelation (att, another_class)
                      else
                             true
                      endif
              );
 }

De esta forma se recorren todos los atributos de la clase, invocando axiliarRelation cuando se trata de un atributo simple, y no de una relación con una clase.

Entonces tengo una relación que me hace esa transformación que quiero hacer con los atributos simples:

relation auxiliarRelation{

     checkonly domain source att:uml::Property{};
 
     enforce domain target another_class:uml::Class{
          ownedAttribute = atribs:uml::Property{
            name = att.name,
            type = att.type 
            --así se copian los atributos
          }
     };
 }

[MediniQVT] De declarativo a procedural

Algo que me mata es que cada vez que tengo ciertas transformaciones que cada vez que las ejecuto me dan un resultado distinto. Esto es algo frustrante, porque al querer verificar si un cambio fue bueno o no, hay que ejecutar varias veces y ver con qué resultados quedarse!

Hace poco Ricardo me comentó que hay distintas formas de hacer las mismas cosas, algunas veces a él le pasaba eso, y otras veces no, con lo cual adoptó esa forma de hacer las cosas para evitar este problema. Me pasó sus transformaciones y las estuve mirando, y ahora entendí cuál es el truco: hay que usar el lenguaje declarativo lo más procedural (imperativo) posible, y esto se logra con el uso de ciertos constructores OCL en el where de una relación.

Imaginen que tenemos una relaciónA y una relaciónB, y la relaciónB tiene que invocarse una vez que se invoca la relaciónA, entonces lo que se aconseja hacer es poner un when en la relaciónB, referenciando relaciónA. En lugar de hacerlo declarativamente, lo que mejor funciona parece ser la forma más imperativa, que sería poner un código como el que sigue en la relaciónA:

where {
     packageA.packagedElement->forAll(elem|
                     if (elem.oclIsTypeOf(uml::Class) and
                        (not elem.getAppliedStereotypes()->isEmpty()) and
                        elem.isStereotypeApplied(helper::getStereotype('Table')))
                     then 
                         generateTestContext(elem, tcont, testcase, p)
                     else
                         true
                     endif
              );
 }

Y lo que terminamos poniendo en el cuerpo del forAll es algo similar a lo que pondríamos en el when de relaciónB. En este ejemplo estoy logrando que para cada clase que tiene el estereotipo “Table” se invoque a “generateTestContext”.

RubyTL

Durante las JISBD me recomendaron darle una mirada a RubyTL como alternativa a QVT, dado que estuve expresando las dificultades que me está dando MediniQVT.

Otros me recomendaron mirar QVT Operational (tutorial aquí), Xpand, etc…. lo cual me hace continuar mi pregunta de ¿para qué sirven los estándares si no hay ninguna herramienta que los implemente correctamente?

Si Medini me sigue dando problemas probaré alguna de estas alternativas.

Cómo aplicar un UML Profile con QVT (II) – Método java para automatizar ajustes

Para facilitar este proceso que había explicado antes, hice un método java que me hace la sustitución adecuada a mis metamodelos. Hay que hacer dos cambios para que el archivo que se procesa con una transformación QVT quede con el perfil correctamente aplicado, entonces hago una sustitución de un par de cadenas de caracteres en el archivo resultado.

try {
// Check if source file exists
 String fileName = "./udmp2utp/output/test001_output.uml";
 String targetName = fileName + "out.uml";
File sourceFile = new File(fileName);
 if (!sourceFile.exists()) {
 System.out.println("Source file " + fileName
 + " does not exist");
 fail();
 }
File targetFile = new File(targetName);
// Create input and output files
 Scanner input = new Scanner(sourceFile);
 PrintWriter output = new PrintWriter(targetFile);
// cambiar líneas
// ENCABEZADO
// xmlns:utp="http:///utp.ecore">
 String headToFind = "xmlns:utp=\"http:///utp.ecore\">";
// -----------------por---------------------
// xmlns:utp="http:///schemas/utp/_zQa2cPvkEeGryt8C_nFAIg/0"
 // xsi:schemaLocation="http:///schemas/utp/_zQa2cPvkEeGryt8C_nFAIg/0 ../../Metamodels/utp.uml#_zYIA8PvkEeGryt8C_nFAIg">
String headToReemplace = "xmlns:utp=\"http:///schemas/utp/_zQa2cPvkEeGryt8C_nFAIg/0\"\n\t"
 + "xsi:schemaLocation=\"http:///schemas/utp/_zQa2cPvkEeGryt8C_nFAIg/0 "
 + "../../Metamodels/utp.uml#_zYIA8PvkEeGryt8C_nFAIg\">";
String s1 = null;
 while (input.hasNext()) {
 s1 = input.nextLine();
 if (s1.contains(headToFind)) {
 s1 = s1.replace(headToFind, "");
 output.println(s1);
 output.println(headToReemplace);
 break;
 } else {
 output.println(s1);
 }
 }
// PROFILE APPLICATION
// <profileApplication>
 // <appliedProfile
 // href="../../Metamodels/utp.uml#_17_0_12b803b5_1292364137078_17156_1878"/>
 // </profileApplication>
// -----------------por---------------------
// <profileApplication xmi:id="_xUOVIcqEEeGr09qrcP0Uig">
 // <appliedProfile
 // href="../../Metamodels/utp.uml#_17_0_12b803b5_1292364137078_17156_1878"/>
 //
 // <eAnnotations xmi:id="_xUOVIsqEEeGr09qrcP0Uig"
 // source="http://www.eclipse.org/uml2/2.0.0/UML"
 // references="../../Metamodels/utp.uml#_zYIA8PvkEeGryt8C_nFAIg"/>
 // </profileApplication>
String profApplicationToReemplace = "<profileApplication xmi:id=\"_xUOVIcqEEeGr09qrcP0Uig\">\n\t"
 + "<appliedProfile href=\"../../Metamodels/utp.uml#_17_0_12b803b5_1292364137078_17156_1878\"/>\n\t\t"
 + "<eAnnotations xmi:id=\"_xUOVIsqEEeGr09qrcP0Uig\" source=\"http://www.eclipse.org/uml2/2.0.0/UML\"\n\t\t"
 + "references=\"../../Metamodels/utp.uml#_zYIA8PvkEeGryt8C_nFAIg\"/>\n\t"
 + "</profileApplication>";
while (input.hasNext()) {
 s1 = input.nextLine();
 if (s1.contains("<profileApplication>")) {
 // debo avanzar dos líneas más
 input.nextLine();
 input.nextLine();
 output.println(profApplicationToReemplace);
 break;
 } else {
 output.println(s1);
 }
 }
while (input.hasNext()) {
 s1 = input.nextLine();
 output.println(s1);
 }
 input.close();
 output.close();
} catch (Exception e) {
 e.printStackTrace();
 fail();
 }