Entity services en het contextprincipe

Een domein bestaat uit een aantal entiteiten. Voor een webwinkel zijn dat dingen als product, winkelwagentje en bestelling. Zulke entiteiten verwachten we, als we aan Domain-Driven Design (DDD) doen, terug te vinden in onze code: Product, ShoppingCart en Order. Tot dusver niets controversieels.

In veel codebases vinden we, naast deze entiteiten, corresponderende objecten: services. De logica rondom een product wordt afgehandeld in de ProductService, die van een winkelwagentje in een ShoppingCartService – en waar je de logica voor een bestelling kunt vinden, kun je vast wel raden.

Antipatroon

Het gedachteloos introduceren van dit soort entity services is me een doorn in het oog. Vaak bestaat zo’n service voor een groot deel uit boiler plate code, getuige de vele pass through-methods, waar John Ousterhout terecht op afgeeft in A Philosophy of Software Design. Zulke methods doen weinig meer dan objecten uit de database rechtstreeks doorspelen naar de bovenliggende laag. Dat is al erg genoeg.

Maar de situatie verbetert nauwelijks wanneer businesslogica zijn weg vindt naar zulke services. Ze zijn een vergaarbak voor verschillende operaties, een excuusbrief voor ontwikkelaars om niet na te hoeven denken over zinvolle abstracties.

De situatie wordt zo mogelijk nog erger wanneer de services gedachteloos in een microservicesarchitectuur worden gepropt. Elke entity service kan dan – in theorie – apart worden gedeployd. Maar omdat de vele services gebruik van elkaar (moeten) maken, kan alleen een verzameling services zinvolle functionaliteit ontsluiten. Het gevolg is dat elke service alsnog in combinatie met andere moet worden getest. Het resultaat is een gedistribueerde monoliet.

Entity services zijn een antipatroon, dat is een empirische vaststelling. Maar waarom introduceren ontwikkelaars dan keer op keer deze pseudo-abstractie? Waar komt dan de aantrekkingskracht van dit idee vandaan?

Betekenis

Ik geloof – maar dat is, vergeef me, natuurlijk omdat ik filosofie heb gestudeerd – dat de bron van dit idee best wel fundamenteel is, namelijk de veronderstelling dat een woord op zichzelf een betekenis heeft. Wat, op zich, zou je denken, een heel redelijke veronderstelling is. Ga maar na: als je een woordenboek openslaat, wat vind je daar dan? Een lijst, jawel, woorden, op alfabetische volgorde nog wel, met daarachter hun betekenis. Dus als we het woordenboek mogen geloven, heeft een woord op zichzelf een betekenis.

Dat beeld van betekenis impliceert dat de betekenis van een zin wordt opgebouwd uit de betekenis van woorden. Woorden zijn de atomen, als het ware, die samen een betekenismolecuul vormen, dat is dan de zin. Maar bekijk de volgende zin eens:

Ik heb het geld op de bank gezet.

‘Ik,’ dat ben ik; ‘het geld’, dat is een bepaalde hoeveelheid van een algemeen geaccepteerd ruilmiddel; ‘[ergens] op gezet’ is wat ik met dat geld gedaan heb, ik heb het in zekere zin verplaatst. Maar wat is ‘de bank’? Het kan de instantie zijn die mijn rekening beheert, dat is de meest voor de hand liggende interpretatie. Maar het kan ook betekenen: de zitmeubel. Hoe beslis ik of ik het geld naar de instantie heb gebracht die mijn rekening beheert, of dat ik het thuis op mijn zitmeubel heb gelegd?1

Op basis van de woorden alleen kan ik die beslissing niet maken. Het woord op zichzelf is niet voldoende om de betekenis te bepalen. Dus er is iets anders wat de betekenis van ‘de bank’ vastlegt. Maar wat?

Taalfilosoof Gottlob Frege meende: het is de zin. Hij zei: een woord heeft alleen betekenis in de context van een zin. Dat is zijn contextprincipe. Dit idee vinden we ook terug in Wittgensteins Tractatus Logico-Philosophicus (in propositie 3.3, bijvoorbeeld).2 Later radicaliseerde Wittgenstein het contextprincipe in de notie van taalspelen. Daarin stelt hij dat de zin alleen niet voldoende is om betekenis te bepalen, maar dat socio-culturele context van de taaluiting mee moet worden genomen in de betekenisbepaling.

Bounded context

Mijn stelling is: entity services veronderstellen dat woorden atomaire betekenisdragers zijn. Daarom denkt een programmeur van zo’n service dat het zin heeft om over een product of winkelwagentje of bestelling an sich te praten. En waar vindt dat gesprek plaats? In hun respectievelijke services.

Maar de betekenis van die woorden is niet eenduidig. Afhankelijk van de context, verkrijgen bepaalde eigenschappen van een product relevantie en worden andere juist betekenisloos. Een afbeelding van het product is relevant voor de (potentiële) koper ervan, maar niet voor de instantie die het op de post doet. Andersom kan die instantie zeer geïnteresseerd zijn in het gewicht van het product, maar dat zal de koper een worst wezen (in elk geval voor sommige producten). In een centrale ProductService worden beide stakeholders bediend – dat is hoe zo’n service een vergaarbak van functionaliteit wordt.

Of er een directe lijn kan worden getrokken van Frege naar Eric Evans, durf ik niet te zeggen. Maar het is vanuit filosofisch oogpunt niet vreemd dat hij in Domain-Driven Design van bounded contexts spreekt. Evans heeft het contextprincipe gepopulariseerd in de wereld van softwareontwikkeling, zou je kunnen zeggen – maar aan het aantal entity services te beoordelen, hebben we nog een lange weg te gaan.


  1. Natuurlijk, dit voorbeeld maakt gebruik van een toevallige eigenschap van de taal, namelijk dat ‘bank’ een homoniem is. Die eigenschap maakt ambiguïteit in de taal expliciet. Maar het punt van het contextprincipe blijft staan, ook buiten deze toevalligheid om. De Philosophical Investigations van Ludwig Wittgenstein werkt dit punt uit met de metafoor van familiegelijkenis↩︎

  2. Eén van de eerste filosofen die het belang van Freges contextprincipe onderkende voor het werk van Wittgenstein, was Gilbert Ryle in zijn recensie van de eerste Engelse vertaling van Freges verzameld werk. De recensie is integraal afgedrukte in essaybundel Early Analytic Philosophy: Origins and Transformations, die ik recenseerde voor Boekenkrant↩︎

domain-driven design · filosofie · microservices · wittgenstein, ludwig