Extra investering verdient zich bij complexere systemen snel terug
Edwin van Dillen en Wilco Verdoold | Verschenen in Automatisering Gids nr. 38, 2008
Edwin van Dillen en Wilco Verdoold zijn respectievelijk CTO en directeur bij Sogyo
en zijn te bereiken via evdillen@sogyo.nl en wverdoold@sogyo.nl.
Domain-Driven Design (DDD), Domain-Oriented Architecture (DOA), domeingeoriënteerde applicatiearchitectuur zijn verschillende namen voor een stijl van applicatieontwikkeling waarin het (business)domein centraal gesteld wordt en daarmee de complexiteit beheersbaar wordt. Maar wat maakt deze stijl zo bijzonder? Wanneer kies je voor een domeingeoriënteerde applicatiearchitectuur? Welke voor- en nadelen zijn er in de praktijk? Heeft de domeingeoriënteerde applicatiearchitectuur toekomst? Edwin van Dillen en Wilco Verdoold geven antwoord op bovenstaande vragen.
Het centrale uitgangspunt van een domeingeoriënteerde benadering is de representatie van het businessdomein in een class-diagram, ook wel domeinmodel genoemd. Door dit domeinmodel te implementeren, wordt het hart van het systeem gerealiseerd. Neem bijvoorbeeld het domein van een verzekeraar. Het domeinmodel bestaat uit objecten die een polis of relatie representeren. Een polis heeft de eigenschappen dat hij aangemaakt kan worden, zichzelf aan een relatie kan toewijzen en zichzelf uit kan keren. Kortom: eigenschappen die de primaire business van de verzekeraar representeren.
De objecten die onderdeel uitmaken van het domeinmodel hebben alleen het gedrag dat de business van ze verwacht. Vanuit het businessmodel gezien, hebben de objecten niet de verantwoordelijkheid om zichzelf op te slaan in een vast medium (bijvoorbeeld een database) of zichzelf te representeren naar de gebruiker. Dit zijn verantwoordelijkheden die buiten het domein vallen en moeten worden ingevuld door de omgeving waarin het domeinmodel geïmplementeerd wordt. Deze omgeving moet daarom beschikken over faciliterende services die het domeinmodel kunnen voorzien in opslag- en presentatiemogelijkheden. Deze services hebben een technisch karakter en zijn afhankelijk van het platform waarop ze geïmplementeerd worden. Denk hierbij aan services voor .NET of J2EE.
Het domeinmodel wordt omringd door verschillende faciliterende services. De presentatieservice bijvoorbeeld bevat de implementatie om de domeinobjecten op een specifiek medium weer te geven. Wanneer een gebruiker bijvoorbeeld met het domeinmodel wil interacteren via het web, dan zorgt de presentatieservice ervoor dat alle informatie die de gebruiker van het domeinmodel wil hebben, naar het web wordt ontsloten.
Daarnaast heeft de presentatieservice de verantwoordelijkheid om het domeinmodel te ontsluiten naar verschillende andere kanalen, zoals een Windows-desktop of een mobiel apparaat. Door de strikte scheiding van verantwoordelijkheden hoeft het domeinmodel dus zelf niet aangepast te worden. Om weer het voorbeeld van de verzekeringsmaatschappij te nemen: Voor het beschikbaar maken op het web van het domeinmodel polis dat al via een presentatieservice geïmplementeerd is op een Microsoft Windows-platform, hoeft alleen de presentatieservice uitgebreid te worden.
Naast de presentatieservice omringen vele andere faciliterende services het domeinmodel. Deze services hebben samen de verantwoordelijkheid om het bestaan van het domeinmodel te faciliteren. Zo is de rol van de persistentieservice het persisteren van het domeinmodel in bijvoorbeeld een relationele database. Tevens zorgt de service ervoor dat objecten gecreëerd kunnen worden: De persistentieservice haalt de data uit de database en creëert het object in geheugen met de juiste toestand. Het domeinobject is zichzelf daardoor niet bewust van het feit dat deze opgeslagen moet worden in een database. De persistentieservice regelt dit immers voor het object. Bovenstaande expliciete scheiding van verantwoordelijkheden van objecten wordt ook wel het ‘Expert pattern’ genoemd. Objecten doen die dingen waar ze goed in zijn.

