<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
   <title>compte goutte</title>
   <link rel="alternate" type="text/html" href="http://www.innoq.com/blog/mrs/" />
   <link rel="self" type="application/atom+xml" href="http://www.innoq.com/blog/mrs/atom.xml" />
   <id>tag:www.innoq.com,2009:/blog/mrs//20</id>
   <updated>2009-03-03T10:56:34Z</updated>
   <subtitle>a sporadical weblog by Marc Schlienger</subtitle>
   <generator uri="http://www.sixapart.com/movabletype/">Movable Type 3.31</generator>

<entry>
   <title>Generate Text with loremipsum.de</title>
   <link rel="alternate" type="text/html" href="http://www.innoq.com/blog/mrs/2009/03/text_generator_loremipsumde.html" />
   <id>tag:www.innoq.com,2009:/blog/mrs//20.3505</id>
   
   <published>2009-03-03T10:50:24Z</published>
   <updated>2009-03-03T10:56:34Z</updated>
   
   <summary>On loremipsum.de: [...] Simply generate as much Lorem ipsum text as you require [...] Really useful once you need a specific amount of text. Much of the background of Lorem Ipsum is also well described on the site....</summary>
   <author>
      <name>Marc Schlienger</name>
      <uri>http://www.innoq.com/blog/mrs/</uri>
   </author>
         <category term="util" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="en" xml:base="http://www.innoq.com/blog/mrs/">
      <![CDATA[On <a href="http://www.loremipsum.de/index_e.html">loremipsum.de</a>:

<blockquote>[...] Simply generate as much Lorem ipsum text as you require [...]</blockquote>

Really useful once you need a specific amount of text. Much of the background of Lorem Ipsum is also well described on the <a href="http://www.loremipsum.de/about_lorem_ipsum.html">site</a>.]]>
      
   </content>
