Wednesday, June 19, 2013

Five good reasons to port your code generator to Xtend

If you happen to have an existing code generator written in Xpand or some other (template) language, here are five good reasons why you should migrate to Xtend.

Xtend is fast

Code generation adds to the development turn around time. We all know it : tools can slow us down. They take their share of CPU cycles during the daily development and all that automation is not worth it, if you have to wait for your machine all day long. Many template languages are interpreted and are therefore rather slow as they cannot benefit from optimizations done during compilation. Code generators written in these languages suffer from that of course, and if you don't care you can easily multiply the time your build takes with a slow code generator.
Xtend code is translated to readable and idomatic Java code. It runs as fast as Java, which is *very* fast and there's no additional overhead nor dependencies at runtime. Rough measures have shown that code generators implemented with Xtend are up to ten times faster then the equivalent Xpand version.

Xtend is debuggable

Code generators, just like any other software system, have a tendency to get a bit complex over time. It's not so funny to find and fix a bug in a real world code generator without any debugging support. Unfortunately that's the situation with most template languages : They don't have any good debugging support.
As Xtend code is translated to readable Java code you can always use the advanced Java debugging tools you are used to. Additionally the Eclipse debugger lets you choose whether you want to debug through the Xtend source code or the generated Java code. You can even switch back and forth during the same debug session (see the screenshot).

Better IDE Support

Xtend's Eclipse support is propably the most advanced after Java. The integration between Xtend and Java is seamless : Navigation, Call Hierarchies and even cross language refactorings just work. And Xtend features the whole Java type system and gives you errors and warnings as you type.

Template Expressions and Grey-Space Support

In contrast to typical template languages such as Xpand, templates in Xtend are expressions which yield some value. This allows for composing multiple templates and lets you pass the results around and process them.
A unique feature to Xtend is the greyspace support. It solves the conflict between pretty printing a template and pretty printing the to-be-generated output. Common template languages cannot distinguish between indentation meant for the template and indentation meant for the output. Xtend can. Here's an example (note the different coloring of whitespace):

Better Extendability

In order to reuse a code generator and adapt it to the needs of a particular project, you need to be able to hook into it and change certain implementation details. In Xpand this was supported through AOP: You could hook into any template invocation and do what seems fit.
Although very flexible, this approach is also very fragile. The original code generator cannot be evolved, since clients might hook into any template call and you break them easily. Even worse you don't get any compile-time feedback about the broken extension hook.
With Xtend you can use dependency injection together with extension providers. No AOP anymore and the solutions is even faster and statically typed. If you need to exchange some implementation, just reconfigure your dependency injection configuration and your are good.

Summary

There are many more advantages and cool features in Xtend, but I hope the five listed here are convincing enough.

Tuesday, June 18, 2013

Xtend's Extension Providers

Xtend supports extension methods very similar to how they are supported by C#. The basic idea is to make static methods available as instance method on the first argument's type. Example :

import static extension java.util.Collections.*

...

// we can use static methods from Collections like this 
val maxValue = myCollection.max // calls Collections.max(myCollection)
val minValue = myCollection.min // calls Collections.min(myCollection)
...
 

This makes code much more readable as you don't have to read inside out, but can read from left to right. Also the discoverabilty of available features via content assist works much better.

But of course using static methods all over the place is problematic, as you bind your code to the implementation which makes it hard to test and to reconfigure for different situations (e.g. use a different database system).

Enter Extension Providers!

In Xtend you can put the extension keyword to a local field or a parameter. This will make its instance methods available on the first parameter's type.

I'll explain that with an example using JPA and Java EE.

 // Java code
@PersistenceContext
EntityManager em

public LineItem createLineItem(Order order, Product product, int quantity) {
    LineItem li = new LineItem(order, product, quantity);
    order.getLineItems().add(li);
    em.persist(li);
    return li;
}

public void removeOrder(Integer orderId) {
    Order order = em.find(Order.class, orderId);
    em.remove(order);
}
 

If you add the keyword extension to the field declaration, the instance methods of the PersistenceManager get projected onto the entities. So you no longer have to write em.persist(li) but can just write li.persist:


@PersistenceContext extension EntityManager

def createLineItem(Order order, Product product, int quantity) {
    val li = new LineItem(order, product, quantity)
    order.lineItems += li
    li.persist
    return li
}

def removeOrder(Integer orderId) {
    val order = Order.find(orderId)
    order.remove
}
 

Extension provider allow for adding layer specific functionality to any classes in a non-invasive way. And you don't have to use static methods for that.

Better APIs with Extension Providers

When designing an API, you can make it very easy for the clients to have the right extension providers on the scope.

One possibility is to provide an abstract base class which contains visibly extension fields:


abstract class AbstractDao {
    @PersistenceContext
    protected extension EntityManager em; 
}

class Concrete extends AbstractDao {
 // use extension methods from EntityManager
}
 

If you don't like inheritance that much, another approach is to mark a parameter of an abstract method with the extension keyword.

interface JPACallBack {
    def void doStuff(extension EntityManager em)
}
 

When implementing that method, the IDE will automatically add the extension keword for you. The active annotations API uses that idiom.

Note that in case you define the abstract class or the interface in Java, you can add the @Extension annotation instead of the keyword.

IDE Support

Sometimes the reader might be a bit unsure where a certain member has been declared. Of course the hover as well as navigation always shows the correct declaration. In addition the semantic coloring highlights extension methods ...

...and you can even inspect the desugared version of an expression in the hover :