Development

Software-ontwikkeling
developer

Domeinspecifieke talen: meer mogelijk met minder code

Language workbenches oplossing voor complexe constructie-DSL's

© CC by 2.0: Pixabay Kreatikor
4 juli 2019

Language workbenches oplossing voor complexe constructie-DSL's

Domain-specific languages (DSL's) hebben veel voordelen. Zo is programmeren met DSL's efficiënter, sneller en minder foutgevoelig dan bijvoorbeeld programmeren in Java. De ontwikkeling van die DSL’s zelf is echter bepaald niet eenvoudig, benadrukt Tijs van der Storm. Language workbenches kunnen daar verbetering in brengen.

Programmeertalen zijn er in vele soorten en maten. Sommige staan dicht bij de manier waarop de computer werkt (bijvoorbeeld C en C++), andere staan verder van de hardware af en hebben een hoger abstractieniveau. Door een hoger niveau van abstractie hoeft de programmeur zich minder druk te maken over incidentele details, en kan hij zich meer concentreren op het probleem dat opgelost moet worden.

DSL's zijn een verregaande vorm van dit idee: computertalen toegespitst op een specifiek applicatiedomein. Hiermee kun je dus niet álle problemen oplossen, maar sommige problemen juist heel efficiënt en effectief. Programmeurs, en soms zelfs eindgebruikers, specificeren softwareoplossingen met een nadruk op wat er nodig is, in plaats van de computer te instrueren hoe het resultaat bereikt moet worden.

DSL's zijn geen nieuw idee. De eerste DSL was waarschijnlijk APT, een taal om numerieke controlsystemen mee te besturen, ontworpen in 1956 [1]. Sindsdien zijn DSL's veelvuldig succesvol toegepast. Enkele bekende voorbeelden zijn SQL voor het bevragen van databases, HTML voor webpaginaopmaak, DOT voor graafvisualisatie, of "make" voor het configureren en executeren van softwarebouwprocessen. Tegenwoordig zijn DSL's opnieuw populair door de opkomst van low-codeplatforms (bijvoorbeeld Mendix, OutSystems), en geavanceerde language workbenches die de constructie van DSL's eenvoudiger en doeltreffender maken.
 

QL: een DSL voor vraagformulieren en enquêtes

form aangifte {

  "Kocht u een huis in 2018?"

    huisGekocht: boolean

   

  "Heeft u een hypotheek?"

    hypotheek: boolean

   

  "Verkocht u een huis in 2018?"

    huisVerkocht: boolean

   

  if (huisVerkocht) {

    "Wat was de verkoopprijs?"

      verkoopPrijs: money

    "Wat was u privéschuld voor het huis?"

      schuld: money

    "Uw restwaarde is:"

      restWaarde: money = verkoopPrijs - schuld }}

Figuur 1

 

Figuur 2

Figuur 1 toont een illustratief voorbeeldprogramma (geïnspireerd op de belastingaangifte) in de Questionnaire Language (QL), een simpele, educatieve DSL toegespitst op het domein van interactieve vragenformulieren en enquêtes [2]. Onder de code staat een afbeelding van het resultaat: een user interface waarin de gebruiker de vragenlijst kan beantwoorden.

QL bestaat uit een verzameling vragen met een label (bijvoorbeeld: kocht u een huis in 2018?) en een naam (bijvoorbeeld: huisGekocht). Elke vraag heeft een type (bijvoorbeeld: boolean, money) dat bepaalt hoe het formulier getoond wordt aan de gebruiker; een vraag van het type boolean, bijvoorbeeld, wordt hier getoond als een ja/nee-selectie-element. Vragen kunnen conditioneel getoond worden en sommige 'vragen' worden berekend door middel van een expressie in termen van gegevens die de gebruiker invult (bijvoorbeeld: restwaarde).

Voordelen van DSL's

Ondanks de eenvoud van QL, illustreert de taal al veel van de voordelen van DSL's. De meeste van deze voordelen zijn een gevolg van de scheiding tussen wat en hoe: de gebruiker specificeert wat, de taalengineer realiseert hoe.

DSL-code abstraheert van low-level implementatiedetails en vermijdt 'boilerplate' code. Een gevolg hiervan is dat DSL-code vaak ordegroottes kleiner is dan traditionele programmacode. In QL bijvoorbeeld, is geen spoor te bekennen van hoe GUI-events afgehandeld worden, en hoe en wanneer rekenvragen uitgerekend worden; al die logica zit onder de motorkap van de QL-compiler. Een ontwerper van een vragenlijst hoeft dus geen ervaren GUI-programmeur te zijn om QL te gebruiken.

Een meer specifieke en minder expressieve notatie betekent ook dat er minder vrijheidsgraden voor de programmeur zijn, met als gevolg dat de kans op fouten kleiner wordt. Programmeerfouten als null-pointer dereferencing en oneindige loops zijn bijvoorbeeld niet mogelijk in QL, omdat de taal eenvoudigweg niet toestaat om code met dat soort fouten op te schrijven. Daarbij komt dat domeinspecifieke notatie betere foutdetectie en optimalisatie mogelijk maakt. Bij QL zou de compiler cyclische afhankelijkheden kunnen detecteren (bijvoorbeeld: restwaarde: money = schuld - restwaarde) en hierover zinvolle foutmeldingen rapporteren. Dit is vrijwel onmogelijk als de vragenlijst direct in Java geprogrammeerd zou zijn; de Java-compiler heeft immers geen kennis van het domein van vragenlijsten. Eenzelfde redenering geldt voor domeinspecifieke optimalisaties, die buiten het bereik van gewone programmeertalen liggen.

Tot slot is DSL-code minder afhankelijk van een specifiek executieplatform. Daardoor kan dezelfde applicatie op basis van verschillende platforms gerealiseerd worden en naar nieuwe technologieën geporteerd worden, zonder de DSL-code zelf te hoeven aanpassen. QL als taal is er bijvoorbeeld onafhankelijk van of executie plaatsvindt via traditionele desktop-GUI-frameworks, webgebaseerde UI's of mobiele platforms.

Language engineering met language workbenches

De voordelen die DSL's softwareontwikkeling kunnen bieden, zijn niet gratis: er moet immers een taal ontwikkeld worden, met parsers, compilers, checkers, interpreters, IDE's, documentatie, etc. DSL-implementaties zijn bovendien zelf software die getest, onderhouden en gedocumenteerd moet worden. Hoe kan DSL-ontwikkeling effectiever en laagdrempeliger worden gemaakt?

Dit is precies wat language workbenches proberen te bereiken. Martin Fowler noemde het een potentiële "killer-app for domain-specific languages" [3]. Language workbenches kunnen gezien worden als compiler-compilers 'on steroids': geïntegreerde omgevingen om alle aspecten van taalontwikkeling te ondersteunen, inclusief integrated development environment (IDE)-faciliteiten als syntax highlighting, outline views, foutmarkering, jump-to-definition, incrementeel bouwen etc. Een overzicht en vergelijking van de bekendste language workbenches, zowel industrieel als academisch, is te vinden in referentie 2.

Language workbenches verhogen de productiviteit van DSL-ontwikkeling door veel aspecten van taalimplementatie te automatiseren. Hierdoor komt meer tijd vrij voor het ontwerp van de taal, waar de ware uitdaging ligt: geen DSL is vaak beter dan een slecht ontworpen DSL. Een goed begrip van het domein is essentieel om precies die aspecten in de taal te modelleren die ertoe doen, en om te voorkomen dat onnodige complexiteit wordt toegevoegd. Language workbenches ondersteunen het ontwerpproces met krachtige gereedschappen, waardoor een eerste prototype vaak in een week klaar kan zijn, in plaats van na maanden.   

Zoals zo veel stijlen en technieken voor softwareontwikkeling, zijn DSL's geen panacee. Maar een goed ontworpen DSL voor een goed gedefinieerd domein, gemaakt met de juiste gereedschappen, kan productiviteit en kwaliteit naar een nieuw plan tillen.

Rascal

De Software Analysis & Transformation (SWAT)-onderzoeksgroep aan het CWI ontwikkelt de Rascal-metaprogrammeertaal en language workbench [4]. Rascal is een geïntegreerde programmeertaal voor de ontwikkeling van sourcecodeanalyse- en transformatietools, waaronder DSL-compilers en IDE's. Enkele voorbeelden van DSL's die met Rascal zijn ontwikkeld, zijn Machino (voor routerconfiguratie), MicroMachinations (voor speleconomieën), Rebel (voor financiële producten), Derric (voor digitial forensics) en TwoStones (voor live webprogrammeren). Verder wordt Rascal gebruikt om DSL-engineering aan de Rijksuniversiteit van Groningen te onderwijzen, aan de hand van QL, en aan de UvA, TU/e en OU in vakken over softwareanalyse en evolutie.

De ervaring leert dat tools als Rascal de productiviteit van DSL-ontwikkeling enorm kunnen verhogen. Als zodanig zou je Rascal kunnen zien als een DSL voor het ontwikkelen van DSL's: meer mogelijk maken met minder code, in het domein van DSL's zelf. Om deze ervaring breder in te zetten, is in 2017 de spin-off SWAT.engineering [5] opgericht, die nu voor diverse klanten DSL's ontwerpt.

Referenties

[1] APT programming language https://en.wikipedia.org/wiki/APT_%28programming_language%29

[2] Sebastian Erdweg, Tijs van der Storm, Markus Völter, Laurence Tratt, et al. Evaluating and Comparing Language Workbenches: Existing Results and Benchmarks for the Future

Computer Languages, Systems & Structures, Volume 44, Part A, December 2015, pp 24-47

[3] Martin Fowler, Language Workbenches: The Killer-App for Domain Specific Languages?

https://www.martinfowler.com/articles/languageWorkbench.html

[4] Rascal: the one-stop shop for metaprogramming. https://www.rascal-mpl.org/

[5] SWAT.engineering https://www.swat.engineering/

Magazine AG Connect

Dit artikel is ook gepubliceerd in het magazine van AG Connect (juni-julinummer 2019). Wil je alle artikelen uit dit nummer lezen, klik dan hier voor de inhoudsopgave.

Lees meer over Development OP AG Intelligence
Reactie toevoegen
De inhoud van dit veld is privé en zal niet openbaar worden gemaakt.