Pragmatische DSL in der Praxis, mit Java und Drools

Keine Kommentare

Martin Fowlers Vortrag auf der Java Users Group in Köln hat mich dazu motiviert etwas aus einem meiner Projekte bei codecentric zu erzählen. Denn Martin sprach davon, dass der wahre Charme von DSLs die Lesbarkeit sei. Programmiert man in der „Sprache des Fachbereichs“ kann dieser ganz leicht prüfen ob die Logik richtig sein könnte. Diese Argumentation ist häufig viel treffender und hilfreicher als das sonst oft vorgebrachte Argument, dass doch der Fachbereich auch Code schreiben könne.
Nun nahm sich Martin das Recht heraus, darüber zu schimpfen, dass Java keine lesbare Sprache sei. Mann müsse detektivisch Java code mühsam entziffern. Als Konsequenz daraus entwickelte er seine eigene Sprache und einen dazu passenden Parser. Diesbezüglich bemerkte er:

Einige Leute denken, dass Parser programmieren schwierig sei, weil sie an der Universität keinen Compilerbau-Kurs belegt haben. Und diejenigen die an diesen Kursen teilnahmen wissen, dass Parser schreiben schwierig ist.


Also verwarf er seine selbstgeschriebene DSL, da sie erstaunliche Ähnlichkeit mit gültigem Ruby Code hat.
Aber der springende Punkt ist, dass die eigentliche Formatierung nicht so wichtig ist, solange man klare Konzepte verwendet. Dann nämlich kann man seine DSL in einer Sprache wie Ruby schreiben, oder so wie wir, in Drools.
Drools ist eine Regelmaschine und damit schon sehr gut auf die Auswertung von Zuständen vorbereitet.
In unserem Projekt benötigten wir im wesentlichen 3 DSLs:

  1. Eine Empfehlungsermittlung, welche aus Profildaten Produkte empfiehlt.
  2. Einen Validator, der Profile auf Konsitenz prüfen kann.
  3. Einen Preisberechner, der Profildaten zur Preisermittlung verwendet.

Diese 3 waren sich so ähnlich, dass wir vermuteten, dass wir eine Technologie für alle Fälle verwenden können. Und das obwohl die Unterschiede durchaus relevant sind: Die Empfehlung wertet Profildaten aus und versieht Produkte mit Empfehlungen, während die Validierung Fehler erzeugt. Die Berechnung verwendet Tabellen und Formeln und liefert Preise.

Ohne groß über Alternativen nachzudenken wussten wir, dass Drools die perfekte Technologie für uns war. Also mussten wir nur noch einen Weg finden unser Fachmodell in Drools zu integrieren.

Die 3 Anwendungsfälle lesen alle aus einem Profil. Dafür hatten wir bereits ein Domänenobjekt, allerdings wollten wir nicht auf die Werte über einfache Getter zugreifen. So wollten wir es möglich machen auf ein Alter zuzugreifen, obwohl wir im Profil nur ein Geburtsdatum mitführen. Deshalb erfanden wir für diese Zwecke einen Wrapper um unser Profil. Der Wrapper selbst erhält allerlei nützliche Methoden um aus der DSL in der Sprache des Fachbereiches Werte auszulesen.
Die Ausgaben erfolgen in Drools über globale Objekte auf die Werte gesetzt werden können. Also müssen wir nur dafür sorgen, dass diese Objekte ansprechend benannt sind.
Mit diesem Konzept und ein wenig Feintuning an der Benennung, entstand eine lesbare DSL. Unser Kunde kann die Empfehlungen und Validierungen lesen und prüfen und sogar die Preisberechnung mit aktuellen Werten befüllen.
Urteilt selbst und teilt mir mit was ihr denkt. Ist doch eine recht überschaubare und einfache DSL?

Hier unsere Validierungs DSL mit Drools:

global ValidierungsFehler fehler;
 
rule "Alter muss kleiner als 101 sein"
	when
	  Profil( alter > 100 )
	then
	  fehler.add("Wenn Sie älter als 100 Jahre sind, wenden Sie sich bitte an ihren persönlichen Berater.", Feld.Geburtsdatum);
end
 
rule "Das Geburtsdatum darf nicht in der Zukunft liegen"
	when
	  Profil( geburtsdatum > heute )
	then
	  fehler.add("Unsere Dienstleistung ist nur für bereits geborene Personen möglich.", Feld.Geburtsdatum);
end

Und so sieht unsere Empfehlungs DSL aus:

global Produktportfolio produkte;
 
rule "Kinder"
when
	Profil( alter <= 15 )
then
	produkte.empfehle( "PRODUKT_A", 5 );
	produkte.empfehle( "PRODUKT_B", 0 );
	produkte.empfehle( "ANDERES_PRODUKT", 3 );
end

Und ein Screenshot unserer Preisberechnung. Es ist möglich die Implementierungsdetails auszublenden.:

Der Fachbereich ist sehr zufrieden mit dem Ergebnis. Sie können alles „programmierte“ prüfen und sogar die Tabellen an neue Preise anpassen.

Fabian Lange ist Lead Agent Engineer bei Instana und bei der codecentric als Performance Geek bekannt. Er baut leidenschaftlich gerne schnelle Software und hilft anderen dabei, das Gleiche zu tun.
Er kennt die Java Virtual Machine bis in die letzte Ecke und beherrscht verschiedenste Tools, die JVM, den JIT oder den GC zu verstehen.
Er ist beliebter Vortragender auf zahlreichen Konferenzen und wurde unter anderem mit dem JavaOne Rockstar Award ausgezeichnet.

Share on FacebookGoogle+Share on LinkedInTweet about this on TwitterShare on RedditDigg thisShare on StumbleUpon

Kommentieren

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.