Delen via


Domeinanalyse gebruiken om microservices te modelleren

Een van de grootste uitdagingen van microservices is het definiëren van de grenzen van afzonderlijke services. De algemene regel is dat een service 'één ding' moet doen, maar om die regel in de praktijk te brengen, is zorgvuldig nagedacht. Er is geen mechanisch proces dat het "juiste" ontwerp produceert. U moet diep nadenken over uw bedrijfsdomein, vereisten, architectuurkenmerken (ook wel niet-functionele vereisten genoemd) en doelstellingen. Anders kunt u eindigen met een hapazer ontwerp dat enkele ongewenste kenmerken vertoont, zoals verborgen afhankelijkheden tussen services, strakke koppeling of slecht ontworpen interfaces. In dit artikel wordt een domeingestuurde benadering voor het ontwerpen van microservices beschreven. Het evalueren van servicegrenzen is een doorlopende inspanning voor het ontwikkelen van workloads. Soms resulteert de evaluatie in opnieuw gedefinieerde definities van bestaande grenzen waarvoor aanvullende toepassingsontwikkeling nodig is om tegemoet te komen aan de wijzigingen.

In dit artikel wordt een droneleveringsservice gebruikt als een actief voorbeeld. Meer informatie over het scenario en de bijbehorende referentie-implementatie vindt u hier.

Inleiding

Microservices moeten worden ontworpen rond bedrijfsmogelijkheden, niet horizontale lagen, zoals gegevenstoegang of berichten. Bovendien moeten ze losse koppeling en een hoge functionele samenhang hebben. Microservices zijn losjes gekoppeld als u de ene service kunt wijzigen zonder dat andere services tegelijkertijd moeten worden bijgewerkt. Een microservice is samenhangend als deze één, goed gedefinieerd doel heeft, zoals het beheren van gebruikersaccounts of het bijhouden van de leveringsgeschiedenis. Een service moet domeinkennis inkapselen en die kennis van clients abstraheren. Een klant moet bijvoorbeeld een drone kunnen plannen zonder de details van het planningsalgoritmen te kennen of hoe de drone vloot wordt beheerd. Architectuurkenmerken moeten worden gedefinieerd voor elke microservice om te voldoen aan de domeinproblemen, in plaats van te worden gedefinieerd voor het hele systeem. Een klantgerichte microservice moet bijvoorbeeld prestaties, beschikbaarheid, fouttolerantie, beveiliging, testbaarheid en flexibiliteit hebben. Een back-endmicroservice moet mogelijk alleen fouttolerantie en beveiliging hebben. Als microservices synchrone communicatie met elkaar hebben, produceert de afhankelijkheid tussen deze services vaak de noodzaak om dezelfde architectuurkenmerken te delen.

Domain-Driven Design (DDD) biedt een framework waarmee u bijna helemaal tot een set goed ontworpen microservices kunt komen. DDD bestaat uit twee verschillende fasen: de strategische en de tactische. In strategische DDD definieert u de grootschalige structuur van het systeem. Met strategische DDD kunt u uw architectuur gericht houden op zakelijke mogelijkheden. Tactische DDD biedt een set ontwerppatronen waarmee u het domeinmodel kunt maken. Deze patronen bestaan onder meer uit entiteiten, aggregaties en domeinservices. Met deze tactische patronen kunt u microservices ontwerpen die losjes gekoppeld en samenhangend zijn.

Diagram van een DDD-proces (Domain-Driven Design)

In dit artikel en het volgende doorlopen we de volgende stappen, waarbij ze worden toegepast op de Drone Delivery-toepassing:

  1. Begin met het analyseren van het bedrijfsdomein om inzicht te krijgen in de functionele vereisten van de toepassing. De uitvoer van deze stap is een informele beschrijving van het domein, die kan worden verfijnd tot een formelere set domeinmodellen.

  2. Definieer vervolgens de gebonden contexten van het domein. Elke contextgrens bevat een domeinmodel dat een bepaald subdomein van de grotere toepassing vertegenwoordigt.

  3. Pas binnen een contextgrens tactische DDD-patronen toe om entiteiten, aggregaties en domeinservices te definiëren.

  4. Gebruik de resultaten uit de vorige stap om de microservices in uw toepassing te identificeren.

In dit artikel behandelen we de eerste drie stappen, die voornamelijk betrekking hebben op DDD. In het volgende artikel identificeren we de microservices. Het is echter belangrijk om te onthouden dat DDD een iteratief, doorlopend proces is. Servicegrenzen worden niet in steen opgelost. Naarmate een toepassing zich ontwikkelt, kunt u besluiten om een service op te splitsen in verschillende kleinere services.

