DSL-sprog skrevet i Java holder styr på hundredvis af police-regler

Illustration: mkabakov/Bigstock
Der er ingen grund til krumspring, hvis man skal skrive et sprog, der kan udtrykke domænespecifik viden. Et gammelt sprog som Java kan sagtens bruges til opgaven.

Man behøver ikke at tage tricks i brug for at skrive et domænespecifikt sprog (DSL) i Java. Det mener i hvert fald de to franskmænd Gilles Di Guglielmo og Alexandre DuBreuil, der arbejder i forsikringsselskabet Les Furets.

De gav et foredrag om deres open source framework Doov, som er et lille sprog til at validere input med, på konferencen JDK IO, der blev afholdt i København i midten af juni.

Hos forsikringsselskabet skal der tjekkes knap 500 regler, når kunderne indberetter forsikringskrav, eller vil have et tilbud på en police.

Tidligere var reglerne programmeret som selvstændige klasser i Java - en klasse pr. regel. Det medførte problemer med styring og revision af reglerne. Derudover gav det problemer med ydelsen, fortæller Gilles Di Guglielmo.

Nu er selskabet gået over til det domænespecifikke sprog Doov, der skrives som helt almindelig Java, og benytter et såkaldt ‘fluent’-api, hvor operationer kædes sammen på en måde, så det giver læsbar mening. Det kan se sådan ud:

ValidationRule rule = DslSampleModel
   .when(userBirthdate.ageAt(today()).greaterOrEquals(18)
   .and(accountEmail.length().lesserOrEquals(maxEmailSize))
   .and(accountCountry.eq(Country.FR))
   .and(accountPhoneNumber.startsWith("+33")))
   .validate();

De gamle klasser, som forsikringsselskabet benyttede, var en skønsom blanding af if-sætninger og validering med logiske operatorer. Det kan i det nye sprog barberes ned til få linjer, som er meget mere forståelige.

Snakke-sproget Java kan godt bruges til DSL

Som de fleste nok er enige i, så er Java noget af et snakkesagligt sprog, hvor der skal skrives en masse. Men det kan sagtens lade sig gøre at benytte sproget til at udtrykke den domænespecifikke viden, og nyere Java-faciliteter, såsom lambda’er og streams, gør det nemmere at opnå dette, mener de to udviklere.

En domæneklasse skal blot udstyres med annotationer, som herunder, for at kunne valideres. Så klarer værktøjer resten af sagen i et snuptag.

// Root class of model
class Model {
  User user;
}
 
// Add key named EMAIL
enum ModelFieldId {
  EMAIL;
}
 
// Annotate email field
class User {
  @Path(field = EMAIL
        readable = ... )
  String email;
} 

Det er ikke bare datavalidering, der bliver nemmere. Det er også test af reglerne, der lettes, og den slags er måske endnu vigtigere i forsikringsverdenen, end så mange andre steder, på grund af lovgivning og regler, der omfatter den branche.

Reglerne kan også skrives ud som naturligt sprog, som i eksemplet herunder. Og det er af stor betydning i forhold til revision og opfyldelse af reglementerne for forsikringsvirksomhed.

System.out.println("> " + EMAIL_VALID.readable());
 
> When (email matches '\w+[@]\w+.com' or
email matches '\w+[@]\w+.fr') validate

Reglerne kan tilføjes et ‘registry,’ således at der er centralt styr på reglerne i systemet. En manglende løsning på dette område var et problem i det gamle system.

Ingen grund til at bruge Groovy

I Java-verdenen er Groovy, som afvikles på Javas virtuelle maskine, det sprog, som praler af at være bedst til DSL'er og metaprogrammering. Så hvorfor ikke Groovy til Doov?

»Det spørger alle om,« siger Alexandre DuBreuil.

»Men der er masser af DSL’er, som er implementeret i Java, og de fungerer rigtig godt.«

Det gælder eksempelvis Jooq, som er en måde at skabe SQL-forespørgsler i Java-kode.

»Andre grunde er, at alle vores værktøjer bruger Java, og det er det, vores udviklere kan. Det giver bedst mening at bygge oven på den ekspertise. At tilføje et nyt sprog giver bare mere kompleksitet.«

Men man slipper ikke for parenteser og punktummer i Javas syntaks, og det får DSL-koden til at se meget Java-agtig ud. Det gør dog ikke noget, synes de to.

»Det er OK,« siger Gilles Di Guglielmo.

»Det er ikke alt for frustrerende at læse forretningsregler med et punktum imellem.«

Derudover er indlæringskurven lav.

Og brugen af Java gjorde det også nemmere at flytte reglerne fra den tidligere regelmaskine til DSL-sproget.

Det giver også bedre mening for forretningsfolket, som kan tilgå forretningsreglerne, der kan skrives ud i naturligt sprog, til HTML-dokumenter.

Det er dog udviklerne, der skriver reglerne, sammen med folk fra forretningslaget. Og der skal også skrives tests i forbindelse med nye regler.

Historisk set har idealet for DSL’er i almindelighed været, at domæneeksperterne på egen hånd kan skrive koden, selvom der næppe er mange eksempler på, at den tankegang kan realiseres i praksis.

Og det er i øvrigt slet ikke noget god ide, mener Alexandre DuBreuil.

»Udvikleren kender til kode, logik og tests, og forstår, hvordan koden vil opføre sig på serveren. Det er viden, som kun udvikleren har - det er deres job.«

Tips og korrekturforslag til denne historie sendes til tip@version2.dk
Følg forløbet
Kommentarer (4)
sortSortér kommentarer
  • Ældste først
  • Nyeste først
  • Bedste først
Peter Stricker

Artiklen bruger på et tidspunkt betegnelsen Fluent API. Jeg synes det er en meget bedre betegnelse for det, der er vist i det lille eksempel.

Jeg ville heller ikke kalde Mockito for et unit test DSL, men et framework med et fluent API.

Jeg vil gå med til at kalde Doov for et domænespecifikt API.

Derudover ser jeg intet i eksemplet, der ville gøre det svært at bruge i et program skrevet i Groovy, Scala, Kotlin eller lignende.

Sune Marcher

Det er et eksempel på et indlejret DSL, som er implementeret med method chaining, som sikkert er det samme som fluent API.


Fluent API'er anvender method chaining, men er væsentligt mere end bare method chaining i sig selv.

Idéen er at bygge et builder-klassehierarki hvor metoderne returnerer et objekt med de operationer, der giver mening ud fra den operation du lige har kaldt.

En simpel builder, der ikke kan andet end method chaining til at sætte properties, vil jeg ikke betegne som et fluent API.

Log ind eller Opret konto for at kommentere