Wir haben gerade ein Kundenprojekt im Eclipse-
bzw.
Eclipse-Modeling-Framework-Umfeld
fertiggestellt, das aus der Erstellung von mehreren Plugins für die
bestehende Anwendung des Kunden bestand. Wir haben dabei die
Programmiersprache Xtend in der
Version 2.4.3 eingesetzt. Dieser Artikel geht auf unsere Erfahrungen
mit Xtend ein, die, soviel sei schon einmal vorweg genommen, eher
negativ sind.
Ursprünglich wollten wir das Projekt in
Scala umsetzten, einer Sprache in der
man sehr leicht die zwei funktionalen
APIs, die den Kern des
entwickelnten Plugins bilden, hätte implementieren können. Die eine
API ist eine kompositionale DSL für das Format tabellarischer Daten,
die andere ist ebenfalls kompositional und dient der Definition von
Update-Operationen eines EMF-Modell. Der Kunde wollte aber lieber bei
Sprachen und Bibliotheken bleiben, die bereits bei ihm im Einsatz
waren. Dazu zählte auch Xtend, eine Sprache die zumindest einige
Konzepte der funktionalen Programmierung enthält, und uns daher immer
noch besser erschien als „plain Java“.
Xtend wirbt damit, dass es eine Erweiterung von Java sei, und man mit
ihm „Java 10 schon heute“ bekommen würde. Eine Behauptung die so nicht
stimmt, was ich im Folgenden näher darlege.
Implementiert ist Xtend als Eclipse-Plugin auf der Basis von
Xtext. Xtext erlaubt die Definition
von neuen Sprachen auf Basis einer Grammatik und Übersetzungscode zu
beliebigen anderen Sprachen, z.B. Java. Es liefert einem außerdem mit
relativ wenig Aufwand eine Integration dieser Sprache in das
Eclipse-Framework. Diese Integration ist aber eher spärlich,
insbesondere verglichen mit der Integration von Java. Dies muss man
auch schon als einen ersten großen Negativpunkt aufführen, da Dinge
wie „Gehe zu Definition“ und „Suche Verwendungen“ nur deutlich
schlechter (z.B. erst nach einem Build), und teilweise gar nicht
funktionieren (bei sog. Templates).
Außerdem ist der Xtend-Compiler nicht gerade schnell, bzw. leckt
irgendeine Schicht der Implementierung offensichtlich Speicher,
wodurch die Kompilierung immer langsamer wird und regelmäßig Neustarts
von Eclipse notwendig werden. Ursprünglich beinhaltete unser Projekt
z.B. circa 1500 von uns generierte Xtend-Klassen. Diese Menge hat die
ganze Entwicklung aber derart behindert, dass wir für diesen Teil auf
die Generierung von Java-Code umgestiegen sind. Das hat die Sache
etwas entschärft.
Die Sprachelemente, die Xtend von Java abgrenzen, waren
nichtsdestotrotz sehr hilfreich für die Umsetzung des Projekts. Dazu
gehört der deklarative Grundansatz (keine Statements, alles sind
Expressions), sowie Funktionsliterale der Form
[ Type arg | body ]
Diese kann der Xtend-Compiler, ähnlich wie Java 8, automatisch in
„Single-Abstract-Method“-Typen konvertieren. Für den allgemeinen Fall
sind einige generische Funktionstypen mit enthalten. Listen und
Map-Literale machen insbesondere das Testen deutlich einfacher. Auch
dass alle Parameter und „Variablen“ per default „final“ sind, also
nicht neu gebunden werden können, sowie die Typ-Inferenz von Variablen
und Rückgabetypen, machen das Programmieren in Xtend im allgemeinen
schon wesentlich angenehmer als in Java. Außerdem kann man Extension
Methods definieren und die Standardbibliothek tut dies auch reichlich
für die Java-Collections. Das macht beispielsweise folgenden Code
möglich:
def static <A> filterFirst(List<A> all, (A) => boolean pred) {
val matching = all.filter(pred)
if (matching.empty)
throw new Exception("...")
else
matching.get(0)
}
Der Typ List ist hier die Standard-Java-Collection java.util.List,
und filter eine Extension Method die die Xtend-Bibliothek hinzufügt.
Was dann aber wiederum sehr lästig ist, ist dass man keine „anonymen
Klassen“ wie in Java definieren kann. Es gibt keine Expression zur
Instantiierung einer abstrakten Klasse mit mehr als einer Methode.
Gerade bei einem funktionalen Programmierstil stößt man sehr schnell
an dieses, gegenüber Java fehlende Sprachelement. Auch „inner classes“
gibt es nicht, und auf der Mailingliste taucht immer wieder der
Hinweis auf „das musst du dann in Java machen“. Daher kann man Xtend
meiner Meinung nach auch nicht als Erweiterung von Java bezeichnen.
Die Entwickler versuchen zwar alles zu bieten was Java „kann“, aber an
dieser und anderen Stellen fehlt etwas (bis zur aktuellen Version 2.5
fehlt es zumindest immer noch).
Ein weiteres Grundproblem von Xtend ist, dass der Compiler
offensichtlich kein korrektes bzw. vollständiges Modell von Java
verwendet. Immer wieder passiert es, dass der Xtend-Code fehlerfrei zu
sein scheint und der Compiler den Java-Code generiert hat, dass aber
anschließend der Java-Compiler einen Fehler im generierten Code
meldet. Ganz besonders schlimm war das in etwas älteren Versionen
(2.1), aber selbst in der aktuellen Version (2.5) kann das immer
noch passieren.
Insgesamt hat uns Xtend die Umsetzung des Projekts sicherlich
erleichtert, aber nur im Vergleich zu einer Implementierung in Java.
Mit einer „erwachsenen“ Programmiersprache, wie z.B. Scala, kann Xtend
(noch) nicht mithalten.