Notitie

In dit artikel wordt geen volledige en uitgebreide domeinanalyse getoond. We hebben het voorbeeld bewust kort gehouden om de belangrijkste punten te illustreren. Voor meer achtergrondinformatie over DDD raden we Domain-Driven Design van Eric Evans aan, het boek waarin hij de term heeft geïntroduceerd. Een ander goed naslagwerk is Implementing Domain-Driven Design van Vaughn Vernon.

Scenario: Dronelevering

Fabrikam, Inc. begint met een service voor het leveren van pakketjes per drone. Het bedrijf beheert een hele vloot van drones. Bedrijven registreren zich bij de service en gebruikers kunnen dan een aanvraag indienen om pakketjes door een drone te laten ophalen. Wanneer een klant een datum en tijd opgeeft waarop het pakketje moet worden opgehaald, wordt er een drone toegewezen en de gebruiker op de hoogte gesteld van de geschatte levertijd. Terwijl de levering wordt uitgevoerd, kan de klant de locatie van de drone zien, met een doorlopend bijgewerkte verwachte aankomsttijd.

Voor dit scenario is een tamelijk gecompliceerd domein een vereiste. Een aantal van de problemen die het bedrijf ondervindt, is het plannen van de drone-inzet, het traceren van pakketjes, het beheren van gebruikersaccounts, en het opslaan en analyseren van historische gegevens. Bovendien wil Fabrikam zijn toepassingen sneller op de markt kunnen afzetten en met een hogere frequentie, waarbij nieuwe functionaliteit en mogelijkheden worden toegevoegd. De toepassing moet op cloudschaal werken en een hoge serviceniveaudoelstelling hebben. Fabrikam verwacht ook dat de verschillende onderdelen van het systeem volledig verschillende vereisten hebben voor wat betreft gegevensopslag en het uitvoeren van query's. Op basis van al deze overwegingen kiest Fabrikam ervoor een microservicearchitectuur te gebruiken voor de toepassing Drone Delivery.

Het domein analyseren

Met behulp van een DDD-benadering kunt u microservices ontwerpen, zodat elke service een natuurlijke pasvorm vormt voor een functionele bedrijfsvereiste. Het kan u helpen om te voorkomen dat organisatiegrenzen of technologiekeuzen uw ontwerp bepalen.

Voordat u code schrijft, hebt u een vogelperspectief nodig van het systeem dat u maakt. DDD begint met het modelleren van het bedrijfsdomein en het maken van een domeinmodel. Het domeinmodel is een abstract model van het bedrijfsdomein. Het biedt afgeleide en georganiseerde domeinkennis en een gemeenschappelijke taal voor ontwikkelaars en domeinexperts.

Begin met het in kaart brengen van alle bedrijfsfuncties en de verbindingen ervan. Dit wordt waarschijnlijk een gezamenlijke inspanning van domeinexperts, softwarearchitecten en andere belanghebbenden. U hoeft geen specifieke vorm te gebruiken. Schets een diagram of teken op een whiteboard.

U kunt beginnen met het identificeren van afzonderlijke subdomeinen als u het diagram gaat invullen. Welke functies zijn nauw verwant? Welke functies behoren tot de kernactiviteiten van het bedrijf en welke bieden aanvullende services? Wat is de afhankelijkheidsgrafiek? In deze eerste fase hoeft u zich niet te bekommeren om technologieën of implementatiedetails. Let wel op de plaats waar de toepassing moet worden geïntegreerd met externe systemen, zoals CRM of systemen voor betalingsverwerking of facturering.

Voorbeeld: Drone delivery application

Na enige initiële domeinanalyse heeft het Fabrikam-team een ruwe schets gemaakt die het Drone Delivery-domein weergeeft.

Diagram van het Drone Delivery-domein

  • Verzending wordt in het midden van het diagram geplaatst, omdat het de kern van het bedrijf is. Al het andere in het diagram bestaat om deze functionaliteit in te schakelen.
  • Dronemanagement is ook de kern van het bedrijf. Functionaliteit die nauw samenhangt met dronebeheer omvat droneherstel en voorspellende analyse om te voorspellen wanneer drones onderhoud en onderhoud nodig hebben.
  • ETA-analyse biedt tijdsramingen voor ophalen en bezorgen.
  • Met transport van derden kan de toepassing alternatieve transportmethoden plannen als een pakket niet volledig per drone kan worden verzonden.
  • Drone delen is een mogelijke uitbreiding van het kernbedrijf. Het bedrijf heeft mogelijk overtollige dronecapaciteit tijdens bepaalde uren en kan drones huren die anders niet actief zouden zijn. Deze functie bevindt zich niet in de eerste release.
  • Videobewaking is een ander gebied dat het bedrijf later kan uitbreiden.
  • Gebruikersaccounts, Facturering en Callcenter zijn subdomeinen die ondersteuning bieden voor het kernbedrijf.

