Mapper Contexts Supercontexts: ontkoppeling van domeinspecifieke en domeingenerieke begrensde contexten

(1 aug.2019)

Je bouwt een nieuw systeem en twee leden van uw team stellen alternatieve architecturen voor voor het verzenden van meldingen. Welke is correct?

De eerste ontwikkelaar stelt een push-model voor: begrensde contexten moeten de notificatiecontext instrueren om een ​​notificatie te verzenden. De meldingscontext (Meldingen) moet gewoon commandos uit andere contexten gehoorzamen en meldingen verzenden wanneer hierom wordt gevraagd.

De tweede ontwikkelaar heeft een hekel aan het push-model en stelt een gechoreografeerde oplossing voor: wanneer begrensde contexten gebeurtenissen oproepen, moeten notificaties luisteren en bepalen wanneer een notificatie moet worden verzonden.

Hoe zou u de oplossing ontwerpen? Wat nog belangrijker is, hoe zou u deze beslissing in het team oplossen? Hoe ga je de meest effectieve architectuur ontwerpen die korte-termijndoelen en langetermijnevolutie ondersteunt?

Het hebben van DDD-vaardigheden in het team is een groot voordeel. Als u uw domein kunt analyseren om de kern-, ondersteunende en generieke mogelijkheden te begrijpen, kunt u goede technische afwegingen maken.

Laten we dit scenario verder verkennen vanuit een DDD-perspectief.

Domein Capability Analysis

Het argument voor optie 1 (push-commandos) is dat generiek (notificaties) niet afhankelijk moet zijn van specifiek. Als iets generiek is voor veel domeinen, is het logischerwijs verkeerd als het is gekoppeld aan iets in een enkel domein.

Als we verder kijken dan abstract redeneren, waar gaat deze heuristische waarschuwing ons over? Wat zijn de technische gevolgen waarvan we ons bewust moeten zijn?

Er zijn twee scenarios die we willen vermijden:

  1. Voorkomen dat domeinspecifieke logica lekt naar generieke contexten, wat resulteert in -wijziging
  2. Onvermogen om generieke contexten te hergebruiken of te vervangen door een kant-en-klare oplossing omdat te nauw is gekoppeld aan domeinspecifieke begrensde contexten

Koppeling van domein en algemene verantwoordelijkheden

Met optie 1 is er geen gelijktijdige verandering tussen domeinspecifieke en domein-generieke APIs. Als een nieuwe melding nodig is, veranderen alleen de domeinspecifieke contexten. Maar dit is niet het geval met optie 2.

Met optie 2 (gechoreografeerd), als een nieuw evenement wordt geïntroduceerd waarvoor meldingen zijn vereist, moet een domeinspecifieke API het nieuwe evenement en de meldingsservice publiceren moet zich abonneren op het evenement en een melding sturen. Dit voelt niet goed – kennis van het domein verbergt zich in de algemene context.

Algemene mogelijkheden isoleren

Als de meldingsservice echt generiek is en hergebruikt voor veel teams of zelfs een organisatie, moet het op de hoogte zijn van honderden domeingebeurtenissen. En met zoveel teams die afhankelijk zijn van de kennisgevingscontext, zal het zeker een bottleneck worden, waardoor het potentieel voor hergebruik in een organisatie wordt verkleind.

Een ander stukje ontwerpfeedback is dat we de generieke context niet kunnen vervangen door een kant-en-klare oplossing. Als het echt generiek is voor veel domeinen, maar we het niet kunnen vervangen door een kant-en-klare oplossing die meer functionaliteit heeft en minder kost, geeft het ontwerp feedback dat er iets mis is.

Dus commandos van specifiek naar algemeen is een best practice?

Al het bewijs suggereert dat optie 1 correct is: domeinspecifieke contexten zouden commandos naar domein-generieke contexten moeten sturen om ze los te koppelen van domeinlogica. Onze analyse was echter oppervlakkig. We moeten het domein verder analyseren om ons het vertrouwen te geven dat we goede technische keuzes maken.

Diepere domeinanalyse

Als we beter kijken naar optie 1 (specifieke instructies generiek), kan elk domein -specifieke context die meldingen moet verzenden, heeft een extra verantwoordelijkheid gekregen. Het moet weten wanneer meldingen moeten worden verzonden en welk type melding moet worden verzonden.

Is het verstandig om de logica van meldingen te verspreiden over alle begrensde contexten? Samen met verwarde code kan dit een grootschalige coördinatie tussen veel teams betekenen als de kennisgevingen veranderen.

