Analysera ett program och identifiera nedbrytningsgränser

Slutförd

För att flytta programmet till en mikrotjänstarkitektur måste Fabrikam utvärdera sitt aktuella program och fastställa omfånget och gränsen för varje mikrotjänst. För den här utvärderingen kommer de att använda ramverket domändriven design (DDD). Nu ska vi se hur de tillämpar det på sitt program.

Not

Den här artikeln visar inte en fullständig och omfattande domänanalys. Vi höll avsiktligt exemplet kort för att illustrera huvudpunkterna. Mer information om DDD finns i avsnittet "Läs mer" i sammanfattningen i slutet av den här modulen.

Vad är domändriven design?

DDD är en metod för systemdesign som ursprungligen introducerades av Erik Evans i 2005 års bok Domain-Driven Design: Tackling Complexity in the Heart of Software. Den här metoden innehåller tre viktiga element:

  • Fokusera på kärndomänen och domänlogik.
  • Strukturera designen på en modell av domänen.
  • Driva iterativt samarbete mellan de tekniska teamen och affärspartners för att ständigt förbättra systemet.

DDD tillhandahåller ett ramverk som kan ge dig det mesta av vägen till en uppsättning väldesignade mikrotjänster. Det har två distinkta faser, strategiska och taktiska. I strategisk DDD definierar du systemets storskaliga struktur. Strategisk DDD hjälper till att säkerställa att din arkitektur fortsätter att fokusera på affärsfunktioner. Taktisk DDD innehåller en uppsättning designmönster som du kan använda för att skapa domänmodellen. Dessa mönster omfattar entiteter, aggregeringar och domäntjänster. Dessa taktiska mönster hjälper dig att utforma mikrotjänster som är löst kopplade och sammanhängande.

Diagram över stegen för domändriven design.

Under den strategiska fasen av DDD mappar du ut affärsdomänen och definierar avgränsade kontexter för dina domänmodeller. Taktisk DDD är när du definierar dina domänmodeller med större precision. De taktiska mönstren tillämpas inom en enda begränsad kontext. I en mikrotjänstarkitektur är vi intresserade av entitets- och aggregerade mönster. Genom att använda dessa mönster kan vi identifiera naturliga gränser för tjänsterna i vårt program. Som en allmän princip bör en mikrotjänst inte vara mindre än en aggregering och inte större än en begränsad kontext.

På hög nivå kan du dela upp den här processen i fyra steg:

  1. Analysera affärsdomänen för att förstå programmets funktionskrav. Utdata från det här steget är en informell beskrivning av domänen, som kan förfinas till en mer formell uppsättning domänmodeller.
  2. Definiera domänens avgränsade kontexter. Varje begränsad kontext innehåller en domänmodell som representerar en viss underdomän för det större programmet.
  3. I en begränsad kontext använder du taktiska DDD-mönster för att definiera entiteter, aggregeringar och domäntjänster.
  4. Identifiera mikrotjänsterna i ditt program med hjälp av resultaten från föregående steg.

Låt oss ta en närmare titt på vad som händer i vart och ett av de här stegen.

Analysera affärsdomänen

DDD börjar med att modellera företagsdomänen och skapa en domänmodell. Domänmodellen är en abstrakt modell av företagsdomänen. Förädlar och organiserar domänkunskap, och det ger ett gemensamt språk för utvecklare och domänexperter.

Börja med att mappa alla affärsfunktioner och deras anslutningar. Den här analysen är ett samarbete som involverar domänexperter, programvaruarkitekter och andra intressenter. Du behöver inte använda någon särskild formalism. Skissa ett diagram eller rita ut det på en whiteboard.

När du fyller i diagrammet kan du börja identifiera diskreta underdomäner. Vilka funktioner är nära relaterade? Vilka funktioner är centrala för verksamheten och vilka tillhandahåller kompletterande tjänster? Vad är beroendediagrammet? Under den här inledande fasen bryr du dig inte om teknik eller implementeringsinformation. Med detta sagt bör du notera den plats där programmet behöver integreras med externa system, till exempel CRM, betalningsbearbetning eller faktureringssystem.

