Návrh doménového modelu mikroslužeb

Tip

Tento obsah je výňatek z eBooku, architektury mikroslužeb .NET pro kontejnerizované aplikace .NET, které jsou k dispozici na .NET Docs nebo jako zdarma ke stažení PDF, které lze číst offline.

.NET Microservices Architecture for Containerized .NET Applications eBook cover thumbnail.

Definujte jeden bohatý doménový model pro každou obchodní mikroslužbu nebo ohraničený kontext.

Vaším cílem je vytvořit jeden soudržný doménový model pro každou obchodní mikroslužbu nebo ohraničený kontext (BC). Mějte ale na paměti, že bc nebo obchodní mikroslužba se někdy skládají z několika fyzických služeb, které sdílejí jeden doménový model. Doménový model musí zachytit pravidla, chování, obchodní jazyk a omezení jediného vázaného kontextu nebo obchodní mikroslužby, kterou představuje.

Model entity domény

Entity představují objekty domény a primárně jsou definovány jejich identitou, kontinuitou a trvalostí v průběhu času, a to nejen atributy, které je tvoří. Jak říká Eric Evans, "objekt, který je primárně definován jeho identitou, se nazývá Entita." Entity jsou v doménovém modelu velmi důležité, protože jsou základem modelu. Proto byste je měli pečlivě identifikovat a navrhnout.

Identita entity může překračovat více mikroslužeb nebo ohraničených kontextů.

Stejnou identitu (tj. stejnou Id hodnotu, i když pravděpodobně ne stejnou entitu domény) je možné modelovat napříč několika ohraničenými kontexty nebo mikroslužbami. To však neznamená, že by stejná entita se stejnými atributy a logikou byla implementována v několika ohraničených kontextech. Místo toho entity v každém vázaném kontextu omezují své atributy a chování na ty, které jsou vyžadovány v doméně ohraničeného kontextu.

Entita kupujícího může mít například většinu atributů osoby, které jsou definovány v entitě uživatele v mikroslužbě profilu nebo identity, včetně identity. Entita kupujícího v mikroslužbě objednávání ale může mít méně atributů, protože s procesem objednávky souvisí pouze určitá data kupujícího. Kontext každé mikroslužby nebo ohraničeného kontextu má vliv na jeho doménový model.

Kromě implementace atributů dat musí entity domény implementovat chování.

Entita domény v DDD musí implementovat logiku domény nebo chování související s daty entity (objekt přístupný v paměti). Například jako součást třídy entity objednávky musíte mít obchodní logiku a operace implementované jako metody pro úlohy, jako je přidání položky objednávky, ověření dat a celkový výpočet. Metody entity se starají o invarianty a pravidla entity místo toho, aby se tato pravidla rozprostřela napříč aplikační vrstvou.

Obrázek 7–8 ukazuje entitu domény, která implementuje nejen atributy dat, ale také operace nebo metody s související logikou domény.

Diagram showing a Domain Entity's pattern.

Obrázek 7–8 Příklad návrhu entity domény, který implementuje data plus chování

Entita doménového modelu implementuje chování prostřednictvím metod, to znamená, že se nejedná o "anemický" model. Samozřejmě, že někdy můžete mít entity, které neimplementují žádnou logiku jako součást třídy entity. K tomu může dojít v podřízených entitách v rámci agregace, pokud podřízená entita nemá žádnou speciální logiku, protože většina logiky je definovaná v kořenovém adresáři agregace. Pokud máte komplexní mikroslužbu, která má logiku implementovanou v třídách služby místo v entitách domény, můžete být zahrnuti do doménového modelu anemické domény, vysvětlené v následující části.

Bohatý doménový model versus anemický doménový model

V jeho post AnemicDomainModel Martin Fowler popisuje anemický doménový model tímto způsobem:

Základním příznakem modelu Anemic Domain Model je, že na první pohled vypadá jako skutečná věc. Existují objekty, mnoho pojmenovaných po podstatných jmenách v prostoru domény a tyto objekty jsou propojeny s bohatými relacemi a strukturou, které mají skutečné doménové modely. Úlovek přijde, když se podíváte na chování, a uvědomujete si, že na těchto objektech není téměř žádné chování, takže je trochu více než tašky getters a setters.

