Poznámka
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Návod
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.
V DDD lze ověřovací pravidla považovat za invarianty. Hlavní odpovědností agregace je vynucovat invarianty napříč změnami stavu pro všechny entity v rámci této agregace.
Entita domény by měla být vždy platná entita. Existuje určitý počet invariantů pro objekt, který by měl být vždy pravdivý. Například objekt položky objednávky musí mít vždy množství, které musí být kladné celé číslo plus název a cena článku. Invarianty jsou tedy odpovědností entit domény (zejména kořene agregátu) a objekt entity by neměl existovat, pokud není platný. Invariantní pravidla jsou vyjádřena jednoduše jako kontrakty a při jejich porušení jsou vyvolány výjimky nebo oznámení.
Důvodem je, že k mnoha chybám dochází, protože objekty jsou ve stavu, ve kterých by nikdy neměly být.
Pojďme navrhnout, že nyní máme službu SendUserCreationEmailService, která přebírá UserProfile ... Jak můžeme v této službě zdůvodnit, že jméno není null? Zkontrolujeme to znovu? Nebo pravděpodobněji ... se prostě neobtěžujete zkontrolovat a "doufáte v to nejlepší" — doufáte, že se někdo obtěžoval s ověřením před tím, než vám to poslal. Samozřejmě, při použití TDD bychom jeden z prvních testů měli napsat tak, že pokud pošleme zákazníka s nulovým jménem, měl by vyvolat chybu. Ale jakmile začneme psát tyto druhy testů znovu a znovu si uvědomujeme ... "co když nikdy nepovolíme, aby jméno bylo null? Neměli bychom všechny tyto testy!".
Implementace ověření ve vrstvě doménového modelu
Ověřování se obvykle implementují v konstruktorech entit domény nebo v metodách, které mohou entitu aktualizovat. Existuje několik způsobů implementace ověření, například ověření dat a vyvolání výjimek v případě selhání ověření. Existují také pokročilejší vzory, jako je použití vzoru specifikace pro ověřování, a vzor oznámení pro vrácení kolekce chyb místo vrácení výjimky pro každé ověření, jak k tomu dochází.
Ověřte podmínky a vyvolejte výjimky
Následující příklad kódu ukazuje nejjednodušší přístup k ověření v entitě domény vyvoláním výjimky. V tabulce odkazů na konci této části vidíte odkazy na pokročilejší implementace na základě vzorů, které jsme probrali dříve.
public void SetAddress(Address address)
{
_shippingAddress = address?? throw new ArgumentNullException(nameof(address));
}
Lepší příklad by ukázal potřebu zajistit, aby se buď vnitřní stav nezměnil, nebo že došlo ke všem mutacím pro metodu. Například následující implementace ponechá objekt v neplatném stavu:
public void SetAddress(string line1, string line2,
string city, string state, int zip)
{
_shippingAddress.line1 = line1 ?? throw new ...
_shippingAddress.line2 = line2;
_shippingAddress.city = city ?? throw new ...
_shippingAddress.state = (IsValid(state) ? state : throw new …);
}
Pokud je hodnota státu neplatná, první řádek adresy a město již byly změněny. To může zneplatnit adresu.
Podobný přístup lze použít v konstruktoru entity a zvýšit výjimku, aby byla entita po vytvoření platná.
Použití ověřovacích atributů v modelu na základě datových poznámek
Datové poznámky, jako jsou atributy Required nebo MaxLength, je možné použít ke konfiguraci vlastností pole databáze EF Core, jak je vysvětleno podrobně v části Mapování tabulek , ale už nefungují pro ověřování entit v EF Core (ani IValidatableObject.Validate tato metoda), jak to udělalo od EF 4.x v rozhraní .NET Framework.
Datové anotace a rozhraní IValidatableObject lze stále používat pro ověřování modelu během vazby modelu, před obvyklým vyvoláním akcí kontroleru. Tento model by však měl být chápán jako ViewModel nebo DTO, což je záležitost MVC nebo API, nikoliv doménového modelu.
Po objasnění koncepčního rozdílu můžete stále používat datové poznámky a IValidatableObject
ve třídě entity pro ověřování, pokud vaše akce přijímá parametr objektu entity, což se nedoporučuje. V takovém případě dojde k ověření během vazby modelu, těsně před spuštěním akce. Stav modelu kontroleru můžete zjistit pomocí vlastnosti ModelState.IsValid. To se však stane v kontroleru, nikoli před uložením objektu entity v DbContext, jak tomu bylo u EF od verze 4.x.
Stále můžete implementovat vlastní ověřování ve třídě entity pomocí datových poznámek a metody IValidatableObject.Validate
přepsáním metody SaveChanges třídy DbContext.
Ukázkovou implementaci pro ověřování IValidatableObject
entit v tomto komentáři najdete na GitHubu. Tato ukázka neprovádí ověřování založená na atributech, ale mělo by být snadné je implementovat pomocí reflexe ve stejné metodě přepisu.
Z hlediska DDD je však doménový model nejlépe štíhlý s použitím výjimek v metodách chování vaší entity nebo implementací vzorů specifikace a oznámení k vynucení ověřovacích pravidel.
Může dávat smysl používat datové poznámky v aplikační vrstvě ve třídách ViewModel (místo entit domény), které budou přijímat vstupy, aby bylo možné ověřování modelu v rámci vrstvy uživatelského rozhraní. To by se ale nemělo provádět při vyloučení ověření v rámci doménového modelu.
Ověření entit implementací vzoru specifikace a vzoru oznámení
A konečně složitější přístup k implementaci ověřování v doménovém modelu spočívá v implementaci vzoru specifikace ve spojení se vzorem oznámení, jak je vysvětleno v některých dalších prostředcích uvedených později.
Stojí za zmínku, že můžete také použít jenom jeden z těchto vzorů – například ruční ověřování pomocí řídicích příkazů, ale použití vzoru oznámení k naskládání a vrácení seznamu chyb ověření.
Použití odloženého ověření v doméně
Existují různé přístupy k řešení odložených ověření v doméně. Ve své knize Implementing Domain-Driven Design Vaughn Vernon diskutuje tyto koncepty v části o ověřování.
Dvoustupňové ověřování
Zvažte také dvoustupňové ověřování. Ověřování na úrovni pole můžete použít pro příkaz Data Transfer Objects (DTOs) a ověřování na úrovni domény uvnitř entit. Můžete to provést vrácením výsledného objektu místo výjimek, aby bylo snazší pracovat s chybami ověření.
Když používáte ověřování polí pomocí datových anotací, například nedefinujete ověření dvakrát. Provádění ale může být na straně serveru i na straně klienta v případě objektů DTO (například příkazů a modelů ViewModel).
Dodatečné zdroje
Rachel Appel. Úvod k ověřování modelu v ASP.NET Core MVC
https://learn.microsoft.com/aspnet/core/mvc/models/validationPřidání ověření
https://learn.microsoft.com/aspnet/core/tutorials/first-mvc-app/validationMartin Fowler. Nahrazování vyvolání výjimek upozorněním během ověřovacích procesů
https://martinfowler.com/articles/replaceThrowWithNotification.htmlVzory specifikace a oznámení
https://www.codeproject.com/Tips/790758/Specification-and-Notification-PatternsLev Gorodinski. Ověřování v návrhu Domain-Driven (DDD)
http://gorodinski.com/blog/2012/05/19/validation-in-domain-driven-design-ddd/Colin Jack. Ověření doménového modelu
https://colinjack.blogspot.com/2008/03/domain-model-validation.htmlJimmy Bogard. Ověřování ve světě DDD
https://lostechies.com/jimmybogard/2009/02/15/validation-in-a-ddd-world/