Afb. 1 Domein is gescheiden van faciliterende services. Faciliterende services hebben samen de verantwoordelijkheid om het bestaan van het domeinmodel te faciliteren.
- – - – - – - – - – - – - – -
Door het domeinmodel centraal te stellen, wordt het ontwikkelproces overzichtelijker. Bij een domeingeoriënteerde benadering start een project met het verkennen van het domein. Samen met de businesseigenaren worden de objecten uit het domein in kaart gebracht. Gedrag wordt aan de objecten toegewezen zodat ze de verantwoordelijkheden vervullen die nodig zijn om de business te ondersteunen. Eventueel kunnen schermprototypes gemaakt worden om de communicatie met de businesseigenaren te ondersteunen.
Door deze aanpak komen de businessregels in een vroegtijdig stadium van het project naar voren. Het is zelfs mogelijk om de domeinobjecten op dat moment al te implementeren. In moderne talen als Java en C# is het mogelijk om het geïmplementeerde model dan ook te instantiëren, wat betekent dat de objecten daadwerkelijk gecreëerd worden en dus ook hun verantwoordelijkheden kunnen invullen. Middels unittests kunnen we vervolgens controleren of de geïnstantieerde objecten daadwerkelijk het gedrag vertonen dat van ze verwacht wordt. Het domeinmodel kan dan al in zijn geheel getest worden. In het voorbeeld van de verzekeraar betekent dit dat de polis en verzekeringnemer geïnstantieerd kunnen worden. De polis kan gevraagd worden zichzelf te prolongeren.
Parallel aan de domeinmodellering kunnen de ontwikkelaars starten met het verkennen van de benodigde faciliterende services: presentatie-, persistentie-, communicatieservices, etc. Tijdens de verkenning hiervan worden de belangrijkste technische knelpunten en uitdagingen onderkend. Door proefopstellingen te maken, wordt duidelijk hoe de daadwerkelijke implementatie zal functioneren. Denk hierbij aan een proefopstelling om vast te stellen hoe de persistentieservice objecten gaat persisteren.
Op het moment dat een domeinmodel vaste vorm krijgt, kunnen de services om het model worden geplaatst. Concreet betekent dit dat de presentatieservices de domeinobjecten kunnen ontsluiten naar bijvoorbeeld het web. In de meeste gevallen is het zelfs mogelijk een systeem te ontwikkelen door eerst het domein te ontsluiten met een presentatieservices. Er kan dan al een gebruikerstest plaatsvinden zonder dat de domeinobjecten daadwerkelijk in een database worden gepersisteerd. Voor de gebruiker zal het systeem het verwachte gedrag vertonen. Een gebruiker hoeft per slot van rekening niet te weten dat zijn gegevens in een database worden opgeslagen. In een later stadium kunnen we vervolgens de persistentieservice onder het domein plaatsen. Deze service slaat de toestand van de objecten netjes op in de database.
Ondanks deze voordelen is de domeingeoriënteerde applicatiearchitectuur niet in alle gevallen de aangewezen oplossing. Deze aanpak bewijst zijn waarde vooral in systemen voor bijvoorbeeld hypotheekberekening of het opstellen van planningen, waarin de (business)regels een grotere rol spelen dan de data. Afhankelijk van de beoogde toepassing zal men zeker ook andere oplossingen in overweging moeten nemen. In de literatuur worden meerdere ontwikkelstijlen voor het realiseren van applicaties onderkend. Martin Fowler onderscheidt er naast de domeingedreven aanpak nog twee:
• transactiescript
• tabelgedreven.
Van deze is de transactiescriptbenadering de oudste. In deze stijl wordt per functie code geschreven die het gebruikersproces ondersteunt. Komt er een nieuw proces bij, dan wordt nieuwe code SEnD in de vorm van een script SEnD geschreven. Dit is een typische ontwikkelstijl voor systemen met een beperkte omvang en een beperkt aantal te ondersteunen functies. Denk hierbij bijvoorbeeld aan een eenvoudige webwinkel. Het plaatsen van een product in de winkelwagen en het afrekenen ervan leveren hierbij losstaande scripts op.

