DCI: een andere blik

 
04 augustus 2009

Een tijdje geleden heeft André Boonzaaijer een blogpost over DCI geschreven. Zijn conclusie was: “Of DCI (…) de ideale manier is weet ik niet”. Ik was ook niet overtuigd toen ik het artikel van Trygve Reenskaug en James O. Coplien las waar André naar verwees. Trygve Reenskaug, de bedenker van DCI, heeft echter meer hierover geschreven en naar mijn mening zijn zijn ideeën duidelijker gemaakt in het lange artikel “The Common Sense of Object Oriented Programming”. Overtuigd ben ik (nog) niet, maar ik denk wel dat het de moeite waard is om uit te proberen.


Het probleem

Is er iets mis met OO? Volgens Trygve Reenskaug wel! Een OO oplossing bestaat uit een aantal klassen en/of interfaces en bijbehorende methodes. Die geven aan hoe individuele instanties (objecten) zich gedragen. Met andere woorden: de code maakt expliciet het gedrag van individuele instanties. Toch wordt relevante functionaliteit meestal bereikt door de collaboratie van meerdere objecten die eventueel instanties van verschillende klassen zijn. Om te begrijpen hoe bepaalde functionaliteit bereikt wordt moeten we eerst weten waar het “entry point” zich bevindt. Hierna gaan we van methode naar methode en van klasse naar klasse afhankelijk van de inhoud van elke bezochte methode. Als er geen methode meer aangeroepen wordt zijn we klaar en weten we hoe de functionaliteit geïmplementeerd is. Dit proces moet herhaald worden voor elke functionaliteit. In het kort: om te begrijpen wat de code doet moeten we eigenlijk de code simuleren. Is het niet mogelijk om OO code te schrijven die ook expliciet aangeeft wat hij doet?


De DCI oplossing

DCI is een “nieuw” programmeerparadigma dat veronderstelt dat de code drie verschillende perspectieven op een systeem moet aanbieden.

Het dataperspectief bestaat uit alle domeinklassen en bijbehorende relaties. In tegenstelling tot het OO-paradigma mogen deze klassen geen businesslogica implementeren (in de woorden van Martin Fowler wordt dit een “anemic model” genoemd).

Het contextperspectief bestaat (voorlopig) uit één klasse per systeemoperatie. Elke klasse (contextklasse) heeft een methode die het “entry point” voor de betreffende systeemoperatie is. Net zoals bij een conventionele OO-oplossing wordt de systeemoperatie door middel van collaborerende objecten mogelijk gemaakt. De structuur van deze collaboratie wordt met rollen en connecties tussen rollen in de contextklasse vastgelegd (zie figuur 1).

Een rol is eigenlijk een soort van contextafhankelijk domeinklasse. Denk aan een uitleensysteem voor bibliotheken. Bij het uitlenen van een boek hebben we te maken met drie rollen: de lener, de uitlener en het geleende boek. Deze rollen worden vervuld door een persoon, de bibliotheek en één exemplaar van een boek. Het maakt niet uit wie precies het boek leent, welke bibliotheek het is, of welk boek er geleend wordt. De collaboratie kan gedefinieerd worden aan de hand van de aangegeven rollen. Aan de andere kant moet het mogelijk zijn om rolobjecten aan te maken vanaf bestaande domeinobjecten (bijv. een lener object moet aangemaakt kunnen worden vanaf een bestaand persoon object).

Collaboratienetwerk voor het uitlenen van boeken

Figuur 1. Collaboratienetwerk voor het uitlenen van boeken.

De connecties tussen rollen geven aan welke rollen rechtstreeks te bereiken zijn vanaf elke rol. Zo wordt het duidelijk hoe het collaboratienetwerk eruit ziet.

Naast het definiëren van het “entry point” en de structuur van het collaboratienetwerk is de contextklasse ook verantwoordelijk voor het aanmaken van rolinstanties.

Het interactieperspectief is niet meer dan een view op de methodes van de rollen die in het contextperspectief gedefinieerd zijn. Deze methodes leggen de manier waarop rollen met elkaar collaboreren en de desbetreffende businesslogica vast.


Een voorbeeld

Om het DCI paradigma te illustreren maak ik hier gebruik van het voorbeeld dat Serge Beaumont gebruikt heeft tijdens zijn presentatie “DCI: een nieuw programmeerparadigma gebaseerd op rollen” op J-Spring 2009. Het gaat om een uitleensysteem voor een groep bibliotheken. Dit systeem moet het mogelijk maken om boeken te lenen en te retourneren. Laten we eerst een conventionele OO oplossing hiervoor bekijken (kijk naar figuur 2).

OO oplossing van het uitleensysteem voor bibliotheken