Samozřejmě, když použijete doménový model anemické domény, tyto datové modely se použijí ze sady objektů služby (tradičně pojmenované obchodní vrstvy), které zachycují veškerou doménu nebo obchodní logiku. Obchodní vrstva se nachází nad datovým modelem a používá datový model stejně jako data.

Anemický doménový model je pouze procedurální styl návrhu. Anemické objekty entity nejsou skutečné objekty, protože nemají chování (metody). Uchovávají pouze vlastnosti dat, a proto nejsou objektově orientované na návrh. Když umístíte veškeré chování do objektů služeb (obchodní vrstva), v podstatě skončíte s špagetovým kódem nebo transakčními skripty, a proto ztratíte výhody, které poskytuje doménový model.

Bez ohledu na to, jestli je mikroslužba nebo ohraničený kontext velmi jednoduchá (služba CRUD), může být model domény anemické domény ve formě objektů entit s pouze vlastnostmi dat dostatečně dobrý a nemusí být vhodné implementovat složitější vzory DDD. V takovém případě to bude jednoduše model trvalosti, protože jste záměrně vytvořili entitu pouze s daty pro účely CRUD.

Proto jsou architektury mikroslužeb ideální pro přístup s více architekturami v závislosti na každém vázaném kontextu. Například v eShopOnContainers mikroslužba řazení implementuje vzory DDD, ale mikroslužba katalogu, což je jednoduchá služba CRUD, ne.

Někteří lidé říkají, že anemický doménový model je anti-vzor. To opravdu závisí na tom, co implementujete. Pokud je mikroslužba, kterou vytváříte, dostatečně jednoduchá (například služba CRUD), po modelu anemické domény se nejedná o anti-vzor. Pokud ale potřebujete řešit složitost domény mikroslužby, která má spoustu neustále se měnících obchodních pravidel, může být model anemické domény pro tuto mikroslužbu nebo ohraničený kontext anti-pattern. V takovém případě může mít návrh jako bohatý model s entitami obsahujícími data plus chování a implementaci dalších vzorů DDD (agregace, objekty hodnot atd.) obrovské výhody pro dlouhodobý úspěch takové mikroslužby.

Další materiály

Vzor objektu hodnoty

Jak poznamenal Eric Evans, "Mnoho objektů nemá koncepční identitu. Tyto objekty popisují určité vlastnosti věci."

Entita vyžaduje identitu, ale v systému existuje mnoho objektů, které ne, jako je model Value Object. Objekt hodnoty je objekt bez konceptuální identity, která popisuje aspekt domény. Jedná se o objekty, které vytváříte instanci představující prvky návrhu, které vás zajímají pouze dočasně. Staráš se o to, co jsou, ne o to, kdo jsou. Mezi příklady patří čísla a řetězce, ale můžou se jednat také o koncepty vyšší úrovně, jako jsou skupiny atributů.

Něco, co je entita v mikroslužbě, nemusí být entitou v jiné mikroslužbě, protože v druhém případě může mít ohraničený kontext jiný význam. Například adresa v aplikaci elektronického obchodování nemusí mít identitu vůbec, protože může představovat pouze skupinu atributů profilu zákazníka pro osobu nebo společnost. V tomto případě by se adresa měla klasifikovat jako objekt hodnoty. V aplikaci pro elektrickou elektrárnu ale může být pro obchodní doménu důležitá adresa zákazníka. Adresa proto musí mít identitu, aby fakturační systém mohl být přímo propojený s adresou. V takovém případě by se adresa měla klasifikovat jako entita domény.

Osoba se jménem a příjmením je obvykle entita, protože osoba má identitu, i když se jméno a příjmení shoduje s jinou sadou hodnot, například pokud tato jména odkazují také na jinou osobu.

Objekty hodnot se obtížně spravují v relačních databázích a ORM, jako je Entity Framework (EF), zatímco v dokumentově orientovaných databázích se snadněji implementují a používají.

EF Core 2.0 a novější verze obsahují funkci Vlastněné entity , která usnadňuje zpracování objektů hodnot, jak si podrobněji ukážeme později.

