DCI Architecture

Via het blog van collega Rob Vens kwam ik een weekje terug een artikel tegen van Jim Coplien en Trygve Reenskaug over een nieuwe manier van OO denken. DCI staat hierbij voor Data, Context en Interaction. De moeite waard om helemaal door te nemen, en als aanvulling is er tevens een interessante forumdiscussie na te lezen. Ik zal pogen kort samen te vatten waar het in de kern om gaat.

Volgens de auteurs is OO volgens de ‘klassieke’ manier zoals in de jaren ’80 van de vorige eeuw uitgewerkt relatief slecht in het vertalen van mentale modellen van gebruikers van een systeem naar code. Een eindgebruiker zal een use-case altijd uitleggen als een sequence van stappen die hij onderneemt – in feite een algoritmische view op de use case. Als we dit vertalen naar een OO model gaan we deze stappen ‘verdelen’ over een aantal classes waardoor een netwerk van kleine methoden ontstaan die door de code verspreid worden.

Dit heeft nadelen voor wat betreft onderhoudbaarheid van de code. Het klassieke idee dat we alleen lokaal hoeven na te denken over verantwoordelijkheden en dat het model het als geheel wel op gaat lossen via een soort ‘emergent behaviour’ wordt door de auteurs min of meer afgeschoten. In plaats daarvan moeten we een plek zoeken in onze code die dit soort eindgebruikersalgoritmen op een centrale plaats vasthoudt, los van alle verschillende classes die erbij betrokken zijn.

DCI stelt dat er een nieuw concept nodig is voor de plaatsing van dit soort algoritmen: rollen. Rollen zijn gedragingen die objecten in verschillende contexten toebedeeld kunnen krijgen. Er wordt een voorbeeld aangedragen in het bronartikel van bankrekeningen die verschillende rollen op zich kunnen nemen in een overschijving: source en destinationaccount. Al naargelang de context die geschapen wordt kan een account een verschillende rol vervullen. De basis class van deze bankrekeningen is een ‘domme’ class die alleen data en simpele operaties als verhogen/verlagen van het saldo bevat. De echte businesslogica wordt in rollen uitgewerkt zodat de algoritmen voor bijvoorbeeld overschijvingen als geheel terug te vinden zijn in de code. Deze rollen worden dan runtime contextafhankelijk aan de objecten toegewezen via programmeerconstructies als mixins of traits (ik ga daar nu niet op in). De problematiek om verantwoordelijkheden en gedrag te distribueren over een model heb ik zelf al eens wat over op papier gezet.

Dit artikel heeft mij aan het denken gezet. Vaak is het zo dat het erg lastig is om verantwoordelijkheden goed te leggen in domeinmodellen. Gesteld dat we een overboeking willen modelleren, welke account is dan verantwoordelijk voor deze actie – source of destination? De state van beide accounts wordt gemanipuleerd dus in feite wringt er iets in deze versimpelde collaboratie. Als ik puur vanuit een modelleerperspectief kijk dan zou ik ook zeggen dat er een transactie object in het model nodig zou zijn. Hier stappen de auteurs overheen; de transactie is alleen aanwezig in het algortime en wordt verder niet als gevolg van deze actie opgeslagen (ik kan een transactieoverzicht op mijn rekening toch wel waarderen). Daarnaast ben ik er niet zeker van dat rollen het gestelde probleem op gaan lossen. We verplaatsen immers alleen de logica, om het echte probleem op te lossen moeten we juist meer procedureel gaan denken. Als ik verschillende kleine rollen definieer en hierover de algoritmen verdeel heb ik nog steeds het probleem dat mijn use-cases verweven zijn door de code, alleen nu door rollen i.p.v. classes.

De conclusie die ik eruit trek is dat te stricte toepassing van OO denken leidt tot distributie van algoritmen over verschillende classes. Dit heeft als nadeel dat de code minder transparant is en slecht mapt op mentale modellen van eindgebruikers. Om deze modellen beter terug te laten komen in de code zullen we op een meer procedurele manier moeten programmeren. Of DCI hiervoor nu de ideale manier is weet ik niet, Evans/Fowler etcetera praten ook binnen Domain Driven Design over een ‘application layer’ die deze mapping faciliteert. Ikzelf ben technisch gesproken ook een voorstander van het werken met een 4-laags model, waarin er een (service)laag is opgenomen die ‘bovenop’ het domeinmodel draait die helder aangeeft welke use cases (of contracts, of services) het onderliggende model aanbiedt. Zo kunnen we in deze tussenlaag exact aangeven waar de entry-points voor de use cases in het model liggen.