U ziet dat we op dit moment in het proces geen beslissingen hebben genomen over implementatie of technologieën. Sommige subsystemen kunnen externe softwaresystemen of services van derden omvatten. Bovendien moet de toepassing communiceren met deze systemen en services, dus het is belangrijk om ze op te nemen in het domeinmodel.

Notitie

Wanneer een toepassing afhankelijk is van een extern systeem, bestaat het risico dat het gegevensschema of de API van het externe systeem in uw toepassing lekt en uiteindelijk het architectuurontwerp in gevaar brengt. Dit geldt met name voor verouderde systemen die mogelijk geen moderne aanbevolen procedures volgen en mogelijk gebruikmaken van samengevoegde gegevensschema's of verouderde API's. In dat geval is het belangrijk om een goed gedefinieerde grens te hebben tussen deze externe systemen en de toepassing. Overweeg hiervoor het patroon Strangler Fig of het anti-corruptielaagpatroon te gebruiken.

Contextgrenzen definiëren

Het domeinmodel zal representaties van echte dingen in de wereld bevatten, zoals gebruikers, drones en pakketten. Dat betekent echter niet dat in elk deel van het systeem dezelfde representaties voor dezelfde dingen moeten worden gebruikt.

Subsystemen die bijvoorbeeld droneherstel en voorspellende analyse verwerken, moeten veel fysieke kenmerken van drones vertegenwoordigen, zoals hun onderhoudsgeschiedenis, kilometerstand, leeftijd, modelnummer, prestatiekenmerken, enzovoort. Als we een levering plannen, zijn dat soort zaken echter niet van belang. In het subsysteem voor planning hoeft alleen bekend te zijn of een drone beschikbaar is en wat de verwachte ophaal- en levertijd zijn.

Als we zouden proberen één model voor beide subsystemen te maken, zou dat model onnodig ingewikkeld zijn. Het zou ook lastiger zijn om het model in de loop van de tijd verder te ontwikkelen omdat elke wijziging zou moeten voldoen aan de wensen van meerdere teams die aan afzonderlijke subsystemen werken. Daarom is het vaak beter om afzonderlijke modellen te ontwerpen voor dezelfde werkelijke entiteit (in dit geval een drone) in twee verschillende contexten. Elk model bevat alleen de functies en kenmerken die relevant zijn binnen de specifieke context.

Hier komt het DDD-concept van gebonden contexten in het spel. Een contextgrens is gewoonweg de grens binnen een domein waarop een bepaald domeinmodel van toepassing is. De functies in het vorige diagram kunnen we groeperen op basis van aanwezigheid ervan in één domeinmodel.

Diagram van gebonden contexten

Gebonden contexten zijn niet noodzakelijkerwijs van elkaar geïsoleerd. In dit diagram vertegenwoordigen de ononderbroken lijnen die de begrensde contexten verbinden plaatsen waar twee contexten met elkaar communiceren. De verzending is bijvoorbeeld afhankelijk van gebruikersaccounts om informatie over klanten te krijgen en dronebeheer om drones van de vloot te plannen.

In het boek Domain Driven Design beschrijft Eric Evans verschillende patronen voor het behouden van de integriteit van een domeinmodel wanneer het communiceert met een andere gebonden context. Een van de belangrijkste principes van microservices is dat services communiceren via goed gedefinieerde API's. Deze benadering komt overeen met twee patronen die Evans open hostservice en gepubliceerde taal aanroept. Het idee van Open Host Service is dat een subsysteem een formeel protocol (API) definieert voor andere subsystemen om ermee te communiceren. Gepubliceerde taal breidt dit idee uit door de API te publiceren in een vorm die andere teams kunnen gebruiken om clients te schrijven. In het artikel API's ontwerpen voor microservices bespreken we het gebruik van OpenAPI-specificatie (voorheen Swagger genoemd) voor het definiëren van taalagnostische interfacebeschrijvingen voor REST API's, uitgedrukt in JSON- of YAML-indeling.

Voor de rest van deze reis richten we ons op de context Van verzending gebonden.

Volgende stappen

Nadat u een domeinanalyse hebt voltooid, is de volgende stap het toepassen van tactische DDD om uw domeinmodellen met meer precisie te definiëren.