Command Query Separation

Gisteren heb ik een klant geholpen bij het opzetten van een nieuwe (voorbeeld) architectuur.
De basisgedacht in de architectuur is dat alle acties in de applicatie traceerbaar moeten zijn. Hierbij moest ik meteen denken aan een sessie met Greg Young bij Devnology.
Hierin legde hij uit wat Command Query Seperation (CGS) in de context van DDD is en wat je ermee kunt.

Wat we gedaan hebben is een apart domeinmodel opgezet voor het doorvoeren van wijzigingen, het command gedeelte. Sleutelwoorden hierbij waren: traceerbaarheid, uitbreidbaar, schaalbaar, onderhoudbaar en loosely coupled.

Hoe hebben we dit opgezet? Ons command domein bestaat feitelijk uit drie spelers, businessevents, businessactions en een eventqueue.

Businessactions zijn classes welke een implementatie bevatten voor het verwerken van een bepaald type businessevent. Ze worden geregistreerd bij de eventqueue, zodat deze weet welke acties afgevuurd moeten worden als een businessevent in de queue wordt gestopt. Het zogenaamde publish-subscribe mechanisme.

Businessevents zijn dataobjecten met een specifieke naam, zoals ChangeCustomerAddress. Hierin zijn dan properties aanwezig als CustomerNumber, Street, Number en City.

Een dergelijk object wordt aan de queue toegevoegd vanuit een Opslaan operatie in een MVC controller bijvoorbeeld of wordt toegevoegd door de implementatie van een Address webservice.

De queue verwerkt alle inkomende businessevents 1-voor-1 en vuurt alle geregistreerde acties af voor een bepaald eventtype.

Het grote voordeel van dit mechanisme is dat er geen directe koppeling tussen het event en de bijbehorende actie bestaat. Het businessevent kan als eerste worden gedefinieerd en gebruikt vanuit bijvoorbeeld de userinterface, lang voordat de daadwerkelijk implementatie is gebouwd in één of meerdere businessactions.

Ook is het mogelijk om later nog een businessaction toe te voegen voor een bepaald businessevent. De architectuur is hiermee daadwerkelijk modulair opgebouwd, eenvoudig te testen en goed onderhoudbaar.

Door een zogenaamde CatchAll-businessaction te bouwen die voor alle types businessevents wordt afgevuurd kunnen de businessevents worden opgeslagen, waardoor ook de traceerbaarheid is gegarandeerd.

Daarnaast is een domeinmodel beschikbaar voor het weergeven van de informatie in het pakket, deze is veel simpeler en bevat geen klassieke CRUD operaties. Alle wijzigingen moeten immers doorgevoerd worden in het commandgedeelte. De achterliggende data in het query domein wordt geupdate door een Anti Corruption Layer, wat ervoor zorgt dat de wijzigingen uit de commands op de juiste wijze worden doorgevoerd op het datamodel.

Oh ja, de specifieke referentie implementatie bij deze klant is in Delphi 2010.

Ronald Harmsen

I'm a software developer. When I'm not developing software I'm training & coaching other developers, speaking on a conference or fiddling with some technical stuff.

Arnhem, The Netherlands

Subscribe to Ronald to the cloud

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!