Mapper-sammenhænge Superkontekster: Afkobling af domænespecifikke og domæne-generiske afgrænsede sammenhænge

(1. aug. 2019)

Du bygger et nyt system og to medlemmer af dit team foreslår alternative arkitekturer til afsendelse af underretninger. Hvilken er korrekt?

Den første udvikler foreslår en push-model: afgrænsede sammenhænge skal instruere underretningskonteksten om at sende en underretning. Notifikationskonteksten (Notifikationer) skal blot adlyde kommandoer fra andre sammenhænge og sende meddelelser, når de bliver bedt om det.

Den anden udvikler kan ikke lide push-modellen og foreslår en koreograferet løsning: når afgrænsede sammenhænge rejser begivenheder Underretninger skal lytte og bestemme, hvornår de skal sende en underretning.

Hvordan vil du arkitektere løsningen? Endnu vigtigere, hvordan ville du løse denne beslutning i holdet? Hvordan vil du designe den mest effektive arkitektur, der understøtter kortsigtede mål og langsigtet udvikling?

At have DDD-færdigheder i teamet er en stor fordel. At være i stand til at analysere dit domæne for at forstå kerne-, understøttelses- og generiske kapaciteter gør det muligt for dig at foretage afvejninger inden for lydteknik.

Lad os udforske dette scenarie yderligere med et DDD-perspektiv.

Domæne Kapacitetsanalyse

Argumentet for mulighed 1 (pushede kommandoer) er, at generisk (Notifikationer) ikke skal afhænge af specifikke. Hvis noget er generisk på tværs af mange domæner, er det logisk set forkert, hvis det er koblet til noget i et enkelt domæne.

Ser man ud over abstrakt ræsonnement, hvad advarer denne heuristik os om? Hvad er de tekniske konsekvenser, vi skal være opmærksomme på?

Der er to scenarier, vi vil undgå:

  1. Undgå domænespecifik logik, der lækker i generiske sammenhænge, ​​hvilket resulterer i co -ændring
  2. Manglende evne til at genbruge eller erstatte generiske sammenhænge med en løsning, der ikke er på hylden på grund af at være for tæt koblet til domænespecifikke afgrænsede sammenhænge

Koblingsdomæne og generisk ansvar

Med mulighed 1 er der ingen samændring mellem domænespecifikke og domænegeneriske APIer. Hvis der er behov for en ny anmeldelse, ændres kun de domænespecifikke sammenhænge. Men dette er ikke tilfældet med mulighed 2.

Med mulighed 2 (koreograferet), hvis der introduceres en ny begivenhed, der kræver meddelelser, skal en domænespecifik API offentliggøre den nye begivenhed og meddelelsestjenesten skal abonnere på begivenheden og sende en underretning. Dette føles ikke rigtigt – kendskab til domænet gemmer sig inden for den generiske kontekst.

Isolering af generiske kapaciteter

Hvis meddelelsestjenesten virkelig er generisk og genbruges på tværs af mange hold eller endda en organisation, skal det kende hundreder af domænehændelser. Og med så mange hold afhængigt af underretningskonteksten, vil det helt sikkert blive en flaskehals, der reducerer potentialet for genbrug på tværs af en organisation.

Et andet stykke designfeedback er, at vi ikke kan erstatte den generiske kontekst med en hyldeløsning. Hvis det virkelig er generisk på tværs af mange domæner, kan vi ikke erstatte det med en hyldeløsning, der har mere funktionalitet og koster mindre at køre, design giver feedback om, at der er noget galt.

Så kommandoer fra specifikke til generiske er en bedste praksis?

Alt bevis tyder på, at mulighed 1 er korrekt: domænespecifikke sammenhænge skal sende kommandoer til domæne-generiske sammenhænge for at afkoble dem fra domænelogik. Imidlertid har vores analyse været lav. Vi er nødt til at analysere domænet yderligere for at give os den tillid, vi træffer gode tekniske valg.

Dybere domæneanalyse

Ser vi nærmere på mulighed 1 (specifikt instruerer generisk), hvert domæne -specifik kontekst, der skal sende meddelelser, har påtaget sig et yderligere ansvar. Det skal vide, hvornår der skal sendes meddelelser, og hvilken type underretning, der skal sendes.

