Domain-Driven Design (DDD) är ett tillvägagångssätt för mjukvaruutveckling som fokuserar på att förstå och modellera den problemdomän inom vilken ett mjukvarusystem verkar. Det betonar vikten av att ha ett nära samarbete med domänexperter för att utveckla en djup förståelse för domänens krångligheter och komplexitet. DDD tillhandahåller en uppsättning principer, mönster och metoder för att hjälpa utvecklare att effektivt fånga och uttrycka domänkoncept i sina programvarudesigner.
fjädermoduler
Viktiga ämnen för den domändrivna designen (DDD)
- Vad är Domain-Driven Design (DDD)?
- Vikten av domänkunskap
- Strategisk design i domändriven design (DDD)
- Tactical Design Patterns in Domain-Driven Design (DDD)
- Fördelar med domändriven design (DDD)
- Utmaningar med domändriven design (DDD)
- Användningsfall av domändriven design (DDD)
- Verkliga exempel på domändriven design (DDD)
Vad är Domain-Driven Design (DDD)?
Domän
Det hänvisar till ämnesområdet eller problemområdet som mjukvarusystemet byggs för att hantera. Den omfattar verkliga koncept, regler och processer som programvaran är avsedd att modellera eller stödja. Till exempel, i en bankapplikation innehåller domänen begrepp som konton, transaktioner, kunder och regler relaterade till bankverksamhet.
Driven
Driven innebär att utformningen av mjukvarusystemet styrs eller påverkas av domänens egenskaper och krav. Med andra ord baseras designbesluten på en djup förståelse av domänen, snarare än att de enbart drivs av tekniska överväganden eller implementeringsdetaljer.
Design
Design hänvisar till processen att skapa en plan eller ritning för mjukvarusystemet. Detta inkluderar beslut om hur systemet ska vara uppbyggt, hur olika komponenter ska interagera och hur systemet ska uppfylla sina funktionell och icke-funktionell krav. Inom ramen för domändriven design ligger fokus på att designa programvaran på ett sätt som exakt återspeglar domänens struktur och beteende.
Domain-Driven Design är ett koncept som introducerats av en programmerare Eric Evans 2004 i sin bok Domändriven design: Ta itu med komplexitet i programvarans hjärta
Vikten av domänkunskap
Anta att vi har designat mjukvara med all den senaste tekniska stacken och infrastrukturen och vår mjukvarudesignarkitektur är fantastisk, men när vi släpper den här programvaran på marknaden är det slutanvändaren som bestämmer om vårt system är bra eller inte. Också om systemet inte löser affärsbehov, är det inte till någon nytta för någon. Oavsett hur vacker den ser ut eller hur väl arkitekturen dess infrastruktur är.
Enligt Eric Evans , När vi utvecklar mjukvara bör vårt fokus inte i första hand ligga på teknik, utan snarare på affärer. Kom ihåg,
Det är inte kundens uppgift att veta vad de vill ha – Steve Jobs
Strategisk design i domändriven design (DDD)
Strategic Design in Domain-Driven Design (DDD) fokuserar på att definiera den övergripande arkitekturen och strukturen för ett mjukvarusystem på ett sätt som ligger i linje med problemdomänen. Den tar upp problem på hög nivå som hur man organiserar domänkoncept, hur man delar upp systemet i hanterbara delar och hur man skapar tydliga gränser mellan olika komponenter.
symmetrisk skillnad
Låt oss se några nyckelbegrepp inom Strategic Design in Domain-Driven Design (DDD)
1. Avgränsade sammanhang
- En avgränsad kontext representerar ett specifikt område inom den övergripande problemdomänen där en viss modell eller språk tillämpas konsekvent.
- Olika delar av ett system kan ha olika betydelser för samma termer, och en Bounded Context definierar explicita gränser inom vilka dessa termer har specifika betydelser.
- Detta gör att teamen kan utveckla modeller som är skräddarsydda för specifika sammanhang utan att skapa förvirring eller inkonsekvenser.
- Bounded Contexts hjälper till att hantera komplexitet genom att bryta ner en stor, komplex domän i mindre, mer hanterbara delar.
2. Kontextkartläggning
- Kontextkartläggning är processen att definiera relationer och interaktioner mellan olika Bounded Contexts.
- Det handlar om att identifiera områden med överlappning eller integration mellan sammanhang och upprätta kommunikationskanaler och avtal mellan dem.
- Kontextkartläggning hjälper till att säkerställa att olika delar av systemet kan samarbeta effektivt samtidigt som tydliga gränser mellan dem bibehålls.
- Det finns olika mönster och tekniker för kontextkartläggning, såsom partnerskap, delad kärna och kund-leverantör.
3. Strategiska mönster
- Strategiska mönster är allmänna riktlinjer eller principer för att organisera arkitekturen för ett mjukvarusystem på ett sätt som överensstämmer med problemdomänen.
- Dessa mönster hjälper till att hantera vanliga utmaningar vid design av komplexa system och ger beprövade metoder för att strukturera systemet effektivt.
- Exempel på strategiska mönster inkluderar aggregat, domänhändelser och anti-korruptionslager.
- Dessa mönster tillhandahåller lösningar på återkommande problem inom domändriven design och hjälper till att säkerställa att systemets arkitektur återspeglar de underliggande domänkoncepten korrekt.
4. Delad kärna
- Shared Kernel är ett strategiskt mönster som involverar identifiering av områden med gemensamhet mellan olika Bounded Contexts och upprättande av en delad delmängd av domänmodellen som används av flera sammanhang.
- Denna delade delmängd, eller kärnan, hjälper till att underlätta samarbete och integration mellan sammanhang samtidigt som det tillåter varje sammanhang att behålla sin egen distinkta modell.
- Shared Kernel bör användas med omtanke, eftersom den introducerar beroenden mellan sammanhang och kan leda till koppling om den inte hanteras noggrant.
5. Anti-Corruption Layer (ACL)
- Anti-korruptionsskiktet är ett annat strategiskt mönster som hjälper till att skydda ett system från påverkan av externa eller äldre system som använder olika modeller eller språk.
- En ACL fungerar som ett översättningslager mellan det externa systemet och kärndomänmodellen, och transformerar data och meddelanden efter behov för att säkerställa kompatibilitet.
- Detta gör att kärndomänmodellen förblir ren och fokuserad på problemdomänen, samtidigt som den fortfarande integreras med externa system vid behov.
6. Allestädes närvarande språk
Ubiquitous Language hänvisar till ett delat ordförråd eller språk som används konsekvent och universellt för alla intressenter som är involverade i utvecklingen av ett mjukvarusystem. Detta språk består av termer, fraser och begrepp som korrekt representerar domänkunskap och begrepp.
Några av nyckelprinciperna för Ubiquitous Language är:
- Delad förståelse : Det primära målet med Ubiquitous Language är att skapa en delad förståelse av problemdomänen bland alla medlemmar i utvecklingsteamet, inklusive utvecklare, domänexperter, affärsanalytiker och intressenter. Genom att använda ett gemensamt språk kan alla inblandade kommunicera mer effektivt och korrekt förmedla domänkoncept och krav.
- Konsekvens och tydlighet : Ubiquitous Language främjar konsekvens och tydlighet i kommunikationen genom att använda exakt och entydig terminologi. Varje term eller fras i språket bör ha en tydlig och överenskommen betydelse,
- Anpassning till affärsidéer : Språket som används i DDD bör stämma överens med terminologin och begreppen som används inom affärsdomänen. Det bör återspegla hur domänexperter tänker och pratar om problemdomänen, vilket säkerställer att programvaran korrekt representerar verkliga koncept och processer.
- Evolutionär natur : Ubiquitous Language är inte statiskt utan utvecklas över tid i takt med att teamet får en djupare förståelse för domänen och när kraven förändras. Det bör anpassas för att återspegla nya insikter, upptäckter eller förändringar i affärsprioriteringar, för att säkerställa att språket förblir relevant och uppdaterat under hela utvecklingsprocessen.
Tactical Design Patterns in Domain-Driven Design (DDD)
I Domain-Driven Design (DDD) är taktiska designmönster specifika strategier eller tekniker som används för att strukturera och organisera domänmodellen i ett mjukvarusystem. Dessa mönster hjälper utvecklare att effektivt fånga domänens komplexitet, samtidigt som de främjar underhållsbarhet, flexibilitet och skalbarhet.
Låt oss se några av de viktigaste taktiska designmönstren i DDD:
1. Entitet
En enhet är ett domänobjekt som har en distinkt identitet och livscykel. Entiteter kännetecknas av sina unika identifierare och föränderliga tillstånd. De kapslar in beteende och data relaterat till ett specifikt koncept inom domänen.
Till exempel, i en bankapplikation, en
BankAccount>
Entitet kan ha egenskaper som kontonummer, saldo och ägare, tillsammans med metoder för att sätta in, ta ut eller överföra pengar.
2. Värdeobjekt
Ett värdeobjekt är ett domänobjekt som representerar ett begreppsmässigt oföränderligt värde. Till skillnad från entiteter har värdeobjekt inte en distinkt identitet och används vanligtvis för att representera attribut eller egenskaper hos entiteter. Värdeobjekt är likvärdighetsjämförbara utifrån deras egenskaper, snarare än deras identitet.
Till exempel, en
Money>
värdeobjekt kan representera en specifik mängd valuta, inkapslande egenskaper som valutatyp och belopp.
3. Aggregera
- Ett aggregat är ett kluster av domänobjekt som behandlas som en enda enhet i syfte att säkerställa datakonsistens och transaktionsintegritet.
- Aggregat består av en eller flera entiteter och värdeobjekt, med en enhet betecknad som den aggregerade roten.
- Den aggregerade roten fungerar som ingångspunkt för åtkomst till och modifiering av aggregatets interna tillstånd.
- Aggregat upprätthåller konsistensgränser inom domänmodellen, vilket säkerställer att ändringar av relaterade objekt görs atomärt.
Till exempel, i ett e-handelssystem, en
Order>
aggregat kan bestå av enheter somOrderItem>
ochCustomer>
, medOrder>
enhet som fungerar som den aggregerade roten.
4. Förvar
- Ett arkiv är en mekanism för att abstrahera dataåtkomst och persistenslogik från domänmodellen.
- Repositories tillhandahåller ett standardiserat gränssnitt för att fråga och lagra domänobjekt, dölja detaljerna om hur data hämtas eller lagras. Lagrar kapslar in logiken för översättning mellan domänobjekt och underliggande datalagringsmekanismer, såsom databaser eller externa tjänster.
- Genom att frikoppla domänmodellen från problem med dataåtkomst möjliggör arkiven större flexibilitet och underhållsbarhet.
Till exempel, en
CustomerRepository>
kan tillhandahålla metoder för sökning och lagringCustomer>
enheter.
5. Fabrik
- En fabrik är en skapande mönster används för att kapsla in logiken för att skapa instanser av komplexa domänobjekt. Fabriker abstraherar processen för objektinstansiering, vilket gör att kunder kan skapa objekt utan att behöva känna till detaljerna i deras konstruktion.
- Fabriker är särskilt användbara för att skapa objekt som kräver komplex initieringslogik eller involverar flera steg.
Till exempel, en
ProductFactory>
kan vara ansvarig för att skapa instanser avProduct>
enheter med standardkonfigurationer.
6. Service
- En tjänst är ett domänobjekt som representerar ett beteende eller en operation som inte naturligt tillhör någon specifik enhet eller värdeobjekt.
- Tjänster kapslar in domänlogik som verkar på flera objekt eller orkestrerar interaktioner mellan objekt.
- Tjänster är vanligtvis statslösa och fokuserar på att utföra specifika uppgifter eller tillämpa domänregler.
Till exempel en
OrderService>
kan tillhandahålla metoder för att behandla beställningar, tillämpa rabatter och beräkna fraktkostnader.
Fördelar med domändriven design (DDD)
- Delad förståelse :
- Det uppmuntrar samarbete mellan domänexperter, utvecklare och intressenter.
- Genom att uppmuntra en delad förståelse av problemdomänen genom det allestädes närvarande språket, kan team kommunicera mer effektivt och säkerställa att programvaran exakt återspeglar verksamhetens behov och krav.
- Fokusera på kärndomänen :
- Det hjälper team att identifiera och prioritera applikationens kärndomän – de områden i systemet som ger mest värde för verksamheten. Genom att fokusera utvecklingsinsatser på kärndomänen kan team leverera funktionalitet som direkt adresserar affärsmål och som skiljer programvaran från konkurrenterna.
- Motståndskraft mot förändring :
- Den betonar att designa mjukvarusystem som är motståndskraftiga mot förändring genom att modellera domänen på ett sätt som återspeglar problemdomänens inneboende komplexitet och osäkerhet.
- Genom att ta till sig förändring som en naturlig del av mjukvaruutveckling kan team reagera mer effektivt på förändrade affärsbehov och marknadsförhållanden.
- Tydlig separation av bekymmer :
- DDD uppmuntrar en tydlig åtskillnad av problem mellan domänlogik, infrastrukturproblem och användargränssnitt. Genom att isolera domänlogik från tekniska detaljer och infrastrukturproblem kan team upprätthålla en ren och fokuserad domänmodell som är oberoende av specifika implementeringsdetaljer eller tekniska val.
- Förbättrad testbarhet :
- Det främjar användningen av domänobjekt med väldefinierade gränser och beteenden, vilket gör det lättare att skriva bättre och fokuserade tester som verifierar riktigheten av domänlogiken.
- Genom att designa mjukvarusystem med testbarhet i åtanke kan team säkerställa att ändringar i kodbasen är säkra och förutsägbara, vilket minskar risken för att införa regressioner eller oavsiktliga biverkningar.
- Stöd för komplexa affärsregler :
- Den tillhandahåller mönster och tekniker för att modellera och implementera komplexa affärsregler och arbetsflöden inom domänmodellen.
- Genom att representera affärsregler explicit i domänmodellen kan teamen säkerställa att programvaran exakt återspeglar affärsdomänens krångligheter och upprätthåller domänspecifika begränsningar och krav.
- Anpassning till affärsmål :
- I slutändan syftar det till att anpassa insatser för mjukvaruutveckling med de strategiska målen och målen för verksamheten. Genom att fokusera på att förstå och modellera problemdomänen kan team leverera mjukvarulösningar som direkt stöder affärsmål, driver innovation och skapar värde för intressenter och slutanvändare.
Utmaningar med domändriven design (DDD)
- Komplexitet :
- DDD kan introducera komplexitet, särskilt i stora och komplexa domäner.
- Att modellera intrikata affärsdomäner korrekt kräver en djup förståelse av domänen och kan innebära att man hanterar oklarheter och osäkerhet. Att hantera denna komplexitet effektivt kräver noggrann planering, samarbete och expertis.
- Ubiquitous Language Adoption :
- Att etablera och upprätthålla ett allestädes närvarande språk – ett delat ordförråd som korrekt representerar domänkoncept – kan vara utmanande. Det kräver samarbete mellan utvecklare och domänexperter för att identifiera och komma överens om domäntermer och betydelser.
- För att uppnå konsensus om det allestädes närvarande språket kan det krävas att man övervinner kommunikationsbarriärer och förenar skillnader i terminologi och perspektiv.
- Bounded Context Alignment :
- I stora och komplexa domäner kan olika delar av domänen ha distinkta modeller och avgränsade sammanhang. Att anpassa dessa avgränsade sammanhang och säkerställa överensstämmelse mellan dem kan vara utmanande.
- Det kräver tydlig kommunikation, samarbete och samordning mellan team som arbetar på olika delar av domänen för att undvika inkonsekvenser och konflikter.
- Teknisk komplexitet :
- Att implementera DDD-principer och -mönster effektivt kan kräva att nya teknologier, ramverk och arkitektoniska tillvägagångssätt antas. Att integrera DDD med befintliga system eller äldre kodbaser kan vara komplext och kan kräva omstrukturering eller omdesign av befintlig kod för att anpassas till DDD-principerna.
- Tekniska utmaningar som prestanda, skalbarhet och underhållsbarhet måste hanteras noggrant för att säkerställa framgången för DDD-anpassningen.
- Motstånd mot förändring :
- Att introducera DDD kan stöta på motstånd från gruppmedlemmar som är vana vid traditionella utvecklingsmetoder eller som uppfattar DDD som alltför komplext eller opraktiskt.
- Att övervinna motstånd mot förändring kräver effektiv kommunikation, utbildning och ledarskap för att visa fördelarna med DDD och ta itu med oro och skepsis.
- Överteknik :
- Det finns en risk för överkonstruktion när man tillämpar DDD, där team fokuserar för mycket på att modellera komplexa domänkoncept och introducera onödiga abstraktioner eller komplexitet. Att hitta rätt balans mellan enkelhet och uttrycksfullhet är avgörande för att undvika att överkomplicera design och implementering.
Användningsfall av domändriven design (DDD)
- Bank och finans :
- Inom finanssektorn kan DDD användas för att modellera komplexa finansiella instrument, transaktioner och regulatoriska krav. Genom att korrekt representera domänkoncept som konton, transaktioner och portföljer hjälper DDD till att säkerställa integriteten och konsekvensen hos finansiella system. Det möjliggör också bättre riskhantering, efterlevnad och rapportering.
- E-handel och detaljhandel :
- E-handelsplattformar hanterar ofta komplexa domänkoncept som produktkataloger, lagerhantering, prissättning och kundorder. DDD kan hjälpa till att modellera dessa koncept effektivt, vilket möjliggör funktioner som personliga rekommendationer, dynamisk prissättning och strömlinjeformad orderhantering.
- Sjukvård och Livsvetenskap :
- Inom vården kan DDD användas för att modellera patientjournaler, medicinska diagnoser, behandlingsplaner och arbetsflöden inom sjukvården. Genom att korrekt representera domänkoncept som patientdemografi, medicinsk historia och kliniska protokoll möjliggör DDD utvecklingen av robusta elektroniska journalsystem (EHR), medicinska bildbehandlingsplattformar och telemedicinapplikationer.
- Försäkring :
- Försäkringsbolag hanterar olika produkter, försäkringar, anspråk och försäkringsprocesser. DDD kan hjälpa till att modellera dessa komplexa domänkoncept, vilket möjliggör funktioner som policyhantering, skadehantering, riskbedömning och försäkringsteknisk analys.
- Fastighets- och fastighetsförvaltning :
- Fastighets- och fastighetsförvaltning involverar hantering av olika fastigheter, hyresavtal, hyresgäster, underhållsförfrågningar och finansiella transaktioner. DDD kan hjälpa till att modellera dessa domänkoncept på ett effektivt sätt, vilket möjliggör funktioner som fastighetslistor, hyreskontrakt, hyresgästportaler och tillgångsspårning.
Verkliga exempel på domändriven design (DDD)
Problembeskrivning
Låt oss säga att vi utvecklar en applikation som kallas RideX. Systemet tillåter användare att begära åk, förare att acceptera åkförfrågningar och underlättar samordningen av åk mellan användare och förare.
metoder i java
Allestädes närvarande språk
- Användare : Avser individer som begär resor via RideX-plattformen.
- Förare : Avser personer som tillhandahåller turer till användare via RideX-plattformen.
- Ride begäran : Representerar en användares begäran om en resa, och anger detaljer som upphämtningsplats, destination och åkpreferenser.
- Rida : Representerar en enskild instans av en resa, inklusive detaljer som hämtnings- och avlämningsplatser, pris och varaktighet.
- Åkstatus : Representerar den aktuella statusen för en resa, till exempel Begärd, Godkänd, Pågår eller Slutförd.
Avgränsade sammanhang
- Ride Management sammanhang : Ansvarig för att hantera livscykeln för åk, inklusive åkförfrågningar, åktilldelningar till förare och åkstatusuppdateringar.
- Användarhanteringskontext : Hanterar användarautentisering, registrering och användarspecifika funktioner som åkhistorik och betalningsmetoder.
- Kontext för drivrutinshantering : Hanterar förarautentisering, registrering, tillgänglighetsstatus och förarspecifika funktioner som intäkter och betyg.
Entiteter och värdeobjekt
- Användarenhet : Representerar en registrerad användare av RideX-plattformen, med egenskaper som användar-ID, e-post, lösenord och betalningsinformation.
- Driver Entity : Representerar en registrerad förare på RideX-plattformen, med egenskaper som förar-ID, fordonsinformation och förarstatus.
- Entitet för åkbeställning : Representerar en användares begäran om en resa, inklusive egenskaper som begäran-ID, hämtningsplats, destination och färdpreferenser.
- Ride Entity : Representerar en enskild instans av en resa, inklusive egenskaper som färd-ID, hämtnings- och avlämningsplatser, biljettpris och färdstatus.
- Plats Värde Objekt : Representerar en geografisk plats, med egenskaper som latitud och longitud.
Aggregat
- Ride Aggregate : Består av Ride Entity som den aggregerade roten, tillsammans med relaterade enheter som Ride Request, User och Driver entiteter. Ride Aggregate kapslar in logiken för att hantera livscykeln för en åktur, inklusive hantering av åkförfrågningar, tilldelning av förare och uppdatering av åkstatus.
Förvar
- Ride Repository : Tillhandahåller metoder för att fråga och lagra åkrelaterade enheter, som att hämta åkdetaljer, uppdatera åkstatus och lagra åkrelaterade data i databasen.
Tjänster
- Åkuppdragstjänst : Ansvarig för att tilldela tillgängliga förare till åkförfrågningar baserat på faktorer som förarens tillgänglighet, närhet till upphämtningsplats och användarpreferenser.
- Betaltjänst : Hanterar betalningshantering för genomförda turer, beräknar priser, behandlar betalningar och uppdaterar användar- och förarbetalningsinformation.
Domänhändelser
- RideRequestedEvent : Representerar en händelse som utlöses när en användare begär en åktur, som innehåller information som information om åkbegäran och användar-ID.
- RideAcceptedEvent : Representerar en händelse som utlöses när en förare accepterar en färdbegäran, som innehåller information som färd-ID, förar-ID och upphämtningsplats.
Exempelscenario
- Användare som begär skjuts : En användare begär skjuts genom att ange sin hämtningsplats, destination och färdpreferenser. RideX skapar en ny åkbegäran-enhet och utlöser en RideRequestedEvent.
- Förare accepterar en åktur : En förare accepterar en åkbegäran från RideX-plattformen. RideX uppdaterar åkstatusen till Accepted, tilldelar föraren åkturen och utlöser en RideAcceptedEvent.
- Åk på gång : Användaren och föraren samordnar åkturen, med åkstatusen övergår från Godkänd till Pågående när föraren når upphämtningsplatsen.
- Avslutad färd : Efter att ha nått destinationen uppdateras färdstatusen till Slutförd. RideX beräknar priset, behandlar betalningen och uppdaterar användarens och förarens betalningsinformation därefter.