Afb.2 Benadering bepalend voor veranderinspanning. De transactiescriptbenadering en de tabelgedreven aanpak lenen zich vooral voor toepassing in niet al te complexe domeinen. Boven een bepaalde grens neemt de inspanning die het kost om veranderingen aan te brengen in een volgens deze benaderingen ontwikkeld systeem, namelijk sterk toe. De domeingedreven aanpak kent wat veranderinspanning betreft een wat hogere instap, maar ook een gelijkmatigere toename van de vereiste inspanning bij toenemende complexiteit. Overigens is bij de huidige stand van kennis niet exact aan te geven waar de kruispunten in het model zich exact bevinden, maar desalniettemin heeft het model wel waarde bij het nadenken over de beschikbare ontwikkelstijlen en het onderbouwen van de keuze voor een bepaalde stijl.
- – - – - – - – - – - – -
De tabelgedreven benadering stelt datatabellen centraal. Rondom deze tabellen (entiteiten) wordt allerlei functionaliteit ontwikkeld. Dit is een ideale benadering voor systemen waarin veel CRUD (Create, Read, Update en Delete)-activiteiten ondersteund moeten worden. Dit zijn vooral administratieve systemen, waarbij het verwerken van formulieren centraal staat. Denk aan toepassingen als een urenregistratie of klachtenadministratie. Naarmate de businesslogica toeneemt, zien we in de praktijk dat de relaties tussen de verschillende entiteiten groter wordt. Hiermee ontstaan grote afhankelijkheden, wat het onderhoud bemoeilijkt.
Een ontwikkelorganisatie moet de competenties ontwikkelen om met alle drie de vormen om te gaan, zodat afhankelijk van het te bouwen systeem de beste stijl gekozen kan worden. Ervaring met de verschillende stijlen maakt het mogelijk om in te schatten welke stijl het beste past bij een bepaald systeem. Een veel gemaakte fout daarbij is dat de gewenste of verwachte levensduur niet in de afweging meegenomen wordt. Veel systemen hebben bijvoorbeeld CRUD-eigenschappen in zich. De complexiteit lijkt dan in eerste instantie gering en dat is dan reden om voor de tabelgedreven benadering te kiezen.
Dergelijke systemen kunnen in hun levenscyclus al snel meer functionaliteit gaan bevatten. Daardoor ontstaat een mismatch in de gehanteerde ontwikkelstijl, waardoor het steeds meer tijd gaat kosten om functionaliteit toe te voegen en het oplossen van fouten resulteert in de introductie van nieuwe fouten. Bij relatief eenvoudige systemen waar een langere levensduur te verwachten is, is een domeinbenadering daarom vaak een veiligere keus.
Voordelen van domeingeoriënteerde benadering
- Complexe businessregels worden overzichtelijk
Het domeinmodel bevat alle businessregels. Aangezien het domeinmodel geïsoleerd kan worden, is het relatief eenvoudig dit model te lezen. Daarmee kunnen ook zeer complexe businessregels eenvoudig inzichtelijk worden gemaakt. - Het domein kan geünittest worden
Het domein is onafhankelijk van de services en kan daarmee geünittest worden. Dit levert op dat het verwachte gedrag van het domeinmodel vroegtijdig getest kan worden. Tijdens de acceptatietest zullen daardoor ook minder fouten naar voren komen. - Focus op businesslogica
Een ontwikkelaar kan zich in eerste instantie concentreren op de businesslogica. Los daarvan kan nagedacht worden over de puur technische zaken. Door de strikte scheiding tussen het domein en de services eromheen is het ook eenvoudiger om inzicht te krijgen in de code die gemaakt is. Dit betekent dat het aanbrengen van wijzigingen gestructureerder kan verlopen. Aanpassingen in de businesslogica hebben niet direct invloed op de services. Alleen wanneer het domeinmodel uitgebreid wordt, zullen eventueel services aangepast moeten worden.
Aandachtspunten bij domeingeoriënteerde benadering
- Vergt meer inspanning tijdens opstartproject
Omdat het domein onafhankelijk van de services moet kunnen bestaan, stelt dit de nodige eisen aan de services. In de beginfase van een project zullen de services vastgesteld moeten worden. Deze kunnen in een ontwikkelorganisatie over projecten hergebruikt worden. De ontwikkelaars zullen echter wel eerst bekend moeten worden met de services. - Aanbrengen scheiding tussen services en domein vereist ervaren ontwikkelaars/applicatiearchitecten
Het domein moet volledig onafhankelijk van de services kunnen functioneren. Om de services herbruikbaar te maken, zijn adaptoren nodig die de services met het domein verbinden. Deze adaptoren kunnen op verschillende manieren geïmplementeerd worden. Om dit goed te doen, zijn goede ontwikkelaars/applicatiearchitecten nodig, liefst met ervaring met domeingeoriënteerd ontwikkelen. - Bekendheid met objectoriëntatie is een must
Het domeinmodel wordt geïmplementeerd door een objectmodel te maken. In de praktijk blijkt dat nog veel mensen moeite hebben om echt in objecten te denken. Gevolg hiervan is dat het domeinmodel een verzameling functies wordt. Kennis en ervaring rondom objectmodellering zijn dan ook een vereiste voor domeingeoriënteerd ontwikkelen.