Další materiály

Model Agregace

Doménový model obsahuje clustery různých datových entit a procesů, které můžou řídit významnou oblast funkcí, jako je plnění objednávek nebo inventář. Jemněji odstupňovaná jednotka DDD je agregace, která popisuje cluster nebo skupinu entit a chování, které se dají považovat za soudržnou jednotku.

Obvykle definujete agregaci na základě potřebných transakcí. Klasický příklad je objednávka, která obsahuje také seznam položek objednávek. Položka objednávky obvykle představuje entitu. Bude to ale podřízená entita v rámci agregace objednávek, která bude také obsahovat entitu objednávky jako její kořenovou entitu, která se obvykle nazývá agregační kořen.

Identifikace agregací může být obtížná. Agregace je skupina objektů, které musí být konzistentní dohromady, ale nemůžete jen vybrat skupinu objektů a označovat je agregací. Musíte začít konceptem domény a zamyslete se nad entitami, které se používají v nejběžnějších transakcích souvisejících s tímto konceptem. Entity, které musí být konzistentně konzistentní, jsou to, co tvoří agregaci. Přemýšlet o transakčních operacích je pravděpodobně nejlepší způsob, jak identifikovat agregace.

Model agregované kořenové nebo kořenové entity

Agregace se skládá z alespoň jedné entity: agregační kořen, který se označuje také jako kořenová entita nebo primární entita. Kromě toho může mít více podřízených entit a hodnot objektů, přičemž všechny entity a objekty spolupracují na implementaci požadovaného chování a transakcí.

Účelem agregační kořene je zajistit konzistenci agregace; mělo by to být jediný vstupní bod pro aktualizace agregace prostřednictvím metod nebo operací v agregované kořenové třídě. V rámci agregace byste měli provádět změny pouze prostřednictvím kořenového adresáře agregace. Jedná se o opatrovníka konzistence agregace vzhledem ke všem invariantům a pravidlům konzistence, která možná budete muset dodržovat ve své agregaci. Pokud změníte podřízenou entitu nebo objekt hodnoty nezávisle, agregační kořen nemůže zajistit, aby agregace byla v platném stavu. Bylo by to jako stůl s volným nohama. Zachování konzistence je hlavním účelem agregovaného kořenového adresáře.

Na obrázku 7–9 můžete zobrazit ukázkové agregace, jako je agregace kupujícího, která obsahuje jednu entitu (agregovaný kořenový kupující). Agregace objednávky obsahuje více entit a objekt hodnoty.

Diagram comparing a buyer aggregate and an order aggregate.

Obrázek 7–9 Příklad agregací s více entitami nebo s jednou entitou

Doménový model DDD se skládá z agregací, agregace může mít pouze jednu entitu nebo více a může obsahovat i objekty hodnot. Všimněte si, že agregace Kupující může mít další podřízené entity v závislosti na vaší doméně, stejně jako v objednávání mikroslužby v referenční aplikaci eShopOnContainers. Obrázek 7–9 ukazuje pouze případ, kdy má kupující jednu entitu, jako příklad agregace, která obsahuje pouze agregační kořen.

Aby bylo možné udržovat oddělení agregací a udržovat mezi nimi jasné hranice, je vhodné v doménovém modelu DDD zakázat přímou navigaci mezi agregacemi a mít pouze pole cizího klíče (FK), jak je implementováno v doménovém modelu mikroslužby Ordering v eShopOnContainers. Entita Order má pouze pole cizího klíče pro kupujícího, ale ne vlastnost navigace EF Core, jak je znázorněno v následujícím kódu:

public class Order : Entity, IAggregateRoot
{
    private DateTime _orderDate;
    public Address Address { get; private set; }
    private int? _buyerId; // FK pointing to a different aggregate root
    public OrderStatus OrderStatus { get; private set; }
    private readonly List<OrderItem> _orderItems;
    public IReadOnlyCollection<OrderItem> OrderItems => _orderItems;
    // ... Additional code
}

Identifikace a práce s agregacemi vyžaduje výzkum a zkušenosti. Další informace najdete v následujícím seznamu dalších zdrojů informací.

Další materiály