Er is ook een verhoogd risico op inconsistenties en duplicatie / verspilling als elk team zijn eigen benadering van meldingen aanneemt. Gedeelde bibliotheken zijn mogelijk, maar ze lossen niet alle problemen op en brengen ook compromissen met zich mee.

Sommige domeinconcepten partitioneren duidelijk (rood, grijs, gele driehoeken; blauwe cirkels) maar sommige hebben overlappen verschillende dimensies en kunnen op meerdere manieren worden gecategoriseerd (blauwe driehoeken)

Telkens wanneer het moeilijk is om te beslissen of een verantwoordelijkheid in een of andere context moet horen, zoom in en ontleed de verantwoordelijkheid verder. Zoek naar subverantwoordelijkheden die uit elkaar kunnen worden gehaald – misschien is er een verborgen domeinconcept.

Als een concept niet precies past in een enkele begrensde context, analyseer het dan verder om subverantwoordelijkheden te identificeren. Misschien is er een verborgen domeinconcept dat een netjes gepartitioneerd model kan opleveren.

Inzoomen op de omstreden verantwoordelijkheid voor het verzenden van meldingen, zou er een concept kunnen ontbreken ? Misschien is er een derde concept dat domeinspecifiek koppelt aan domein-generiek om een ​​eleganter model te bieden.

Domain Mapper-contexten

Eén patroon dat kan worden gebruikt om domeinspecifieke en domein-generiek is de Domain Mapper Context. Wanneer een context deze rol op zich neemt, luistert het naar specifieke domeingebeurtenissen en wijst deze toe op opdrachten die naar een generieke context zijn verzonden.

Merk op hoe de afwegingen van dit patroon zich verhouden tot de voor- en nadelen van de eerste twee opties. Het biedt de voordelen van beide: vrijheid om de manier waarop meldingen worden verzonden te wijzigen zonder elke domeinspecifieke context te verstoren met aan meldingen gerelateerde complexiteit.

Overweeg het scenario: een intern meldingssysteem wordt vervangen door een kant-en-klare oplossing. De domeintoewijzer stuurt alle commandos naar de nieuwe notificatieservice, zonder dat dit invloed heeft op domeinspecifieke contexten.

Overweeg een ander scenario: er moet een nieuwe notificatie worden toegevoegd. Een registratie zou worden geconfigureerd binnen de mapper: when {domain event} trigger {notification}.

Meldingen zijn een domeingenerieke mogelijkheid – veel domeinen maken gebruik van e-mail- en pushmeldingen
Meldingsvoorkeuren op Twitter – toewijzing van domeinspecifieke gebeurtenis aan domein-generieke acties (e-mails)

Waarom heet Mapper Contexts?

De de naamgeving van dit patroon is significant. Acties die plaatsvinden binnen het ene domein worden toegewezen aan acties die plaatsvinden in een ander domein (een generieke context is algemeen voor veel domeinen en bevindt zich gedeeltelijk ook in een ander domein).

Mogelijk zijn er overeenkomsten met andere patronen, zoals de berichtenvertaler , maar vertaling impliceert enige gelijkwaardigheid; de vertaalde waarde is een andere weergave van de oorspronkelijke waarde. Met een mapper is dit niet het geval.

Een mapper is meer een luisteraar, die observeert wat er binnen het domein gebeurt. Het neemt een beslissing over hoe te reageren op gebeurtenissen in het domein met een actie in een ander domein.

Gateway Domain Mapper Contexts

Als u besluit om uw op maat gemaakte generieke context met een SaaS-oplossing, wordt uw Domain Mapper-context een Gateway Domain Mapper-context.

A Gateway bevindt zich aan de rand van een systeem dat de instroom en uitstroom van informatie beheert

Een Gateway Domain Mapper Context voert in wezen dezelfde functie uit, maar zit nu op de rand van uw systeem en communiceert over systeemgrenzen heen. Het is een route voor informatie die in en uit het systeem stroomt.

De implementatie ziet er misschien hetzelfde uit, maar een preciezere terminologie is handig om je architectuur duidelijker te laten communiceren.

Domain Mapper Engineering Trade-offs

De patronen die verband houden met Domain Mapper Contexts zijn niet onbelangrijk. Door de extra kaartlaag zijn er nu drie medewerkers bij betrokken. Meer dingen die kunnen mislukken.