Er det fornuftigt at have notifikationslogik spredt over alle de afgrænsede sammenhænge? Sammen med sammenfiltret kode kan dette betyde en koordination i stor skala på tværs af mange hold, hvis meddelelsesmetoden ændres.

Der er også en øget risiko eller inkonsekvenser og duplikering / spild, hvis hvert hold vedtager deres egen tilgang til meddelelser. Delte biblioteker er en mulighed, men de løser ikke alle problemerne, og de bringer også kompromiser.

Nogle domæne begreber partitionerer tydeligt (røde, grå, gule trekanter; blå cirkler), men nogle har overlapning på tværs af forskellige dimensioner og kan kategoriseres på flere måder (blå trekanter)

Når der er problemer med at afgøre, om et ansvar skal høre hjemme i en eller anden sammenhæng, zoome ind og nedbryde ansvaret yderligere. Se efter underansvar, der kan opdeles – måske er der et skjult domænekoncept.

Når et koncept ikke passer rent ind i en enkelt afgrænset kontekst, skal du analysere det yderligere for at identificere underansvar. Måske er der et skjult domæne-koncept, der kan give en ren partitioneret model.

Zoom ind i det omstridte ansvar for at sende underretninger, kan der være et manglende koncept ? Måske er der et tredje koncept, der forbinder domænespecifikt til domæne-generisk for at give en mere elegant model.

Domain Mapper Contexts

Et mønster, der kan bruges til at afkoble domænespecifikt og domæne-generisk er Domain Mapper Context. Når en kontekst påtager sig denne rolle, lytter den til specifikke domænehændelser og kortlægger dem på kommandoer sendt til en generisk kontekst.

Læg mærke til, hvordan dette mønsters afvejninger sammenlignes med fordele og ulemper ved de to første indstillinger. Det giver fordele ved begge dele – frihed til at ændre, hvordan meddelelser sendes uden at forstyrre enhver domænespecifik kontekst med underretningsrelateret kompleksitet.

Overvej scenariet: et internt underretningssystem skal erstattes af en hyldeløsning. Domænekortlæggeren dirigerer alle kommandoer til den nye underretningstjeneste, uden at der påvirkes nogen domænespecifikke sammenhænge.

Overvej et andet scenario: en ny meddelelse skal tilføjes. En registrering vil blive konfigureret inden for kortlæggeren: når {domænehændelse} udløser {notifikation}.

Underretninger er en domæne-generisk kapacitet – mange domæner udnytter e-mail- og push-underretninger
Underretningsindstillinger på Twitter – kortlægning fra domænespecifik begivenhed til domænegeneriske handlinger (e-mails)

Hvorfor kaldes Mapper Contexts?

The navngivning af dette mønster er vigtig. Handlinger, der sker inden for et domæne, kortlægges på handlinger, der sker i et andet domæne (en generisk kontekst er generisk på tværs af mange domæner, så er delvist i et andet domæne).

Du kan muligvis ligheder med andre mønstre som meddelelsesoversætter , men oversættelse indebærer en vis ækvivalens; den oversatte værdi er en anden repræsentation af den oprindelige værdi. Med en kortlægger er dette ikke tilfældet.

En kortlægger er mere en lytter og observerer, hvad der sker inden for domænet. Det træffer en beslutning om, hvordan man skal reagere på begivenheder i domænet med en handling i et andet domæne.

Gateway Domain Mapper Contexts

Hvis du beslutter at udskifte dit specialbyggede generisk kontekst med en SaaS-løsning, bliver din Domain Mapper Context en Gateway Domain Mapper Context.

A Gateway sidder ved kanten af ​​et system, der styrer tilstrømning og udstrømning af information

En Gateway Domain Mapper Context udfører stort set den samme funktion, men den sidder nu ved kanten af ​​dit system og kommunikerer på tværs af systemgrænser. Det er en rute for information, der flyder ind og ud af systemet.

Implementeringen kan se det samme ud, men at have en mere præcis terminologi er nyttig til at give dig mulighed for at kommunikere din arkitektur mere tydeligt.

Kompromisser mellem domænekortudvikling

De tilknyttede mønstre for domænekortkontekster er ikke ubetydelige. Det ekstra kortlægningslag betyder, at der nu er tre samarbejdspartnere involveret. Flere ting, der kan mislykkes.