Figuur 2. OO oplossing van het uitleensysteem voor bibliotheken.

Wat valt in deze oplossing op? In principe niets. Een persoon houdt bij welke boeken hij bij welke bibliotheken geleend heeft. Een bibliotheek weet welke boeken uitgeleend zijn en boek exemplaren weten door wie ze geleend zijn. In dit geval is het niet moeilijk om te begrijpen hoe het uitlenen en retourneren van een boek in het model opgelost wordt. Toch is dit niet expliciet aangegeven in de code.

Hoe zou een oplossing volgens het DCI paradigma eruitzien? In het dataperspectief hebben we precies dezelfde klassen als in de OO oplossing, alleen de methodes die het uitlenen/retourneren van boeken mogelijk maken worden daaruit gehaald. In het contextperspectief definiëren we een klasse die het uitlenen en retourneren van boeken mogelijk maakt. Deze klasse heeft twee “entry point” methodes, één voor het uitlenen en één voor het retourneren van boeken. Deze klasse definieert ook de structuur van het collaboratienetwerk (zie figuur 3). De geïdentificeerde rollen zijn lener, uitlener en uitgeleend boek. Deze bevatten de methodes die het uitlenen/retourneren van boeken mogelijk maken (zie figuur 4).

Het collaboratienetwerk voor het uitlenen/retourneren van boeken

Figuur 3. Het collaboratienetwerk voor het uitlenen/retourneren van boeken.


De rollen voor het uitlenen/retourneren van boeken

Figuur 4. De rollen voor het uitlenen/retourneren van boeken.

In het interactieperspectief wordt de code van de methodes in de rollen vastgelegd.

Zoals te merken valt verschilt de DCI oplossing bijna niet van de OO oplossing. Toch word het naar mijn idee duidelijker waar de “entry points” voor de systeemoperaties zijn en welke methodes bij de benodige collaboratie betrokken zijn. Daarnaast hoeven we ook niet van methode naar methode te springen om erachter te komen van welke objecten bijbetrokken zijn.

De meerwaarde van DCI zou nog opmerkelijker zijn als er extra functionaliteit toegevoegd wordt. In de conventionele OO oplossing resulteert dit (waarschijnlijk) in extra methodes in de bestaande klassen. De klassen worden groter en het wordt dus moeilijker om te weten welke methodes bij welke functionaliteit horen. In de DCI oplossing worden extra contextklassen en de bijbehorende rollen toegevoegd. De scheiding tussen de verschillende functionaliteiten wordt expliciet aangegeven in de code. Daarnaast is ook het collaboratienetwerk expliciet aangegeven.


Conclusie

DCI staat nog in de kinderschoenen. De voorbeelden die in de verschillende artikelen verschijnen zijn vrij eenvoudig. De algemene aanname is dat een instantie van een contextklasse aangemaakt wordt als de respectievelijke systeemoperatie uitgevoerd moet worden en hierna weer worden weggegooid. Dit is niet het geval in het voorbeeld dat hier gepresenteerd was. Zoals je waarschijnlijk gemerkt hebt moet de toestand van de rollen bewaard worden om te zorgen dat boeken die geleend zijn geretourneerd kunnen worden. De situatie wordt nog ingewikkelder/uitdagender als een probleem als het Mancala spel aangepakt wordt. Hebben we contexten binnen contexten nodig? Toch ben ik van mening dat DCI de moeite waard is om verder te onderzoeken. Even een paar ingewikkelde domeinen met DCI aanpakken. Wie durft? :)



Werken met ?
Kijk dan bij onze mogelijkheden voor zowel starters als ervaren engineers.


Categorieën: Development

Tags: ,