diagram över affärsdomänen.

Definiera avgränsade kontexter

Domänmodellen innehåller representationer av verkliga saker i världen som användare, drönare och paket. Men det betyder inte att alla delar av systemet behöver använda samma representationer för samma saker.

Till exempel måste undersystem som hanterar drönarreparation och förutsägelseanalys representera många fysiska egenskaper hos drönare. Dessa egenskaper omfattar underhållshistorik, körsträcka, ålder, modellnummer och prestandainformation. Men när det är dags att schemalägga en leverans bryr vi oss inte om dessa saker. Undersystemet för schemaläggning behöver bara veta om en drönare är tillgänglig och den uppskattade ankomsttiden (ETA) för upphämtning och leverans.

Om vi försöker skapa en enda modell för båda dessa undersystem är det mer komplext än vi behöver. Det blir också svårare för modellen att utvecklas över tid, eftersom alla ändringar måste uppfylla flera team som arbetar med separata undersystem. Det är ofta bättre att utforma separata modeller som representerar samma verkliga entitet (i det här fallet en drönare) i två olika sammanhang. Varje modell innehåller endast de funktioner och attribut som är relevanta i dess specifika kontext.

Den här metoden är den metod där DDD-begreppet avgränsade kontexter spelar in. En begränsad kontext är helt enkelt gränsen inom en domän där en viss domänmodell gäller. Om vi tittar på föregående diagram kan vi gruppera funktioner beroende på om olika funktioner delar en enda domänmodell.

Diagram över de avgränsade kontexterna för drönarprogrammet.

Definiera entiteter, aggregeringar och tjänster

Taktisk DDD är när du definierar dina domänmodeller med större precision. De taktiska mönstren tillämpas inom en enda begränsad kontext. I en mikrotjänstarkitektur är vi intresserade av entitets- och aggregerade mönster. Genom att använda dessa mönster kan vi identifiera naturliga gränser för tjänsterna i vårt program. Som en allmän princip bör en mikrotjänst inte vara mindre än en aggregering och inte större än en begränsad kontext.

Det finns flera taktiska DDD-mönster att tänka på:

  • Entiteter: En entitet är ett objekt med en unik identitet som bevaras över tid. I ett bankprogram är till exempel kunder och konton entiteter.
  • Värdeobjekt: Ett värdeobjekt har ingen identitet. Värdena för dess attribut definierar det och det är oföränderligt. Vanliga exempel på värdeobjekt är färger, datum och tider samt valutavärden.
  • Aggregeringar: En aggregering definierar en konsekvensgräns runt en eller flera entiteter. Syftet med en aggregering är att modellera transaktionella invarianter. Saker i verkligheten har komplexa nät av relationer. Kunder skapar beställningar, beställningar innehåller produkter, produkter har leverantörer och så vidare. Hur garanterar programmet konsekvens om programmet ändrar flera relaterade objekt? Hur håller vi reda på invarianter och framtvingar dem?
  • Domän- och programtjänster: I DDD-terminologi är en tjänst ett objekt som implementerar viss logik utan att ha något tillstånd. Evans skiljer mellan domäntjänster, som kapslar in domänlogik, och programtjänster som tillhandahåller tekniska funktioner. Programtjänster omfattar vanligtvis tekniska funktioner som användarautentisering eller att skicka ett SMS. Domäntjänster används ofta för att modellera beteende som omfattar flera entiteter.
  • Domänhändelser: Domänhändelser kan användas för att meddela andra delar av systemet när något händer. Som namnet antyder bör domänhändelser betyda något inom domänen. Till exempel är "en post infogades i en tabell" inte en domänhändelse. "En leverans avbröts" är en domänhändelse. Domänhändelser är särskilt relevanta i en arkitektur för mikrotjänster. Eftersom mikrotjänster distribueras och inte delar datalager är domänhändelser ett sätt för mikrotjänster att samordna med varandra.

Diagram över drönardomänmodellen.