Er is ook co-change. Wanneer nieuwe evenementen worden geïntroduceerd of bestaande evenementen veranderen, zullen zowel de domeinspecifieke contexten die eigenaar zijn van de evenementen als de mapper-context moeten veranderen.

Er zijn veel gebruikte oplossingen om deze kosten te minimaliseren.

Selfservice Domain Mapper Contexten

Een patroon dat vaak in het wild voorkomt, is de selfservice-gebonden context. Een begrensde context die deze rol speelt, stelt consumenten in staat gebruik te maken van de mogelijkheden van de context zonder te worden geblokkeerd door het team dat de context bezit.

De eerste variant is een compilatietijdmechanisme via broncontrole en de tweede is een runtime-mechanisme via API-aanroepen.

In het notificatiescenario zou de zelfbedieningscontext een DSL kunnen opleveren. Teams die domeinspecifieke contexten bezitten, zouden een pull-verzoek maken met wijzigingen in een configuratiebestand (nog beter – code die compileert en wordt getest), die met behulp van de DSL een mapping configureert tussen een domeingebeurtenis om op te abonneren en een melding naar verzonden.

Met de dynamische versie zou de overeenkomstige configuratie worden uitgevoerd via een API-oproep of UI. Wanneer dynamische configuratie mogelijk is en er geen afhankelijkheden tijdens compileren van het domein zijn, verschuift de context naar volledig generiek. Dit is een algemeen evolutionair patroon ().

Gepubliceerde taal

Een ander DDD-patroon dat in dit type scenario moet worden overwogen, is de gepubliceerde taal. Elke gebeurtenis die een melding activeert, moet deel uitmaken van een gepubliceerde taal.

Een gepubliceerde taal is een contract of een overeenkomst over het formaat van berichten geproduceerd door een begrensde context. Door ervoor te zorgen dat gebeurtenissen waarvoor een melding vereist is, deel uitmaken van een gepubliceerde taal, moet er meer aandacht worden besteed aan compatibiliteit met eerdere versies en moet ik consumenten op de hoogte stellen van toekomstige wijzigingen.

Moet ik altijd Domain Mapper-contexten gebruiken?

Absoluut niet. Elk van de patronen die in het bericht worden gepresenteerd, is geldig en wordt met succes gebruikt in verschillende systemen. Domain Mapper-contexten zijn een ander patroon met duidelijke afwegingen die u kunt gebruiken om alternatieve modelleringsmogelijkheden te verkennen.

De zoektocht naar supercontexten

Het is gemakkelijk om domeinen te modelleren op een naïef of oppervlakkig niveau . Wanneer je een woord als meldingen hoort, valt het gemakkelijk voor de samenhangende naamfout, ervan uitgaande dat, omdat een woord klinkt als een enkel concept, het moet worden weergegeven door een enkele begrensde context in ons systeem.

Wanneer we DDD gebruiken om op een dieper niveau te analyseren, en we kijken naar het scheiden van domeinspecifieke en domeingenerieke concepten, zullen we vaak ontdekken dat er meerdere manieren zijn om het domein te modelleren, waaronder meerdere begrensde contexten – waarbij domeinspecifieke van generieke – binnen een enkele supercontext.

Het ontkoppelen van domeinspecifiek van domein-generiek gaat niet over het creëren van prachtige abstracte modellen die oude DDD-regels volgen, het gaat over het ontkoppelen van concepten die om verschillende redenen samen veranderen, zodat we handel kunnen ontwikkelen -offs waardoor systemen gemakkelijker kunnen evolueren.

Probeer de Single Domain Classification Fallacy te vermijden: ervan uitgaande dat een high-level mogelijkheid, Notifications, een enkele domeinclassificatie moet hebben (bijv. generiek).

In orde Om diepere domeininzichten te krijgen, raad ik aan om DDD-vaardigheden en DDD-activiteiten in de manier van werken van je team te integreren. Experimenteer met EventStorming en (The Bounded Context Design Canvas) als een startpunt om te leren hoe u beter begrensde contexten kunt modelleren.

Training en advies

Als u hulp zoekt bij het verkennen van uw domein, het ontwerpen van uw systeem of het trainen van uw teams, contact met mij opnemen voor meer informatie. Ik werk met een netwerk van zeer ervaren DDD-beoefenaars die een passie hebben voor het ontwerpen van effectieve sociotechnische systemen die zijn afgestemd op de zakelijke doelen en het domein.