Een toepassing analyseren en ontledingsgrenzen identificeren
Als u de toepassing naar een microservicearchitectuur wilt verplaatsen, moet Fabrikam de huidige toepassing evalueren en het bereik en de grens van elke microservice bepalen. Voor deze evaluatie gebruiken ze het DDD-framework (domain-driven design). Laten we eens kijken hoe ze deze toepassen op hun toepassing.
Notitie
In dit artikel wordt geen volledige en uitgebreide domeinanalyse weergegeven. We hebben het voorbeeld bewust kort gehouden om de belangrijkste punten te illustreren. Zie de sectie Meer informatie in de samenvatting aan het einde van deze module voor meer informatie over DDD.
Wat is domeingestuurd ontwerp?
DDD is een benadering van systeemontwerp oorspronkelijk geïntroduceerd door Erik Evans in het boek Domain-Driven Design: Tackle Complexity in the Heart of Software. Deze aanpak omvat drie belangrijke elementen:
- Richt u op de kerndomein- en domeinlogica.
- Structureer het ontwerp op een model van het domein.
- Iteratieve samenwerking tussen de technische teams en zakenpartners stimuleren om het systeem voortdurend te verbeteren.
DDD biedt een framework waarmee u de meeste mogelijkheden krijgt voor een set goed ontworpen microservices. Het heeft twee verschillende fasen, strategische en tactische. In strategische DDD definieert u de grootschalige structuur van het systeem. Strategische DDD helpt ervoor te zorgen dat uw architectuur gericht blijft op bedrijfsmogelijkheden. Tactische DDD biedt een set ontwerppatronen die u kunt gebruiken om het domeinmodel te maken. Deze patronen omvatten entiteiten, aggregaties en domeinservices. Deze tactische patronen helpen u bij het ontwerpen van microservices die losjes gekoppeld en samenhangend zijn.
Tijdens de strategische fase van DDD wijst u het bedrijfsdomein toe en definieert u gebonden contexten voor uw domeinmodellen. Tactische DDD is wanneer u uw domeinmodellen met meer precisie definieert. De tactische patronen worden toegepast binnen een enkele begrensde context. In een microservicesarchitectuur zijn we geïnteresseerd in de entiteit en statistische patronen. Door deze patronen toe te passen, kunnen we natuurlijke grenzen voor de services in onze toepassing identificeren. Als algemeen principe mag een microservice niet kleiner zijn dan een aggregaties en niet groter zijn dan een gebonden context.
Op hoog niveau kunt u dit proces opsplitsen in vier stappen:
- Analyseer het bedrijfsdomein om inzicht te hebben in de functionele vereisten van de toepassing. De uitvoer van deze stap is een informele beschrijving van het domein, die kan worden verfijnd in een meer formele set domeinmodellen.
- Definieer de gebonden contexten van het domein. Elke gebonden context bevat een domeinmodel dat een bepaald subdomein van de grotere toepassing vertegenwoordigt.
- Pas binnen een context gebonden tactische DDD-patronen toe om entiteiten, aggregaties en domeinservices te definiëren.
- Identificeer de microservices in uw toepassing met behulp van de resultaten uit de vorige stap.
Laten we eens kijken wat er gebeurt bij elk van deze stappen.
Het bedrijfsdomein analyseren
DDD begint met het modelleren van het bedrijfsdomein en het maken van een domeinmodel. Het domeinmodel is een abstract model van het bedrijfsdomein. Het distilleert en organiseert domeinkennis en biedt een gemeenschappelijke taal voor ontwikkelaars en domeinexperts.
Begin met het in kaart brengen van alle bedrijfsfuncties en hun verbindingen. Deze analyse is een gezamenlijke inspanning waarbij domeinexperts, softwarearchitecten en andere belanghebbenden betrokken zijn. U hoeft geen bepaald formalisme te gebruiken. Schets een diagram of teken het op een whiteboard.
Wanneer u het diagram invult, kunt u afzonderlijke subdomeinen identificeren. Welke functies zijn nauw verwant? Welke functies zijn de kern van het bedrijf en welke bieden nevendiensten? Wat is de afhankelijkheidsgrafiek? Tijdens deze initiële fase hebt u geen betrekking op technologieën of implementatiedetails. Dat gezegd hebbende, moet u de plaats noteren waar de toepassing moet worden geïntegreerd met externe systemen, zoals CRM, betalingsverwerking of factureringssystemen.
Gebonden contexten definiëren
Het domeinmodel bevat weergaven van echte dingen in de wereld, zoals gebruikers, drones en pakketten. Maar dat betekent niet dat elk deel van het systeem dezelfde representaties voor dezelfde dingen moet gebruiken.
Subsystemen die bijvoorbeeld omgaan met droneherstel en voorspellende analyse moeten veel fysieke kenmerken van drones vertegenwoordigen. Deze kenmerken omvatten onderhoudsgeschiedenis, kilometerstand, leeftijd, modelnummer en prestatiedetails. Maar als het tijd is om een levering te plannen, geven we niet om die dingen. Het planningssubsysteem hoeft alleen te weten of een drone beschikbaar is en de geschatte tijd van aankomst (ETA) voor ophalen en bezorgen.
Als we proberen één model te maken voor beide subsystemen, is het complexer dan we nodig hebben. Het wordt ook moeilijker voor het model om zich in de loop van de tijd te ontwikkelen, omdat eventuele wijzigingen moeten voldoen aan meerdere teams die aan afzonderlijke subsystemen werken. Het is vaak beter om afzonderlijke modellen te ontwerpen die dezelfde echte entiteit (in dit geval een drone) in twee verschillende contexten vertegenwoordigen. Elk model bevat alleen de functies en kenmerken die relevant zijn binnen de specifieke context.
Deze benadering is waar het DDD-concept van gebonden contexten in het spel komt. Een gebonden context is simpelweg de grens binnen een domein waarop een bepaald domeinmodel van toepassing is. Als we naar het vorige diagram kijken, kunnen we functionaliteit groeperen op basis van of verschillende functies één domeinmodel delen.
Entiteiten, aggregaties en services definiëren
Tactische DDD is wanneer u uw domeinmodellen met meer precisie definieert. De tactische patronen worden toegepast binnen een enkele begrensde context. In een microservicesarchitectuur zijn we geïnteresseerd in de entiteit en statistische patronen. Door deze patronen toe te passen, kunnen we natuurlijke grenzen voor de services in onze toepassing identificeren. Als algemeen principe mag een microservice niet kleiner zijn dan een aggregaties en niet groter zijn dan een gebonden context.
Er zijn verschillende tactische DDD-patronen om rekening mee te houden:
- entiteiten: Een entiteit is een object met een unieke identiteit die in de loop van de tijd blijft bestaan. In een banktoepassing zijn klanten en accounts bijvoorbeeld entiteiten.
- waardeobjecten: een waardeobject heeft geen identiteit. De waarden van de kenmerken definiëren deze en zijn onveranderbaar. Typische voorbeelden van waardeobjecten zijn kleuren, datums en tijden en valutawaarden.
- aggregaties: Een aggregatie definieert een consistentiegrens rond een of meer entiteiten. Het doel van een aggregaties is om transactionele invarianten te modelleren. Dingen in de echte wereld hebben complexe webs van relaties. Klanten maken orders, orders bevatten producten, producten hebben leveranciers, enzovoort. Als de toepassing verschillende gerelateerde objecten wijzigt, hoe garandeert deze consistentie? Hoe houden we invarianten bij en dwingen we ze af?
- Domein- en toepassingsservices: In DDD-terminologie is een service een object dat logica implementeert zonder enige status vast te houden. Evans maakt onderscheid tussen domeinservices, die domeinlogica inkapselen en toepassingsservices, die technische functionaliteit bieden. Toepassingsservices bevatten doorgaans technische functionaliteit, zoals gebruikersverificatie of het verzenden van een sms-bericht. Domeinservices worden vaak gebruikt om gedrag te modelleren dat meerdere entiteiten omvat.
- Domein gebeurtenissen: Domein gebeurtenissen kunnen worden gebruikt om andere onderdelen van het systeem te waarschuwen wanneer er iets gebeurt. Zoals de naam al aangeeft, moeten domeinevenementen iets betekenen binnen het domein. 'Een record is bijvoorbeeld ingevoegd in een tabel' is geen domeingebeurtenis. 'Een levering is geannuleerd' is een domeingebeurtenis. Domeinevenementen zijn met name relevant in een microservicesarchitectuur. Omdat microservices worden gedistribueerd en geen gegevensarchieven delen, bieden domeingebeurtenissen een manier om microservices met elkaar te coördineren.
In hun systeem heeft het ontwikkelteam van Fabrikam de volgende entiteiten geïdentificeerd:
- Levering
- Pakket
- Drone
- Account
- Bevestiging
- Melding
- Tag
De eerste vier entiteiten, levering, pakket, drone en account zijn allemaal aggregaties die transactionele consistentiegrenzen vertegenwoordigen. Bevestigingen en meldingen zijn sub-entiteiten van leveringen. Tags zijn onderliggende entiteiten van pakketten.
De waardeobjecten in dit ontwerp omvatten Locatie, ETA, PackageWeight en PackageSize.
Er zijn twee domeinevenementen:
- Terwijl een drone in de vlucht is, verzendt de drone-entiteit DroneStatus-gebeurtenissen die de locatie en status van de drone beschrijven, bijvoorbeeld in vlucht, geland.
- De leveringsentiteit verzendt DeliveryTracking-gebeurtenissen wanneer de fase van een levering verandert. Deze gebeurtenissen omvatten DeliveryCreated, DeliveryRescheduled, DeliveryHeadedToDropoff en DeliveryCompleted.
U ziet dat deze gebeurtenissen dingen beschrijven die zinvol zijn binnen het domeinmodel. Ze beschrijven iets over het domein en zijn niet gekoppeld aan een bepaalde programmeertaalconstructie.
Het ontwikkelteam heeft nog een gebied van functionaliteit geïdentificeerd, dat niet netjes in een van de tot nu beschreven entiteiten past. Een deel van het systeem moet alle stappen coördineren die betrekking hebben op het plannen of bijwerken van een levering. Het ontwikkelteam heeft twee domeinservices toegevoegd aan het ontwerp. Een Scheduler coördineert de stappen. Een Supervisor bewaakt de status van elke stap om te controleren of er een stap is mislukt of er een time-out optreedt.
Microservices identificeren
Nu zijn we klaar om van domeinmodel naar toepassingsontwerp te gaan. Hier volgt een benadering die u kunt gebruiken om microservices af te leiden van het domeinmodel.
- Begin met een afgebakende context. Over het algemeen mag de functionaliteit in een microservice niet meer dan één gebonden context omvatten. Per definitie markeert een contextgrens de grens van een bepaald domeinmodel. Als uw microservice verschillende domeinmodellen combineert, is het een teken dat u mogelijk uw domeinanalyse moet verfijnen.
- Bekijk vervolgens de aggregaties in uw domeinmodel. Aggregaties zijn vaak goede kandidaten voor microservices. Een goed ontworpen aggregatie toont veel van de kenmerken van een goed ontworpen microservice.
- Een aggregaat ontstaat uit bedrijfsvereisten in plaats van technische aspecten, zoals gegevens toegang of berichtgeving.
- Een aggregatie moet een hoge functionele samenhang hebben.
- Een aggregatie is een grens van persistentie.
- Aggregaten moeten zwak gekoppeld zijn.
- Domeinservices zijn ook goede kandidaten voor microservices. Domeinservices zijn staatloze bewerkingen voor meerdere aggregaten. Een typisch voorbeeld is een werkstroom met verschillende microservices. Later zien we een voorbeeld van een domeinservice in de Drone Delivery-toepassing.
- Houd ten slotte rekening met niet-functionele vereisten. Bekijk factoren zoals teamgrootte, gegevenstypen, technologieën, schaalbaarheidsvereisten, beschikbaarheidsvereisten en beveiligingsvereisten. Deze factoren kunnen ertoe leiden dat u een microservice verder opdeelt in twee (of meer) kleinere services, of om het tegenovergestelde te doen en verschillende microservices in één te combineren.
Het is belangrijk om pragmatisch te zijn en te onthouden dat domeingestuurd ontwerp een iteratief proces is. Bij twijfel, begin met grofmazige microservices. Het is eenvoudiger om een microservice op te splitsen in twee kleinere services dan om functionaliteit over verschillende bestaande microservices te herstructureren.
Domeingestuurd ontwerp toepassen op de dronetoepassing
Voor de toepassing van Fabrikam bevinden al deze services zich in hun bestaande monolithische toepassing. Nadat ze hebben geïdentificeerd waar ze hun toepassing in microservices kunnen ontleden, beginnen ze met de pakketservice.
De pakketservice heeft momenteel een gericht ontwikkelteam, vertoont prestatieproblemen met betrekking tot schaalbaarheid en is een uitstekende kandidaat om de ontleding van hun toepassing te starten.