//

Pragmatic Domain Specific Languages in Java

26.4.2009 | 3 Minuten Lesezeit

Neal Ford hielt am Dienstag auf der JAX einen Talk über DSLs und was sie uns für Vorteile bringen. Er zeigt, daß Java bei der Unterstützung für DSL Notationen recht schnell an seine Grenzen stößt und wechselte daher für seine Beispiele dann zu Ruby. Aber da wir bei codecentric hauptsächlich uns mit Java beschäftigen, habe ich mir mal angesehen was möglich ist und was man damit eigentlich tun kann. Einige Entwickler haben bereits das neue Builder pattern von Josh Bloch mittels eines fluid Interfaces umgesetzt. Aber dieses Pattern hat ein Problem: das sogenannte „finishing problem“. Weil das Builder pattern mittels verketteter Methoden arbeitet und Werte via Rückgabeparameter übergibt sind zu verschiedenen Zeitpunkten bestimmte Werte noch nicht initialisiert. Neal zeigte ein von jMock inspiriertes Beispiel wie man dieses Problem in Java lösen kann. Dies inspirierte mein folgendes Beispiel, welches so oder so ähnlich auch schon von GWT oder Swing Entwicklern verwendet wird.

Mein Java DSL Beispiel

1Session ormPitfalls = new Session() {{
2    speaker("Mirko");
3    attending("Fabian");
4    attending("a lot of other people");
5    at("Rheingoldhalle");
6    at(new JaxDate() {{
7        day2();
8        session2();
9    }});
10}};
11

Auf den ersten Blick sieht dies nicht besonders ungewöhnlich aus. Aber… Oh.. doppelte geschweifte Klammern?? Der hier verwendete Trick ist eine  anonyme Klasse, welche Session erweitert (genauso bei JaxDate etwas weiter). Nachdem der Standard Konstruktor ausgeführt wurde laufen die sogenannten Initializer Blocks. Dieser Initializier, welcher in geschweiften Klammern geschrieben wird, enthält nun Methodenaufrufe in einer DSL im Kontext Session.

Braucht man das?

Genauer gesagt hat dieses Vorgehen sogar probleme. Jede Instanz hat seine eigene Klassendefinition, welche zur Laufzeit erstellt werden muss, was eine etwas längere Erstellungszeit nach sich zieht. Ausserdem ist der Speicherverbrauch etwas größer und getClass().getName() liefert natürlich einen anderen Namen.

Und zuletzt bleibt natürlich die große Frage: Wollen wir wirklich, daß Fachabteilungen in Produktion laufenden Code mittels einer DSL schreiben?

Aber…

… es gibt eine gute Verwendung: Testen! Sehr gerne sähen wir mehr Fachabteilungen am Testen beteiligt, aber selbst mit guten Tools gibt es immernoch einen großen Aufwand an Mocks und Dummies welche erstellt werden müssen. Der oben gezeigte Code um Objektinstanzen zu erstellen ist aber sehr verständlich. Tester können die Domänenmethoden verwenden anstelle sich mit der Erzeugung von Datumsobjekten durch die Java Calendar API rumschlagen zu müssen. Ausserdem ist der Code viel lesbarer und besser. Bis jetzt würde die zu testende und die testende Methode jeweils über eigenen Code ein Datum berechnen. Da es aber keinen Test für den Test gibt wird nicht verifiziert, daß die Datumsberechnung ok ist. Im obigen Beispiel ist die Datumsberechnung jedoch nur einmal implementiert.

Kleiner Calendar Exkurs

Da ich gerade beim Calendar bin. Wie berechnent man „morgen mittag“? So?

1Calendar today = Calendar.getInstance();
2today.setTime(calendar.getTime());
3today.add(Calendar.DAY_OF_YEAR, 1);
4today.set(Calendar.HOUR_OF_DAY, 12);
5today.set(Calendar.MINUTE, 0);
6today.set(Calendar.SECOND, 0);
7today.set(Calendar.MILLISECOND, 0);
8

Das sieht nicht nur hässlich aus, sondern hat auch teilweise falsche Semantik. Besser wäre:

1Calendar calendar = GregorianCalendar.getInstance();
2Calendar today = calendar.clone();
3today.setTime(calendar.getTime());
4Calendar tomorrow = today.clone();
5tomorrow.add(Calendar.DAY_OF_YEAR, 1);
6Calendar tomorrowNoon = tomorrow.clone();
7tomorrowNoon.set(Calendar.HOUR_OF_DAY, 12);
8tomorrowNoon.set(Calendar.MINUTE, 0);
9tomorrowNoon.set(Calendar.SECOND, 0);
10tomorrowNoon.set(Calendar.MILLISECOND, 0);
11

uhh.. zumindest versucht dieser Code den Zwischenzuständen korrekte Namen zu geben. Wenn dieser Code aber in einer Methode namens tomorrowNoon() in unserem CustomCalendar/Date Objekt wäre, würde die Semantik viel besser sein (die Methode arbeitet dann nur auf „this.„), insbesondere ist der Code vor dem Anwender versteckt.

Fazit

Domain Specific Languages sind sehr interessant; insbesondere in Programmiersprachen welche eine noch freundlichere Notation erlauben. Jedoch ist die Zeit in vielen Projekten noch nicht reif. Für Tests hingegen stellen sie schon jetzt ein probates Mittel dar um Fachabteilungen mit einzubeziehen und Testcode les- und wartbarer zu machen. Generell ist es immer hilfreich Methodennamen sprechend zu wählen und die Funktionalität an der Fachdomäne auszurichten.

Beitrag teilen

Gefällt mir

0

//

Weitere Artikel in diesem Themenbereich

Entdecke spannende weiterführende Themen und lass dich von der codecentric Welt inspirieren.

//

Gemeinsam bessere Projekte umsetzen

Wir helfen Deinem Unternehmen

Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.

Hilf uns, noch besser zu werden.

Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.