Modelleerpatronen (2): Push vs Pull (CQS)

 
21 maart 2011

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.


Werken met ?
Kijk dan bij onze mogelijkheden voor starters en/of ervaren IT'ers.


Categorieën: Development

Tags: , , , , , , ,


Reacties (3)

  • Wat denk ik belanglijk is om erbij te vermelden, is dat je voor de’schrijf’ acties binnen de applicatie soms/vaak meer detail nodig hebt (wel die individuele orders, b.v.) dan voor de lees acties. En dat dat dus prima kan. Niet alles hoeft in één datamodel gepropt te worden. Afgeleide modellen automatisch updaten is ook prima.

    Geplaatst op 26 maart 2011 om 22:41 Permalink

  • Andries Nieuwenhuize schreef:

    Ha Sjors,

    optimalisatie uitstellen is idd. een wijs besluit maar laten we niet het kind met het badwater weggooien. Er zijn verschillende soorten van optimalisatie. Ik zou ze opdelen in die gene die buiten de huidige architectuur treden en diegene die er mooi binnen vallen. (Meta)-gegevens over een aggregaat kun je mooi delegeren aan de agg. zelf. Het is zíjn verantwoordelijkheid om te vertellen hoeveel entities hij bevat. En of die agg. dat nu op aanvraag pas gaat berekenen of dit cached en bij iedere mutatie bijhoudt is zijn zaak.

    Geplaatst op 21 maart 2011 om 13:05 Permalink

  • Dit principe toepassen vanaf het begin van het bouwen van een applicatie klinkt in mijn oren als iets wat thuishoort binnen “early optimalisation is the root of all evil”. Ik zie deze oplossing als een manier om je performanceproblemen achteraf op te lossen, en valt idd voor mijn gevoel in hetzelfde straatje als caching (een keer in de x tijd de veelgevraagde requests pre-renderen). Want periodiek herberekenen blijft in mijn ogen noodzaak omdat ik een “domme” counter toch nog altijd minder vertrouw dan een berekende status.

    Geplaatst op 21 maart 2011 om 8:46 Permalink