Hvad jeg forstår om domænedrevet design
On november 15, 2021 by adminDDD 101
Jo større projektet er, jo sværere er det at vedligeholde det. En måde at hjælpe med det er at opdele appen i mindre områder i henhold til deres forretningsregler, kendt som domæner.
Grundlæggende er et domæne et vidensområde, enten offentligt, som reglerne i skak, eller privat, som forretningsreglerne i en nonprofitorganisation .
Et komplekst domæne vil sandsynligvis bruge viden fra andre domæner. For eksempel vil en NPO, der underviser i skak online, have viden om skak, undervisning via onlineplatforme og, selv om du ikke bliver opkrævet som elev, om dens økonomi.
Hvert underområde af dit domæne er kendt i DDD som bounded contexts, hver har sin egen model af verden bygget med specialiserede enheder af kode, kendt som byggeklodser. Her vil jeg fokusere på entiteter og værdi-objekter, begge kan refereres som objekter.
Entiteter er objekter, der er beregnet til at være unikke inden for domænet. Dette opnås ved at bruge en eller flere proprieties til at identificere en given enhed. F.eks. vil to brugere med samme navn i et system altid have forskellige e-mails, fordi e-mails ikke kan gentages – oftest differentieres entiteter ved hjælp af et id og nogle gange ved hjælp af en kombination af proprieties.
Value-objekter har på den anden side ikke en identitet, så kun deres egenskaber kan bruges til at skelne mellem to forekomster. Tag f.eks. to bønder (skakbrikken), de ser ens ud, hvis de kommer fra samme spilsæt og har samme farve, så det er ligegyldigt, om du bytter rundt på dem. I DDD er value-objekter uforanderlige, så det er nemmere at ræsonnere med dem.
Dataintegritet
En afgrænset kontekst eksponerer ikke alle sine objekter for at garantere sin dataintegritet. I stedet eksponerer den nogle aggregerede rødder som en slags offentlig grænseflade til sig selv.
Et aggregat er intet andet end en enhed, der er sammensat af andre objekter. Mere præcist er et aggregat en klynge af tilknyttede objekter, som vi behandler som en enhed, når vi ændrer data.
I praksis vil aggregater antage formen af den datastruktur, der er kendt som et træ. Og derfor har alle aggregater en rod.
Det eneste medlem af et aggregat, som andre objekter kan henvise til, er dets rod, og det er derfor dette, vi eksponerer. Det gøres sådan, fordi det forhindrer andre objekter i at ændre data på en måde, som aggregatet ikke kan kontrollere.
Vigtigt at gøre det klart, at en afgrænset kontekst kan bruge mange aggregater, selv om deres rod ikke er direkte eksponeret for omverdenen.
Håndtering af flere afgrænsede kontekster
Men tingene kan blive mere komplicerede, ikke sandt? Hver bounded context får en lidt anderledes model af de samme objekter, der har forskellige egenskaber og adfærd. Så en bruger i en spilkontekst kan have en egenskab til at håndtere sin score, som i en finansiel kontekst er irrelevant og derfor ikke eksisterer.
Og det er ikke det hele. Det er også muligt, at et domænebegreb, der er repræsenteret som en entitet i en afgrænset kontekst, kan være repræsenteret som en objekt-værdi i en anden, eller bare helt udelades.
For eksempel, mens undervisningskonteksten kræver, at lærere repræsenteres som entiteter, så de kan tildeles elever ved hjælp af deres id’er, foretrækker finanskonteksten at se “lærer” som en værdi for position-egenskaben for medarbejder-entiteten.
Nogle af de andre DDD-byggeklodser er services, repositories, factories og events. Jeg vil forsøge at beskrive dem kort.
Tjenester er kapaciteter i et domæne, som ikke naturligt passer til entiteter eller objektværdier. Vær opmærksom på, at de er domænetjenester, ikke applikations- eller infrastrukturtjenester.
Repositories er broer til lagerenheder – hej CRUD!.
Factories er metoder til at skabe domæneobjekter, så de aldrig har ugyldige værdier. Denne del er det, der fik mig til at tænke på produktdrevne tests.
Events er objekter, der repræsenterer noget, der er sket i domænet – dets eksperter bekymrer sig om dem. Store muligheder for at skabe en begivenhedsdrevet applikation .
Selv om jeg ikke kan huske, at Evans har sagt det, er bounded contexts en god mulighed for at dele din kode op i mikroservices, hvor hver service er en kontekst for sig selv. Det første skridt kan være en “virtuel” opdeling, hvor hver kontekst lægges i et andet modul på den samme app, og hvis du så opdager, at de virkelig er isolerede, så flyt dem til forskellige.
Et sprog til at styre dem alle
En af de første ting folk lærer, når de studerer DDD er, at deres system skal beskrives af et allestedsnærværende sprog. Det vil sige, at vi bør skrive kode ved hjælp af de samme verber (for metoder eller tjenester) og navneord (for objekter), som domæneeksperterne bruger, når de taler med os.
At skrive kode på denne måde har den fordel, at det lukker kommunikationsgabet mellem udviklere og eksperter, når de taler sammen, men det er en oversimplificering af virkeligheden, så jeg bruger det personligt som en retningslinje, men ikke som en endelig løsning.
Jeg gemte den til sidst, fordi for mig er det vigtigste om DDD normalt ikke læst, da det er i den “komplekse” del af bogen.
Nu har jeg erfaret, at forfatteren selv sagde, at den rækkefølge han præsenterer tingene i bogen ikke er optimal, og det jeg beskrev her er tættere på det, der ville have været ideelt 😍. Jeg hørte det på en podcast med henvisning til denne her
Skriv et svar