Domain-Driven Design (DDD) er en tilgang til softwareudvikling, der fokuserer på at forstå og modellere det problemdomæne, som et softwaresystem opererer indenfor. Det understreger vigtigheden af at samarbejde tæt med domæneeksperter for at udvikle en dyb forståelse af domænets forviklinger og kompleksiteter. DDD giver et sæt principper, mønstre og praksisser for at hjælpe udviklere med effektivt at fange og udtrykke domænekoncepter i deres softwaredesign.
heltal dobbelt java
Vigtige emner for domænedrevet design (DDD)
- Hvad er domænedrevet design (DDD)?
- Vigtigheden af domæneviden
- Strategisk design i domænedrevet design (DDD)
- Taktiske designmønstre i domænedrevet design (DDD)
- Fordele ved domænedrevet design (DDD)
- Udfordringer ved domænedrevet design (DDD)
- Use-Cases of Domain-Driven Design (DDD)
- Eksempel på domænedrevet design (DDD) fra den virkelige verden
Hvad er domænedrevet design (DDD)?
Domæne
Det refererer til det emneområde eller problemområde, som softwaresystemet er ved at blive bygget til at adressere. Den omfatter de virkelige begreber, regler og processer, som softwaren er beregnet til at modellere eller understøtte. For eksempel i en bankapplikation omfatter domænet begreber som konti, transaktioner, kunder og regler relateret til bankoperationer.
Kørt
Driven indebærer, at designet af softwaresystemet er styret eller påvirket af domænets egenskaber og krav. Med andre ord er designbeslutningerne baseret på en dyb forståelse af domænet i stedet for udelukkende at være drevet af tekniske overvejelser eller implementeringsdetaljer.
Design
Design refererer til processen med at skabe en plan eller plan for softwaresystemet. Dette inkluderer beslutninger om, hvordan systemet vil være struktureret, hvordan forskellige komponenter vil interagere, og hvordan systemet vil opfylde sine funktionelle og ikke-funktionel krav. I forbindelse med Domain-Driven Design er fokus på at designe softwaren på en måde, der præcist afspejler domænets struktur og adfærd.
Domænedrevet design er et koncept introduceret af en programmør Erik Evans i 2004 i sin bog Domænedrevet design: Håndtering af kompleksitet i hjertet af software
Vigtigheden af domæneviden
Antag, at vi har designet software ved hjælp af al den nyeste teknologistak og infrastruktur, og vores softwaredesignarkitektur er fantastisk, men når vi frigiver denne software på markedet, er det i sidste ende slutbrugeren, der beslutter, om vores system er fantastisk eller ej. Også hvis systemet ikke løser forretningsbehov, så nytter det ikke nogen. Uanset hvor smuk den ser ud, eller hvor god arkitekturen dens infrastruktur er.
Ifølge Erik Evans , Når vi udvikler software, bør vores fokus ikke primært være på teknologi, snarere bør det primært være på forretning. Husk,
Det er ikke kundens opgave at vide, hvad de vil have – Steve Jobs
Strategisk design i domænedrevet design (DDD)
Strategisk design i domænedrevet design (DDD) fokuserer på at definere den overordnede arkitektur og struktur af et softwaresystem på en måde, der stemmer overens med problemdomænet. Den adresserer bekymringer på højt niveau, såsom hvordan man organiserer domænekoncepter, hvordan man opdeler systemet i håndterbare dele, og hvordan man etablerer klare grænser mellem forskellige komponenter.
Lad os se nogle nøglebegreber inden for strategisk design i domænedrevet design (DDD)
1. Afgrænsede sammenhænge
- En Bounded Context repræsenterer et specifikt område inden for det overordnede problemdomæne, hvor en bestemt model eller sprog gælder konsekvent.
- Forskellige dele af et system kan have forskellige betydninger for de samme termer, og en Bounded Context definerer eksplicitte grænser, inden for hvilke disse termer har specifikke betydninger.
- Dette giver teams mulighed for at udvikle modeller, der er skræddersyet til specifikke kontekster uden at indføre forvirring eller uoverensstemmelser.
- Bounded Contexts hjælper med at håndtere kompleksitet ved at nedbryde et stort, komplekst domæne i mindre, mere håndterbare dele.
2. Kontekstkortlægning
- Context Mapping er processen med at definere relationer og interaktioner mellem forskellige Bounded Contexts.
- Det involverer at identificere områder med overlap eller integration mellem kontekster og etablere kommunikationskanaler og aftaler mellem dem.
- Context Mapping hjælper med at sikre, at forskellige dele af systemet kan samarbejde effektivt, mens der stadig bevares klare grænser mellem dem.
- Der er forskellige mønstre og teknikker til Context Mapping, såsom Partnerskab, Shared Kernel og Customer-Supplier.
3. Strategiske mønstre
- Strategiske mønstre er generelle retningslinjer eller principper for at organisere arkitekturen af et softwaresystem på en måde, der stemmer overens med problemdomænet.
- Disse mønstre hjælper med at løse almindelige udfordringer ved design af komplekse systemer og giver gennemprøvede tilgange til at strukturere systemet effektivt.
- Eksempler på strategiske mønstre omfatter aggregater, domænehændelser og anti-korruptionslag.
- Disse mønstre giver løsninger på tilbagevendende problemer i domænedrevet design og hjælper med at sikre, at systemets arkitektur afspejler de underliggende domænekoncepter nøjagtigt.
4. Delt kerne
- Shared Kernel er et strategisk mønster, der involverer identifikation af områder med fællestræk mellem forskellige Bounded Contexts og etablering af en delt undergruppe af domænemodellen, der bruges af flere kontekster.
- Denne delte undergruppe eller kerne hjælper med at lette samarbejde og integration mellem kontekster, mens den stadig tillader hver kontekst at bevare sin egen særskilte model.
- Delt kerne bør bruges med omtanke, da det introducerer afhængigheder mellem kontekster og kan føre til kobling, hvis det ikke håndteres omhyggeligt.
5. Anti-korruptionslag (ACL)
- Anti-korruptionslaget er et andet strategisk mønster, der hjælper med at beskytte et system mod indflydelse fra eksterne eller ældre systemer, der bruger forskellige modeller eller sprog.
- En ACL fungerer som et oversættelseslag mellem det eksterne system og kernedomænemodellen og transformerer data og meddelelser efter behov for at sikre kompatibilitet.
- Dette gør det muligt for kernedomænemodellen at forblive ren og fokuseret på problemdomænet, mens den stadig integreres med eksterne systemer efter behov.
6. Allestedsnærværende sprog
Allestedsnærværende sprog refererer til et fælles ordforråd eller sprog, der bruges konsekvent og universelt på tværs af alle interessenter, der er involveret i udviklingen af et softwaresystem. Dette sprog består af termer, sætninger og begreber, der nøjagtigt repræsenterer domæneviden og -begreber.
Nogle af nøgleprincipperne i allestedsnærværende sprog er:
- Fælles forståelse : Det primære mål med Ubiquitous Language er at etablere en fælles forståelse af problemdomænet blandt alle medlemmer af udviklingsteamet, herunder udviklere, domæneeksperter, forretningsanalytikere og interessenter. Ved at bruge et fælles sprog kan alle involverede kommunikere mere effektivt og præcist formidle domænekoncepter og krav.
- Konsistens og klarhed : Allestedsnærværende sprog fremmer konsistens og klarhed i kommunikationen ved at bruge præcis og utvetydig terminologi. Hvert udtryk eller sætning i sproget skal have en klar og aftalt betydning,
- Tilpasning til forretningskoncepter : Det sprog, der bruges i DDD, bør stemme nøje overens med den terminologi og begreber, der bruges i forretningsdomænet. Det bør afspejle den måde, domæneeksperter tænker og taler om problemdomænet, og sikre, at softwaren nøjagtigt repræsenterer virkelige begreber og processer.
- Evolutionær natur : Allestedsnærværende sprog er ikke statisk, men udvikler sig over tid, efterhånden som teamet får en dybere forståelse af domænet, og efterhånden som kravene ændrer sig. Det bør tilpasses for at afspejle ny indsigt, opdagelser eller ændringer i forretningsprioriteter, og sikre, at sproget forbliver relevant og opdateret gennem hele udviklingsprocessen.
Taktiske designmønstre i domænedrevet design (DDD)
I Domain-Driven Design (DDD) er taktiske designmønstre specifikke strategier eller teknikker, der bruges til at strukturere og organisere domænemodellen i et softwaresystem. Disse mønstre hjælper udviklere med effektivt at fange kompleksiteten af domænet, samtidig med at de fremmer vedligeholdelse, fleksibilitet og skalerbarhed.
javascript streng trim
Lad os se nogle af de vigtigste taktiske designmønstre i DDD:
1. Enhed
En enhed er et domæneobjekt, der har en særskilt identitet og livscyklus. Enheder er karakteriseret ved deres unikke identifikatorer og foranderlige tilstand. De indkapsler adfærd og data relateret til et specifikt koncept inden for domænet.
For eksempel i en bankapplikation, en
BankAccount>enheden kan have egenskaber som kontonummer, saldo og ejer, sammen med metoder til at indbetale, hæve eller overføre penge.
2. Værdi Objekt
Et værdiobjekt er et domæneobjekt, der repræsenterer en begrebsmæssigt uforanderlig værdi. I modsætning til entiteter har værdiobjekter ikke en særskilt identitet og bruges typisk til at repræsentere entiteters attributter eller egenskaber. Værdiobjekter er lighedssammenlignelige baseret på deres egenskaber snarere end deres identitet.
For eksempel en
Money>værdiobjekt kan repræsentere en specifik mængde valuta, der indkapsler egenskaber som valutatype og beløb.
3. Samlet
- Et aggregat er en klynge af domæneobjekter, der behandles som en enkelt enhed med henblik på datakonsistens og transaktionsintegritet.
- Aggregater består af en eller flere entiteter og værdiobjekter, hvor en enhed er udpeget som den aggregerede rod.
- Den samlede rod fungerer som indgangspunktet for adgang til og ændring af aggregatets interne tilstand.
- Aggregater håndhæver konsistensgrænser inden for domænemodellen, hvilket sikrer, at ændringer af relaterede objekter foretages atomært.
For eksempel i et e-handelssystem, en
Order>aggregat kan bestå af enheder somOrderItem>ogCustomer>, medOrder>enhed, der fungerer som den aggregerede rod.
4. Depot
- Et repository er en mekanisme til at abstrahere dataadgang og persistenslogik fra domænemodellen.
- Lagre giver en standardiseret grænseflade til forespørgsel og lagring af domæneobjekter, hvilket skjuler detaljerne om, hvordan data hentes eller gemmes. Lagre indkapsler logikken for oversættelse mellem domæneobjekter og underliggende datalagringsmekanismer, såsom databaser eller eksterne tjenester.
- Ved at afkoble domænemodellen fra bekymringer om dataadgang muliggør repositories større fleksibilitet og vedligeholdelse.
For eksempel en
CustomerRepository>kan give metoder til forespørgsel og lagringCustomer>enheder.
5. Fabrik
- En fabrik er en skabende mønster bruges til at indkapsle logikken til at skabe forekomster af komplekse domæneobjekter. Fabrikker abstraherer processen med objektforekomst, hvilket giver kunderne mulighed for at skabe objekter uden at skulle kende detaljerne i deres konstruktion.
- Fabrikker er særligt nyttige til at skabe objekter, der kræver kompleks initialiseringslogik eller involverer flere trin.
For eksempel en
ProductFactory>kan være ansvarlig for at oprette forekomster afProduct>enheder med standardkonfigurationer.
6. Service
- En tjeneste er et domæneobjekt, der repræsenterer en adfærd eller operation, der ikke naturligt tilhører nogen specifik enhed eller værdiobjekt.
- Tjenester indkapsler domænelogik, der fungerer på flere objekter eller orkestrerer interaktioner mellem objekter.
- Tjenester er typisk statsløse og fokuserer på at udføre specifikke opgaver eller håndhæve domæneregler.
For eksempel en
OrderService>kan give metoder til at behandle ordrer, anvende rabatter og beregne forsendelsesomkostninger.
Fordele ved domænedrevet design (DDD)
- Fælles forståelse :
- Det tilskynder til samarbejde mellem domæneeksperter, udviklere og interessenter.
- Ved at opmuntre til en fælles forståelse af problemdomænet gennem det allestedsnærværende sprog, kan teams kommunikere mere effektivt og sikre, at softwaren nøjagtigt afspejler virksomhedens behov og krav.
- Fokus på kernedomæne :
- Det hjælper teams med at identificere og prioritere applikationens kernedomæne – de områder af systemet, der giver mest værdi for virksomheden. Ved at fokusere udviklingsindsatsen på kernedomænet kan teams levere funktionalitet, der direkte adresserer forretningsmål og adskiller softwaren fra konkurrenterne.
- Modstandsdygtighed over for forandring :
- Det lægger vægt på at designe softwaresystemer, der er modstandsdygtige over for forandringer ved at modellere domænet på en måde, der afspejler problemdomænets iboende kompleksiteter og usikkerheder.
- Ved at omfavne forandring som en naturlig del af softwareudvikling kan teams reagere mere effektivt på skiftende forretningsbehov og markedsforhold.
- Klar adskillelse af bekymringer :
- DDD opfordrer til en klar adskillelse af bekymringer mellem domænelogik, infrastrukturproblemer og brugergrænsefladeproblemer. Ved at isolere domænelogik fra tekniske detaljer og infrastrukturproblemer kan teams opretholde en ren og fokuseret domænemodel, der er uafhængig af specifikke implementeringsdetaljer eller teknologiske valg.
- Forbedret testbarhed :
- Det fremmer brugen af domæneobjekter med veldefinerede grænser og adfærd, hvilket gør det nemmere at skrive bedre og fokuserede test, der verificerer domænelogikkens rigtighed.
- Ved at designe softwaresystemer med testbarhed i tankerne kan teams sikre, at ændringer i kodebasen er sikre og forudsigelige, hvilket reducerer risikoen for at introducere regressioner eller utilsigtede bivirkninger.
- Support til komplekse forretningsregler :
- Det giver mønstre og teknikker til modellering og implementering af komplekse forretningsregler og arbejdsgange inden for domænemodellen.
- Ved at repræsentere forretningsregler eksplicit i domænemodellen kan teams sikre, at softwaren nøjagtigt afspejler forretningsdomænets forviklinger og håndhæver domænespecifikke begrænsninger og krav.
- Tilpasning til forretningsmål :
- I sidste ende sigter det mod at tilpasse softwareudviklingsindsatsen med virksomhedens strategiske mål og målsætninger. Ved at fokusere på at forstå og modellere problemdomænet kan teams levere softwareløsninger, der direkte understøtter forretningsmål, driver innovation og skaber værdi for interessenter og slutbrugere.
Udfordringer ved domænedrevet design (DDD)
- Kompleksitet :
- DDD kan introducere kompleksitet, især i store og komplekse domæner.
- Nøjagtig modellering af indviklede forretningsdomæner kræver en dyb forståelse af domænet og kan involvere håndtering af tvetydighed og usikkerhed. At håndtere denne kompleksitet effektivt kræver omhyggelig planlægning, samarbejde og ekspertise.
- Allestedsnærværende sprogadoption :
- At etablere og vedligeholde et allestedsnærværende sprog – et fælles ordforråd, der nøjagtigt repræsenterer domænekoncepter – kan være udfordrende. Det kræver samarbejde mellem udviklere og domæneeksperter for at identificere og blive enige om domænets termer og betydninger.
- At opnå konsensus om det allestedsnærværende sprog kan kræve at overvinde kommunikationsbarrierer og forene forskelle i terminologi og perspektiver.
- Bounded Context Alignment :
- I store og komplekse domæner kan forskellige dele af domænet have adskilte modeller og afgrænsede sammenhænge. At tilpasse disse afgrænsede sammenhænge og sikre sammenhæng mellem dem kan være udfordrende.
- Det kræver klar kommunikation, samarbejde og koordinering mellem teams, der arbejder på forskellige dele af domænet for at undgå uoverensstemmelser og konflikter.
- Teknisk kompleksitet :
- Effektiv implementering af DDD-principper og -mønstre kan kræve, at man vedtager nye teknologier, rammer og arkitektoniske tilgange. Integrering af DDD med eksisterende systemer eller ældre kodebaser kan være kompleks og kan kræve omstrukturering eller redesign af eksisterende kode for at tilpasse sig DDD-principperne.
- Tekniske udfordringer såsom ydeevne, skalerbarhed og vedligeholdelighed skal behandles omhyggeligt for at sikre succes med DDD-adoption.
- Modstand mod forandring :
- Introduktion af DDD kan støde på modstand fra teammedlemmer, der er vant til traditionelle udviklingstilgange, eller som opfatter DDD som alt for kompleks eller upraktisk.
- At overvinde modstand mod forandring kræver effektiv kommunikation, uddannelse og lederskab for at demonstrere fordelene ved DDD og adressere bekymringer og skepsis.
- Over-engineering :
- Der er risiko for over-engineering ved anvendelse af DDD, hvor teams fokuserer for meget på at modellere komplekse domænekoncepter og introducere unødvendige abstraktioner eller kompleksitet. At finde den rette balance mellem enkelhed og udtryksfuldhed er afgørende for at undgå at overkomplicere design og implementering.
Use-Cases of Domain-Driven Design (DDD)
- Finans og bank :
- I finanssektoren kan DDD bruges til at modellere komplekse finansielle instrumenter, transaktioner og regulatoriske krav. Ved nøjagtigt at repræsentere domænekoncepter som konti, transaktioner og porteføljer hjælper DDD med at sikre integriteten og konsistensen af finansielle systemer. Det muliggør også bedre risikostyring, compliance og rapportering.
- E-handel og detailhandel :
- E-handelsplatforme beskæftiger sig ofte med komplekse domænekoncepter såsom produktkataloger, lagerstyring, priser og kundeordrer. DDD kan hjælpe med at modellere disse koncepter effektivt, hvilket muliggør funktioner såsom personlige anbefalinger, dynamisk prissætning og strømlinet ordrebehandling.
- Sundhedspleje og Biovidenskab :
- I sundhedsvæsenet kan DDD bruges til at modellere patientjournaler, medicinske diagnoser, behandlingsplaner og arbejdsgange i sundhedsvæsenet. Ved nøjagtigt at repræsentere domænekoncepter som patientdemografi, medicinske historier og kliniske protokoller muliggør DDD udviklingen af robuste elektroniske patientjournalsystemer (EPJ), medicinske billedbehandlingsplatforme og telemedicinske applikationer.
- Forsikring :
- Forsikringsselskaber administrerer forskellige produkter, policer, krav og forsikringsprocesser. DDD kan hjælpe med at modellere disse komplekse domænekoncepter, hvilket muliggør funktioner som politikstyring, skadebehandling, risikovurdering og aktuaranalyse.
- Ejendoms- og ejendomsadministration :
- Ejendoms- og ejendomsadministration involverer håndtering af forskellige ejendomme, lejemål, lejere, vedligeholdelsesanmodninger og finansielle transaktioner. DDD kan hjælpe med at modellere disse domænekoncepter effektivt, hvilket muliggør funktioner såsom ejendomsfortegnelser, leasingadministration, lejerportaler og aktivsporing.
Eksempel på domænedrevet design (DDD) fra den virkelige verden
Problemformulering
Lad os sige, vi er ved at udvikle en ride-hailing-applikation kaldet RideX. Systemet giver brugerne mulighed for at anmode om kørsel, chauffører at acceptere kørselsanmodninger og letter koordineringen af ture mellem brugere og chauffører.
opdatering fra join sql
Allestedsnærværende sprog
- Bruger : Refererer til personer, der anmoder om forlystelser via RideX-platformen.
- Chauffør : Refererer til personer, der leverer ture til brugere via RideX-platformen.
- Anmodning om køretur : Repræsenterer en brugers anmodning om en tur, der specificerer detaljer såsom afhentningssted, destination og kørepræferencer.
- Ride : Repræsenterer en enkelt forekomst af en tur, inklusive detaljer såsom afhentnings- og afleveringssteder, billetpris og varighed.
- Kørselsstatus : Repræsenterer den aktuelle status for en tur, såsom Anmodet, Accepteret, Igangværende eller Afsluttet.
Afgrænsede sammenhænge
- Ride Management kontekst : Ansvarlig for styring af tures livscyklus, herunder køreanmodninger, køretildelinger til chauffører og kørestatusopdateringer.
- Brugerstyringskontekst : Håndterer brugergodkendelse, registrering og brugerspecifikke funktioner såsom kørehistorik og betalingsmetoder.
- Driverstyringskontekst : Administrerer chaufførgodkendelse, registrering, tilgængelighedsstatus og førerspecifikke funktioner såsom indtjening og vurderinger.
Enheder og værdiobjekter
- Brugerenhed : Repræsenterer en registreret bruger af RideX-platformen med egenskaber som bruger-id, e-mail, adgangskode og betalingsoplysninger.
- Driver enhed : Repræsenterer en registreret chauffør på RideX-platformen med egenskaber som fører-id, køretøjsoplysninger og førerstatus.
- Entitet for turanmodning : Repræsenterer en brugers anmodning om en tur, herunder egenskaber som anmodnings-id, afhentningssted, destination og præferencer for tur.
- Ride Entity : Repræsenterer en enkelt forekomst af en tur, inklusive egenskaber som køre-id, afhentnings- og afleveringssteder, billetpris og kørestatus.
- Placering Værdi Objekt : Repræsenterer en geografisk placering med egenskaber som breddegrad og længdegrad.
Aggregater
- Ride Aggregate : Består af Ride Entity som den samlede rod sammen med relaterede enheder såsom Ride Request, User og Driver entiteter. Ride Aggregate indkapsler logikken til styring af en turs livscyklus, herunder håndtering af køreanmodninger, tildeling af chauffører og opdatering af kørestatus.
Depot
- Ride Repository : Giver metoder til forespørgsel og lagring af kørerelaterede entiteter, såsom hentning af køreoplysninger, opdatering af kørestatus og lagring af kørerelaterede data i databasen.
Tjenester
- Ride Tildeling Service : Ansvarlig for at tildele tilgængelige chauffører til køreanmodninger baseret på faktorer som chaufførtilgængelighed, nærhed til afhentningssted og brugerpræferencer.
- Betalingsservice : Håndterer betalingsbehandling for gennemførte ture, beregning af takster, behandling af betalinger og opdatering af bruger- og chaufførbetalingsoplysninger.
Domænehændelser
- RideRequestedEvent : Repræsenterer en hændelse, der udløses, når en bruger anmoder om en tur, der indeholder oplysninger såsom oplysninger om køreanmodning og bruger-id.
- RideAcceptedEvent : Repræsenterer en hændelse, der udløses, når en chauffør accepterer en køreanmodning, der indeholder oplysninger såsom køre-id, fører-id og afhentningssted.
Eksempel Scenario
- Bruger anmoder om en tur : En bruger anmoder om en tur ved at angive deres afhentningssted, destination og kørepræferencer. RideX opretter en ny rideanmodningsentitet og udløser en RideRequestedEvent.
- Chauffør accepterer en tur : En chauffør accepterer en køreanmodning fra RideX-platformen. RideX opdaterer kørestatus til Accepteret, tildeler føreren til turen og udløser en RideAcceptedEvent.
- Ride i gang : Brugeren og chaufføren koordinerer turen, hvor kørestatussen skifter fra Accepteret til Igangværende, når chaufføren når frem til afhentningsstedet.
- Kørsel afslutning : Efter at have nået destinationen, opdateres kørestatus til Fuldført. RideX beregner billetprisen, behandler betalingen og opdaterer bruger- og chaufførbetalingsoplysningerne i overensstemmelse hermed.