IoC versus Observable revisited

 
02 augustus 2009

Deze week kwam er weer een oude vertrouwde discussie langs: IoC versus Observable. Mijn collega Ralf Wolter heeft hier een tijd terug al eens een inspirerende blogpost over geschreven: Liever geen Inversion of Control.

Het argument dat deze keer naar voren kwam was dat een observable toch kennis moest hebben van het contract dat naar buiten toe aangeboden wordt, net als bij IoC. Mochten er dus observers aangesloten worden die aanvullende informatie nodig hebben moeten de contracten uitgebreid worden. Dit contract kan je dan als interface net zo goed opnemen in het observable object en dan met een IoC framework laten injecteren.

Modelleertechnisch is er inderdaad geen verschil. Kennis van het contract dient ook aanwezig te zijn in de observable klasse die het event opgooit, dus deze kan net zo goed worden vervangen door een interface. Het technische verschil dat er in mijn optiek wel in zit is dat een interface slechts één implementatie ondersteunt, en dat een observable in principe oneindig veel observers ondersteunt. Dit maakt aan de observer kant dat je opdeling kunt hebben en niet alles in één grote interface implementatie hoeft te vervatten. Bij IoC zal je zowel de aangesloten emailcomponent als de databasecomponent moeten aanspreken via deze ene implementatie. Bij observable kan je ze flexibel aan- en afkoppelen.

Blijft het moeilijke punt: ik krijg een nieuwe requirement die vereist dat ik bepaalde gebeurtenissen in mijn systeem wil gaan uitsturen via emails bijvoorbeeld. Dit is een punt dat pleit voor het correct ontwerpen van je observable classes; alle voor de business significante user stories moeten enerzijds vanuit de buitenwereld aangeroepen kunnen worden op deze classes (via een service layer of iets dergelijks), maar andersom moeten ze dus óók alle relevante business events publiceren via hun observable hooks. Dit gaat dus verder dan alleen CRUD-achtige zaken voor repositories bijvoorbeeld. Sterker nog: wellicht dat CRUD helemaal niet de standaard modus moet zijn voor deze observable classes, dus géén ObjectChanged, ObjecstRequested events meer maar domeinspecifieke zoals QuestionnaireCompleted of EmployeeRetired events…?


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


Categorieën: Architectuur, Development

Tags: , ,


Reacties (4)

  • Ben het hierin met Arno eens, geloof ik. Als ik het in eigen woorden zou samenvatten:

    Verwacht je een implementatie van de interface, dat wil zeggen: is het logisch dat de interface geimplementeerd wordt, dan zou ik geen event gebruiken. Gaat het slechts om het aanbieden van koppelpunten, dan lijken mij events ideaal. Waarbij het dus ook heel goed mogelijk kan zijn dat er geen observer gekoppeld is.

    Verder wel een nuancering op de stelling van Arno over repositories: ja, maar dan zou ik wel bij willen vermelden dat repositories volgens mij iets heel anders zijn dan de database. Met andere woorden: dat iets in de repository wordt opgenomen, hoeft nog niet te betekenen dat het in de database of andere persistentie wordt opgeslagen. Sterker nog, je kunt volgens mij prima zinvolle repositories hebben in een volledig volatile domein, dus zonder persistentie. Als je dat niet duidelijk vind, wil ik wel eens een post aan wagen..

    Geplaatst op 03 augustus 2009 om 19:20 Permalink

    • Arno schreef:

      Definitie van El Evans leunt behoorlijk zwaar op het persisteren naar en ophalen uit een een datastore, in de huidige situatie meestal nog door een database ingevuld. Maar ik kan me voorstellen dat je daar andere platformen of technieken voor gebruikt. En als je een compleet andere insteek hebt, zeker bloggen!

      zie ook:Definition: A Repository is a mechanism for encapsulating storage, retrieval, and search behavior which emulates a collection of objects. (http://domaindrivendesign.org/node/123)

      Geplaatst op 04 augustus 2009 om 22:31 Permalink

      • Ik begreep van l’Evans in zijn veelbesproken boek dat hij daar ook een scheiding aanbrengt tussen een functionele opslag (repository) en persistentie.

        Je kunt een object in en uit een repository halen zonder dat het objectmodel ooit in de database wordt opgeslagen. Andersom kun je je objectmodel in en uit de database halen zonder dat er 1 object in en uit de repository is gegaan (alsof het model in (n-) hibernation is gegaan ;-)). Iets anders is dat het event van het in- en uit de repository halen een database read of write triggert, dat zou natuurlijk best kunnen. Maar ze zijn niet direct gelinkt en het domein weet ook niets van die database acties.

        Voorwaarde voor het kunnen begrijpen waarom een repository hierin iets anders is dan een (fysieke) database, is wel dat je loslaat dat de database de daadwerkelijke state van je applicatie is en dat het domeinmodel daar slechts een toegang toe is (als een soort waakhond ervoor ligt). In de zienswijze op een DDD applicatie die ik aanhang is de repository in het domein leading voor de opslag van state binnen het domein. De database zorgt er slechts voor dat het domeinmodel weer terugkomt in de oorspronkelijke staat nadat je de applicatie uitgezet hebt.

        Geplaatst op 17 augustus 2009 om 9:18 Permalink

  • Arno schreef:

    Volgens mij zijn events inderdaad een goed middel om gebeurtenissen binnen een domein naar buiten te exposen. Met name als er van geen tot veel listeners aan kunnen hangen en het domein niets verwacht van de (eventueel) gekoppelde componenten.

    Waar het volgens mij te ver gaat is als het gebruikt wordt om onderdelen te koppelen die centraal onderdeel zijn van de technische architectuur en conceptueel toch al gekoppeld zijn. Bijvoorbeeld een repository: Je weet dat je moet persisteren en zonder kan het niet werken. Als je dit gaat koppelen met events ziet je
    1. Dat het domeinmodel toch wel weet dat het gekoppeld moet worden. Er wordt immers op een punt (het event) om een object gevraagd.
    2. Dat het vaak synchroon moet worden uitgevoerd. Bijvoorbeeld bij een ObjecstRequested event waarbij het domein verwacht van een gekoppeld component een lijst objecten te krijgen.
    3. Dat het evident is dat er 1 koppeling moet zijn. 0 is geen optie en meer koppelingen kan functioneel gezien niet (gaan straks 3 repositories objecten naar het domein sturen).
    Op zo’n onderdeel heeft het volgens mij geen toegevoegde waarde om events te gebruiken. Sterker nog, het maakt het complexer omdat je moet controleren of er wel iets gekoppeld is aan het event maar niet meer dan éen keer. Je maakt eigenlijk gebruik van een te losse koppeling voor het probleem dat je oplost.

    Business events naar buiten sturen (die niets terug verwachten) is volgens mij wel een goed plan. In een project een tijdje terug gebruik van gemaakt. Hierbij werden er events als ‘NieuweLening’, ‘FinaalAkkoordGegeven’ en ‘DocumentGeaccepteerd’ via WCF (over MSMQ) de wereld in gestuurd. Hierdoor konden er onafhankelijk van elkaar email, sms en andere componenten worden gekoppeld zonder dat het domein daar iets van hoefde te weten. De repository voor persistentie hebben we simpel opgelost met een interface in het domein en een implementatie daarbuiten die met een IoC framework ge-bootstrapped werd. Twee verschillende problemen\eisen met elk hun eigen oplossing.

    Geplaatst op 02 augustus 2009 om 22:34 Permalink