I deras system identifierade Fabrikams utvecklingsteam följande entiteter:

  • Leverans
  • Paket
  • Drönare
  • Konto
  • Konfirmation
  • Anmälan
  • Tagg

De första fyra entiteterna, leverans, paket, drönare och konto, är alla aggregeringar som representerar transaktionskonsekvensgränser. Bekräftelser och meddelanden är underordnade enheter av leveranser. Taggar är underordnade entiteter till paket.

Värdeobjekten i den här designen är Plats, ETA, PackageWeight och PackageSize.

Det finns två domänhändelser:

  • Medan en drönare är under flygning skickar drönarentiteten DroneStatus-händelser som beskriver drönarens plats och status, till exempel under flygning och landade.
  • Leveransentiteten skickar DeliveryTracking-händelser när fasen för en leverans ändras. Dessa händelser inkluderar DeliveryCreated, DeliveryRescheduled, DeliveryHeadedToDropoff och DeliveryCompleted.

Observera att dessa händelser beskriver saker som är meningsfulla i domänmodellen. De beskriver något om domänen och är inte knutna till en viss programmeringsspråkkonstruktion.

Utvecklingsteamet identifierade ytterligare ett funktionsområde, som inte passar in i någon av de entiteter som beskrivs hittills. En del av systemet måste samordna alla steg som ingår i schemaläggningen eller uppdateringen av en leverans. Utvecklingsteamet har lagt till två domäntjänster i designen. En schemaläggare samordnar stegen. En övervakare övervakar statusen för varje steg för att identifiera om några steg misslyckades eller tidsgränsen överskrids.

Identifiera mikrotjänster

Nu är vi redo att gå från domänmodell till programdesign. Här är en metod som du kan använda för att härleda mikrotjänster från domänmodellen.

  1. Börja med en begränsad kontext. I allmänhet bör funktionerna i en mikrotjänst inte omfatta mer än en begränsad kontext. Per definition markerar en avgränsad kontext gränsen för en viss domänmodell. Om mikrotjänsten blandar olika domänmodeller är det ett tecken på att du kan behöva förfina domänanalysen.
  2. Titta sedan på aggregeringarna i din domänmodell. Aggregeringar är ofta bra kandidater för mikrotjänster. Ett väl utformat aggregat visar många av egenskaperna hos en väl utformad mikrotjänst:
    • En aggregering härleds från affärskrav snarare än tekniska problem, till exempel dataåtkomst eller meddelanden.
    • En aggregering bör ha hög funktionell sammanhållning.
    • En aggregering är en gräns för beständighet.
    • Aggregaten ska vara löst kopplade.
  3. Domäntjänster är också bra kandidater för mikrotjänster. Domäntjänster är tillståndslösa operationer över flera aggregat. Ett vanligt exempel är ett arbetsflöde som omfattar flera mikrotjänster. Senare ser vi ett exempel på en domäntjänst i drone delivery-programmet.
  4. Överväg slutligen icke-funktionella krav. Titta på faktorer som teamstorlek, datatyper, tekniker, skalbarhetskrav, tillgänglighetskrav och säkerhetskrav. Dessa faktorer kan leda till att du ytterligare delar upp en mikrotjänst i två (eller flera) mindre tjänster, eller att göra det motsatta och kombinera flera mikrotjänster till en.

Det är viktigt att vara pragmatisk och komma ihåg att domändriven design är en iterativ process. När du är osäker börjar du med mer grova mikrotjänster. Det är enklare att dela upp en mikrotjänst i två mindre tjänster än att omstrukturera funktioner i flera befintliga mikrotjänster.

diagram över mikrotjänsterna.

Tillämpa domändriven design på drönarprogrammet

För Fabrikams program finns alla dessa tjänster i deras befintliga monolitiska program. När de har identifierat var de kan dela upp sitt program i mikrotjänster börjar de med pakettjänsten.

Pakettjänsten har för närvarande ett fokuserat utvecklingsteam som uppvisar prestandaproblem relaterade till skalbarhet och är en bra kandidat för att påbörja nedbrytningen av deras program.