Modelleerpatronen (2): Push vs Pull (CQS)

Titel: Push vs Pull met Command-Query Separation (CQS)

Doel: Acties binnen je model push-gedreven uitvoeren tijdens schrijfacties zodat leesacties veel minder diepe objectbomen raken. Dit scheelt resources en komt de performance en schaalbaarheid van het systeem ten goede. Met name een goede optimalisatie als gebruik wordt gemaakt van O/R bridges.

Motivatie: Command-Query separation is geïntroduceerd door Bertrand Meyer in de jaren ’80 toen hij de taal Eiffel ontwierp. Het idee hierachter is dat leesacties de state van een systeem niet mogen veranderen; slechts schrijfacties mogen ervoor zorgen dat de state van een systeem muteert. Dat is ook logisch en klinkt als een definitiekwestie, echter de recente ontwikkeling dat we met name de persistentie (en dus statebeheer) binnen onze applicaties overlaten aan O/R bridges zoals (N)Hibernate maakt dit principe weer interessant.

Als we op een klassieke objectgeoriënteerde manier nadenken over systemen dan maken we de verantwoordelijkheden binnen classes zo klein mogelijk en zien we al snel dat we veel associaties leggen zodat mogelijk grote netwerken van objecten onder een aggregaat komen te hangen. Denk aan een klant die orders heeft en die orders hebben elk weer een referentie naar artikelen die op hun beurt weer andere geassocieerde objecten hebben. Als we dan alles netjes laten uitrekenen door deze aggregaten kunnen we voor een simpele vraag aan een dergelijk systeem zoals het aantal orders of artikelen dat een klant ooit besteld heeft goed duizenden objecten langsmoeten (er treden combinatorische effecten op met #orders * #orderregels op zodat bij een tiental orders mogelijk al honderden objecten geladen worden).

Het gegeven voorbeeld kunnen we omdraaien door binnen de klant-class een field op te nemen die het aantal bestelde artikelen of orders bijhoudt en dat field wordt bijgewerkt op moment dat er een order geplaatst wordt – en dus niet uitgerekend op moment dat het opgevraagd wordt. Aangezien vrijwel alle systemen vaak een veelvoud aan leesacties moeten afhandelen ten opzichte van de schrijfacties is dit bijna altijd per definitie een optimaler scenario (op loggers na uiteraard). Het concept heeft veel weg van caching.

Toepasbaarheid: Potentieel grote uitwaaierende objectbomen kunnen vaak op deze manier andersom gemodelleerd worden zodat er grote winsten behaald kunnen worden. Denk aan hierarchische modellen als ordersystemen.

Voorbeeld Een voorbeeld van dit patroon is te vinden in een eerder gepubliceerd artikel van mijn hand dat hierop ingaat getiteld “schaalbare modellen” te downloaden bij SDN.