Der er også co-change. Når nye begivenheder introduceres, eller eksisterende begivenheder ændres, skal både de domænespecifikke sammenhænge, ​​der ejer begivenhederne, og kortlægningskonteksten ændres.

Der findes en udbredt løsning til at minimere disse omkostninger.

Selvbetjeningsdomænekortkontekster

Et mønster, der ofte forekommer i naturen, er den selvbetjeningsafgrænsede kontekst. En afgrænset kontekst, der spiller denne rolle, giver forbrugerne mulighed for at udnytte kontekstens muligheder uden at blive blokeret af det hold, der ejer konteksten.

Den første variation er en kompileringstidmekanisme via kildekontrol, og den anden er en runtime-mekanisme via API-opkald.

I notifikationsscenariet kunne selvbetjeningskonteksten give en DSL. Teams, der ejer domænespecifikke sammenhænge, ​​opretter en pull-anmodning, der indeholder ændringer i en konfigurationsfil (endnu bedre – kode, der kompileres og testes), der ved hjælp af DSL konfigurerer en kortlægning mellem en domænehændelse at abonnere på og en underretning om sendes.

Med den dynamiske version udføres den tilsvarende konfiguration via et API-opkald eller UI. Når dynamisk konfiguration er mulig, og der ikke er nogen afhængighed af kompileringstid på domænet, skifter konteksten mod at blive fuldstændig generisk. Dette er et fælles evolutionært mønster ().

Udgivet sprog

Et andet DDD-mønster, der skal overvejes i denne type scenarie, er det offentliggjorte sprog. Enhver begivenhed, der udløser en meddelelse, skal være en del af et offentliggjort sprog.

Et offentliggjort sprog er en kontrakt eller en aftale om formatet på meddelelser, der er produceret af en afgrænset kontekst. At sikre, at begivenheder, der kræver en underretning, er en del af et offentliggjort sprog, betyder, at der skal tages større omhu for at sikre bagudkompatibilitet og underrette forbrugerne om fremtidige ændringer.

Skal jeg altid bruge Domain Mapper Contexts?

Bestemt ikke. Hvert af de mønstre, der præsenteres i indlægget, er gyldige og anvendes med succes i en række forskellige systemer. Domain Mapper Contexts er et andet mønster med klare afvejninger, som du kan bruge til at udforske alternative modelleringsmuligheder.

Søgningen efter supercontexts

Det er let at modellere domæner på et naivt eller overfladisk niveau . Når man hører et ord som underretninger, er det let at falde for det sammenhængende navn fejl, forudsat at fordi et ord lyder som et enkelt koncept, skal det repræsenteres af en enkelt afgrænset kontekst i vores system.

Når vi bruger DDD til at analysere på et dybere niveau, og vi ser på separate domænespecifikke og domæne-generiske koncepter, vil vi ofte finde ud af, at der er flere måder at modellere domænet på, herunder at have flere afgrænsede sammenhænge – afgrænsning af domæne specifikt fra generisk – inden for en enkelt superkontekst.

Afkobling af domænespecifikt fra domænegenerisk handler ikke om at skabe smukke abstrakte modeller, der følger gamle DDD-regler, det handler om afkobling af koncepter, der ændres sammen af ​​forskellige grunde, så vi kan konstruere handel -offs, der tillader systemer at udvikle sig lettere.

Prøv at undgå fejlfinding i Single Domain Classification: forudsat at en kapacitet på højt niveau, Notifications, skal have en enkelt domæne-klassifikation (f.eks. generisk).

I orde r for at få dybere domæneindsigt anbefaler jeg at bringe DDD-færdigheder og DDD-aktiviteter ind i dit teams måde at arbejde på. Eksperimenter med EventStorming og (The Bounded Context Design Canvas) som udgangspunkt for at lære, hvordan man modellerer bedre afgrænsede sammenhænge.

Uddannelse og rådgivning

Hvis du søger hjælp til at udforske dit domæne, designe dit system eller træne dine teams, kontakt mig for yderligere information. Jeg arbejder med et netværk af meget erfarne DDD-praktikere, der brænder for at designe effektive sociotekniske systemer, der er tilpasset forretningsmålene og domænet.