</entry>
<entry>
   <title>Useful stuff on stateofflow.com/projects</title>
   <link rel="alternate" type="text/html" href="http://www.innoq.com/blog/mrs/2009/02/useful_stuff_on_stateofflowcomprojects.html" />
   <id>tag:www.innoq.com,2009:/blog/mrs//20.3504</id>
   
   <published>2009-02-25T10:18:24Z</published>
   <updated>2009-03-03T10:56:34Z</updated>
   
   <summary>Really interesting eclipse plugins there, especially EclipseMetrics, I&apos;ll definitively turn back and try the others soon. More on http://www.stateofflow.com/projects...</summary>
   <author>
      <name>Marc Schlienger</name>
      <uri>http://www.innoq.com/blog/mrs/</uri>
   </author>
         <category term="dev" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="en" xml:base="http://www.innoq.com/blog/mrs/">
      <![CDATA[Really interesting eclipse plugins there, especially <a href="http://www.stateofflow.com/projects/16/eclipsemetrics">EclipseMetrics</a>, I'll definitively turn back and try the others soon.

More on <a href="http://www.stateofflow.com/projects">http://www.stateofflow.com/projects</a>]]>
      
   </content>
</entry>
<entry>
   <title>Levels of code review</title>
   <link rel="alternate" type="text/html" href="http://www.innoq.com/blog/mrs/2009/02/levels_of_code_review.html" />
   <id>tag:www.innoq.com,2009:/blog/mrs//20.3501</id>
   
   <published>2009-02-18T13:54:37Z</published>
   <updated>2009-03-03T10:56:34Z</updated>
   
   <summary>I was recently involved in code reviews on a project. During the review activity, I came to the following levels of code review: The lower you are, the better is the tool support for finding hot spots. Nevertheless, I fint...</summary>
   <author>
      <name>Marc Schlienger</name>
      <uri>http://www.innoq.com/blog/mrs/</uri>
   </author>
         <category term="se" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="en" xml:base="http://www.innoq.com/blog/mrs/">
      <![CDATA[I was recently involved in code reviews on a project. During the review activity, I came to the following levels of code review:

<a href="http://www.innoq.com/blog/mrs/2009/02/18/CodeReviewLevels1.html" onclick="window.open('http://www.innoq.com/blog/mrs/2009/02/18/CodeReviewLevels1.html','popup','width=603,height=430,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false"><img src="http://www.innoq.com/blog/mrs/2009/02/18/CodeReviewLevels-thumb.PNG" width="400" alt="levels of code review" /></a>

The lower you are, the better is the tool support for finding hot spots. Nevertheless, I fint it interesting to have this layering in mind when reviewing code. Depending on the layer, you have a different focus and the range of code you are looking at may vary as well.

This table may be not exhaustive, so I would be happy to get feedback on that.]]>
      
   </content>
</entry>
<entry>
   <title>Fine granular unit testing with oAW</title>
   <link rel="alternate" type="text/html" href="http://www.innoq.com/blog/mrs/2009/02/fine_granular_unit_testing_wit_1.html" />
   <id>tag:www.innoq.com,2009:/blog/mrs//20.3500</id>
   
   <published>2009-02-18T12:49:20Z</published>
   <updated>2009-03-03T10:56:34Z</updated>
   
   <summary>I propose here a simple approach for testing your generator written using oAW and the JUnit test framework. A generator usually consists of model to model transformations and model to code transformations. It would be nice if one could test...</summary>
   <author>
      <name>Marc Schlienger</name>
      <uri>http://www.innoq.com/blog/mrs/</uri>
   </author>
         <category term="mdd" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="en" xml:base="http://www.innoq.com/blog/mrs/">
      <![CDATA[I propose here a simple approach for testing your generator written using oAW and the JUnit test framework. A generator usually consists of model to model transformations and model to code transformations. It would be nice if one could test these steps independently, without having to run the whole generator (or workflow in oAW terms).

Let's consider this simple example: convert from an object model (a class) to a relational model (a table) and finally create text (SQL statements).

For the first transformation (M2M, from class to table), we have an Xtend extension (in the file obj2rel.ext). Please note that the code has been simplified in the next listings for readability.

<pre>Table transformClass( Class c ):
	setName( c.name ) ->
	getColumns().add( c.attributes.transformAttribute() )
;</pre>

For the second one (M2T, from Table to text), we have an XPand template (in the file rel2sql.xpt):

<pre>«DEFINE sql for Table»
create table «name» ( «EXPAND sql for columns » )
«ENDDEFINE»</pre>

First of all I would like to test if the table created after the M2M transformation is right. For that, I define a unit test:

<pre>public class TestTable {
    private XtendCaller ext;
	
    @Before
    public void init(){
        ext = new XtendCaller("my::package::obj2rel", 
            "metamodelPackage_Object",
            "metamodelPackage_Relational");
    }
	
    @Test
    public void testObj2Rel(){
        Class c = createTestClass("TestClass", "att1",
            "String", "att2", "Integer");
        Table t = (Table)ext.call("transformClass", c );
        assertEquals( c.getName(), t.getName() );
        assertEquals( c.getAttributes().size(),
            t.getColumns().size() );
        // more asserts ...
    }
}</pre>

Then, as I did it for my extensions, I test the model to text transformation by defining another unit test:

<pre>public class TestSql {
    private XpandCaller xpt;
	
    @Before
    public void init(){
        xpt = new XpandCaller("metamodelPackage_Relational");
    }
	
    @Test
    public void testObj2Rel(){
        Table t = createTestTable("...");
        xpt.evaluate("my::package::rel2sql", pl1dt);
        String expexted = IOUtils.toString( 
            new FileInputStream(new File("reference.file")) );
        assertEquals(expected, xpand.getOutput() );
    }
}</pre>

As you can see, the various unit tests can cover different parts of the transformation independently. You can also combine a model to model transformation and a model to text transformation in one test if you do not want to use intermediate test data. The real advantage comes by leveraging the JUnit framework in an IDE like Eclipse where you can simply use the diff feature to see where a test fails. This is extremely helpful for comparing string objects such as a text file (which contains the reference artefact) and the result of a M2T template transformation (see next figure).

<a href="http://www.innoq.com/blog/mrs/2009/02/18/compare.PNG">
<img alt="diff feature of JUnit plugin in Eclipse" src="http://www.innoq.com/blog/mrs/2009/02/18/compare.PNG" width="700" />
</a>

The two helper classes XtendCaller and XpandCaller are helpful decorators over the two classes XtendFacade resp. XpandFacade already available within the oAW framework. You will the code for these classes here:
<a href="http://www.innoq.com/blog/mrs/2009/02/18/XtendCaller.java">XtendCaller</a>
<a href="http://www.innoq.com/blog/mrs/2009/02/18/XpandCaller.java">XpandCaller</a>
<a href="http://www.innoq.com/blog/mrs/2009/02/18/StringOutput.java">StringOutput</a>

Thanks to <a href="http://logean.blogspot.com">Antoine Logean</a> for his feedback on this approach.
]]>
      
   </content>
</entry>
<entry>
   <title>oAW Xtend create expressions and Ecore containment</title>
   <link rel="alternate" type="text/html" href="http://www.innoq.com/blog/mrs/2009/01/oaw_xtend_create_expressions_and_ecore_containment.html" />
   <id>tag:www.innoq.com,2009:/blog/mrs//20.3494</id>
   
   <published>2009-01-20T09:56:55Z</published>
   <updated>2009-03-03T10:56:34Z</updated>
   
   <summary>I recently spent an hour figuring out why my Xtend/Xpand code did not produce what I expected. I&apos;m writing a code generator that generates PL/I source code for call level interfaces based on abstract service specifications. A service has an...</summary>
   <author>
      <name>Marc Schlienger</name>
      <uri>http://www.innoq.com/blog/mrs/</uri>
   </author>
         <category term="mdd" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="en" xml:base="http://www.innoq.com/blog/mrs/">
      <![CDATA[I recently spent an hour figuring out why my Xtend/Xpand code did not produce what I expected. I'm writing a code generator that generates PL/I source code for call level interfaces based on abstract service specifications. A service has an input structure and an output structure.

<blockquote>simplified PL/I service signature:

  input: Structure
  - typeName: Field
  - businessAttribute1: Field
  - ...
  - businessAttributeN: Field

  output: Structure
  - typeName: Field
  - further attributes...
</blockquote>

In each of them there is a structure field containing the type name among other business attributes. Both input and output structures should have this typeName field. During model transformation, first the input and then the output structure is created. Nevertheless, as soon as the output structure was created, the input structure kind of lost the typeName field.

After debugging (and thinking a little bit about the causes), I found out that it was due to some features of both Xtend and Ecore. I have an Xtend create expression for creating the typeName field:
<blockquote>
create Field createTypeNameField():
  // code omitted
;
</blockquote>

In the Ecore model, there is a containment association between Structure and Field, i.e. a structure contains a list of fields.

And there we are, the create expression caches the Field instance, the key is "empty" since the create expression has no parameter (kind of singleton). Hence, during the second assignment of the typeName field (to the output structure), the first containment reference to the input structure gets "overwritten" (aka Ecore containment feature).

I solved the problem by assuring the creation of a separate instance of the typeName field each time. For this, the create expression has now a key parameter which is different for the input and for the output structures. Now the cache for the typeName field is parametrized with the key, even if the key is not used within the code of the expression:

<blockquote>
create Field createTypeNameField(String key):
  // code omitted
;
</blockquote>


<strong>As a summary, be aware of create expression with objects involved in containment associations.</strong>]]>
      
   </content>
</entry>
<entry>
   <title>the begining of a mac career?</title>
   <link rel="alternate" type="text/html" href="http://www.innoq.com/blog/mrs/2009/01/the_begining_of_a_mac_career.html" />
   <id>tag:www.innoq.com,2009:/blog/mrs//20.3493</id>
   
   <published>2009-01-13T21:33:41Z</published>
   <updated>2009-03-03T10:56:34Z</updated>
   
   <summary>I recently faced the following error message on my PC: This definitely made me take a turn in my computer career......</summary>
   <author>
      <name>Marc Schlienger</name>
      <uri>http://www.innoq.com/blog/mrs/</uri>
   </author>
         <category term="fun" scheme="http://www.sixapart.com/ns/types#category" />
   
   
   <content type="html" xml:lang="en" xml:base="http://www.innoq.com/blog/mrs/">
      <![CDATA[I recently faced the following error message on my PC:

<a href="http://www.innoq.com/blog/mrs/2009/01/13/changePwd.png"><img alt="changePwd.png" src="http://www.innoq.com/blog/mrs/2009/01/13/changePwd-thumb.png" width="400" height="300" /></a>

This definitely made me take a turn in my computer career...]]>
      
   </content>
</entry>

</feed>