Reacties (5)

  • Hierop terugkomend: de laatste tijd ben ik zelf ook weer meer een onderscheid gaan zien tussen wat een object is en wat hij doet. Het gebruik van rollen om het ‘doen’ gedeelte te benoemen voelt wel natuurlijk aan.

    Wat voor veel verwarring heeft gezorgd, denk ik, is dat een deel van de methodes op een klassiek object te maken hebben met de structuur, zij zijn er namelijk alleen maar om een gebrek te ondervangen in de mogelijkheden om het eigenlijk bedoelde model goed te beschrijven. Dit zijn bijvoorbeeld methodes die dubbelzijdigheid van referenties checken of de volgorde van een lijst van referenties regelen.

    Deze bovenstaande methodes moet je denk ik niet mengen met de methodes die te maken hebben met echt gedrag, wat alleen optreedt in interactie met andere objecten of de omgeving (b.v. tijd). De methodes op een object die alleen bedoeld zijn om de innerlijke structuur te bewaken zijn namelijk meer technisch van aard, je zou ze eigenlijk niet eens willen schrijven.

    Geplaatst op 23 april 2011 om 13:02 Permalink

  • @Arno:

    Helemaal gelijk. Die oplossing heeft Serge Beaumont ook als zijn “ultieme oplossing” gepresenteerd. Ik heb deze buiten beschouwing gelaten om te laten zien dat DCI toegepast kan worden zonder dat er verdere abstracties nodig voor zijn.

    @Rick:

    Ik ben niet helemaal mee eens dat “DCI een oplossing is voor een probleem dat niet had moeten bestaan”. Ik denk dat je dit kan vergelijken met het gebruik van de GOTO instructie. In principe is er niks mis met de GOTO instructie als iedereen deze op een gestructureerde manier gebruikt. Dat is helaas niet altijd het geval geweest en daarom heeft Dijkstra zelfs een artikel daarover geschreven.
    Er is niks mis met OO als het goed toegepast wordt. Maar wat is goed toepassen? DCI is het antwoord van Trygve Reenskaug hierop. Ik deel zijn mening dat met het gebruik van DCI het gedrag van een programma explicieter gemaakt wordt. Daardoor wordt het makkelijker om dit aan te passen.

    Geplaatst op 24 augustus 2009 om 16:58 Permalink

    • Hoi Pedro, als ik zeg “DCI een oplossing is voor een probleem dat niet had moeten bestaan”, dan zeg ik niet dat DCI nutteloos danwel een verkeerde oplossing is. Ik beklaag me meer over de gebrekkige vormen van modelleren die (inderdaad) veel in software te vinden zijn. En dat het daarop zeker een nuttige uitbreiding is.

      Wat ik wel vind, is dat als je alle relevante concepten goed modelleert, je zult zien dat je DCI niet als aparte methodiek/modelleerstijl nodig hebt. Maar goed, aangezien dat zeker niet altijd gebeurt, is er voldoende bestaansreden voor DCI. Om het nou een heel nieuw programmeerparadigma te noemen vind ik echter wel vrij ver gaan.

      De vergelijking met het beroemde “GOTO statement considered harmful” gaat volgens mij een beetje mank op het feit dat Dijkstra pleitte voor een complete afschaffing van het gebruik van GOTO (inderdaad vanwege de schadelijke gevolgen bij slecht gebruik). DCI is mijns inziens meer een bepaalde focus of stijl die je kunt hebben binnen OO modelleren, zeker geen vervanging, opvolger of iets compleet nieuws.

      Maar misschien vergis ik me daarin. Wellicht een leuk onderwerp om eens een keer dieper op in te gaan binnen een avondsessie?

      Geplaatst op 24 augustus 2009 om 20:25 Permalink

  • Het lijkt er een beetje op dat DCI een oplossing is voor een probleem dat niet had moeten bestaan. Ja, als je OO objecten alleen ziet als één-op-één representaties van ‘echte’ objecten, dan is het misschien een toevoeging als je rollen ook als een object ziet. Maar volgens mij is het nooit de bedoeling geweest om alleen ‘echte’ objecten als objecten in OO ontwerpen te vatten. Net als dat alleen de zelfstandig naamwoorden pakken uit een zin ook net even te kort door de bocht is. Het gaat er volgens mij (en niet alleen mij) om, om voor de applicatie relevante concepten te vatten in je model. In het geval van een bibliotheek zal dat zeker ook een ‘lening’ moeten bevatten. Dat kan bijna niet alleen maar een state van een boek zijn, alleen in een hele grove simplificatie.

    Overigens denk ik dat juist de methode om alleen fysieke objecten te modelleren in OO leidt tot van die bloedeloze (anemic) domeinmodellen die gewoon 1-op-1 kopieën zijn van een database schema. Misschien had het beter Concept Orientation kunnen heten. Sowieso heeft Alan Kay al gezegd dat hij bij nader inzien de focus op messaging i.p.v. objecten zou willen leggen, niet? (zie http://en.wikiquote.org/wiki/Alan_Kay).

    Geplaatst op 17 augustus 2009 om 12:52 Permalink

  • Arno schreef:

    Volgens mij moet je hem in de ‘DCI’ versie nog wat verder dootrekken en het niet over een BorrowedBook hebben maar eerder over een BorrowdItem.
    Op die manier kun je de het hele begrip lenen (met de rollen ‘lener’, ‘uitlenener’ en ‘geleende item’ en de interactie daartussen) los definieren en daar later de participanten aan toekennen.

    Bij een bieb: Bibliotheek, boek, lid.
    Bij een videotheek: Videotheek, videoband, lid
    Bij de Sogyo interne bibliotheek: Sogyo, Boek en Medewerker

    Geplaatst op 04 augustus 2009 om 22:08 Permalink