it-swarm-eu.dev

Jak mohu být se všemi těmito službami anemický?

Kde nakreslíme hranici mezi delegací a zapouzdřením obchodní logiky? Zdá se mi, že čím více delegujeme, tím více anemických se stáváme. Delegování však také podporuje opakované použití a principu DRY=). Co je tedy vhodné delegovat a co by mělo zůstat v našich modelech domén?

Jako příklad vezměte následující obavy:

Autorizace . Pokud by byl doménový objekt zodpovědný za udržování svých pravidel řízení přístupu (jako je například vlastnost CanEdit) nebo by měl být delegován na jinou součást/službu, která je výhradně odpovědná za správu přístupu, např. IAuthorizationService.CanEdit (objekt)? Nebo by to měla být kombinace obou? Možná má doménový objekt vlastnost CanEdit, která deleguje interní IAuthorizationService za účelem provedení skutečné práce?

Ověření . Stejná diskuse jako výše se týká validace. Kdo dodržuje pravidla a kdo je za jejich hodnocení odpovědný? Na jedné straně by stav objektu měl patřit tomuto objektu a platnost je stav, ale nechceme přepisovat kód používaný k vyhodnocení pravidel pro každý objekt domény. My můžeme v tomto případě použijeme dědičnost ...

Vytváření objektů . Tovární třída versus tovární metody versus „nováčkování“ v instanci. Používáme-li samostatnou třídu továrny, jsme schopni izolovat a zapouzdřit logiku vytváření, ale na úkor otevření stavu našeho objektu do továrny. To lze spravovat, pokud je naše doména vrstva v odděleném sestavení tím, že odhalí interní konstruktér používaný v továrně, ale toto se stává problémem, pokud existuje více vzorů vytváření. A pokud celá továrna dělá, volá správného konstruktéra, co má smysl mít továrnu?

Tovární metody ve třídě eliminují problém s otevíráním vnitřního stavu objektu, ale protože jsou statické, nemůžeme zlomit závislosti injekcí továrního rozhraní, jako můžeme se samostatnou třídou továrny.

Perzistence . Dalo by se namítnout, že pokud náš objekt domény vystaví CanEdit, zatímco deleguje odpovědnost za provedení kontroly autorizace na jinou stranu (IAuthorizationService), proč nemá metodu Uložit na našem doménovém objektu, která dělá totéž? To by nám umožnilo vyhodnotit vnitřní stav objektu a zjistit, zda lze operaci provést bez přerušení zapouzdření. Samozřejmě to vyžaduje, abychom vložili instanci úložiště do našeho doménového objektu, který mi trochu voní, takže místo toho vyvoláme událost domény a umožníme manipulátoru provádět perzistenční operaci?

Vidíš, kam s tím půjdu?

Rockford Lhotka má velkou diskusi o svých důvodech, proč pro svou cestu CSLA absolvoval cestu Class-in-Charge, a já mám trochu historie s tímto rámcem a vidím jeho představu o obchodních objektech paralelních s doménovými objekty mnoha způsoby. Ale snažím se více vyhovovat dobrým ideálům DDD, zajímalo by mě, kdy se spolupráce stává příliš velkou.

Pokud skončím s IAuthorizationService, IValidator, IFactory a IRepository pro můj agregovaný root, co zbude? Je metoda publikování, která mění stav objektu z konceptu na publikováno natolik, že považuje třídu za neanemický doménový objekt?

Tvoje myšlenky?

92
SonOfPirate

Zdá se, že většina zmatku se týká funkcí, které by v modelu domény neměly vůbec existovat:

  • Perzistence by nikdy nemělo být v modelu domény. Vůbec nikdy. To je důvod, proč se spoléháte na abstraktní typy, jako je IRepository, pokud část modelu někdy potřebuje udělat něco jako načtení jiné části modelu, a použít závislost injekce nebo nějakou podobnou techniku ​​k zapojení implementace. Tak to udeřte ze záznamu.

  • Autorizace není obecně součástí vašeho modelu domény, pokud není skutečně součástí domény, např. pokud píšete bezpečnostní software. Mechanici, kterým je povoleno provádět to, co je v aplikaci, se běžně řeší v „Edge“ úrovně business/domain, veřejných částí, se kterými mohou části UI a integrace skutečně hovořit - Controller v MVC, Services nebo samotný systém zasílání zpráv v SOA ... získáte obrázek.

  • Továrny (a předpokládám, že máte na mysli abstraktní továrny), nejsou zrovna špatné , které mají v doménovém modelu, ale jsou téměř vždy zbytečné. Za normálních okolností máte továrnu pouze tehdy, když se vnitřní mechanika vytváření objektů může změnit. Máte však pouze jednu implementaci doménového modelu, což znamená, že bude existovat pouze jeden druh továrny, která vždy vyvolá stejné konstruktory a další inicializační kód.

    Můžete mít továrny na „pohodlí“, pokud chcete - třídy, které zapouzdřují běžné kombinace konstruktérských parametrů atd. - ale upřímně řečeno, obecně, pokud máte ve svém doménovém modelu mnoho továren, pak jen ztrácíte řádky kódu.

Takže jakmile všechny tyto trávníky odejdete, tak to prostě opustí ověření. To je jediný, který je tak složitý.

Ověření je součástí vašeho doménového modelu, ale je také součástí každé další komponenty aplikace. Vaše uživatelské rozhraní a databáze budou mít svá vlastní, podobná, ale odlišná pravidla validace, založená na podobném, ale odlišném konceptuálním modelu. Není skutečně určeno, zda objekty musejí mít metodu Validate, ale i když ano, obvykle ji delegují do třídy validátoru (ne rozhraní - ověření je ne abstrakt v doménovém modelu je to zásadní).

Mějte na paměti, že validátor je stále technicky součástí modelu; nemusí být připojen k agregovanému kořenovému adresáři, protože neobsahuje žádná data ani stav. Doménové modely jsou koncepční věci, obvykle se fyzicky překládají do Shromáždění nebo do sbírky sestav. Pokud se váš kód delegace nachází v těsné blízkosti modelu objektu, nestresujte se nad „anemickým“ problémem; stále se to počítá.

K tomu všemu opravdu patří to, že pokud se chystáte udělat DDD, musíte pochopit, co je doména . Pokud stále mluvíte o věcech, jako je vytrvalost a autorizace, jste na špatné cestě. Doména představuje běžící stav systému - fyzické a koncepční objekty a atributy. Do doménového modelu, období nepatří nic, co není přímo relevantní pro objekty a vztahy.

Při zvažování, zda něco patří do doménového modelu, se zpravidla položte následující otázka:

„Může se tato funkčnost někdy změnit z čistě technických důvodů?“ Jinými slovy, nikoli kvůli jakékoli pozorovatelné změně skutečného podnikání nebo domény?

Pokud je odpověď „ano“, pak nepatří do modelu domény. Není součástí domény.

Existuje velmi dobrá šance, že jednoho dne změníte svou infrastrukturu vytrvalosti a autorizace. Nejsou proto součástí domény, jsou součástí aplikace. To platí také pro algoritmy, jako je řazení a vyhledávání; neměli byste jít a strčit implementaci binárního vyhledávacího kódu do svého modelu domény, protože vaše doména se týká pouze abstraktní koncepce vyhledávání, nikoli toho, jak to funguje.

Pokud po odstranění všech věcí, na kterých vám nezáleží, zjistíte, že model domény je skutečně anemický , pak by to mělo sloužit jako docela dobrý náznak, že DDD je jednoduše nesprávným vzorem pro váš projekt.

Některé domény jsou skutečně anemické. Aplikace pro sociální bookmarking ve skutečnosti nemají o „doméně“ moc mluvit; všechny vaše objekty jsou v podstatě pouze data bez funkce. Na druhé straně má obchodní a CRM systém docela těžkou doménu; když načtete entitu Rate, pak existuje rozumné očekávání, že ve skutečnosti můžete dělat věci s takovou mírou, například použít na objednané množství a nechte si zjistit objemové slevy a promo kódy a všechno zábavné.

Doménové objekty, které pouze uchovávají data obvykle do znamenají, že máte anemický doménový model, ale to nutně nemusí znamená, že jste vytvořili špatný design - může to znamenat pouze to, že samotná doména je anemická a že byste měli používat jinou metodologii.

67
Aaronaught

Oprávnění. Pokud by byl doménový objekt zodpovědný za dodržování pravidel kontroly přístupu

Ne. Autorizace je sama o sobě záležitostí. Příkazy, které by nebyly platné z důvodu nedostatku oprávnění, by měly být odmítnuty před doménou co nejdříve - což znamená, že často budeme dokonce chtít zkontrolovat autorizaci potenciálního příkazu, abychom mohli sestavit UI (aby uživateli ani neukazoval možnost úpravy).

Sdílení autorizačních strategií napříč vrstvami (v uživatelském rozhraní a dále v obslužné službě nebo příkazu) je jednodušší, když je autorizace komponentizována odděleně od modelu domény.

Jednou složitou částí, na kterou lze narazit, je kontextová autorizace, kde příkaz může nebo nemusí být povolen nejen na základě uživatelských rolí, ale také obchodních dat/pravidel.

Validace. Stejná diskuse jako výše se týká validace.

Také bych řekl ne, nikoli v oblasti (většinou). K validaci dochází v různých kontextech a pravidla validace se mezi jednotlivými kontexty často liší. Při zvažování dat zapouzdřených agregátem málokdy existuje jednoduchý, absolutní smysl pro validitu nebo neplatnost.

Stejně jako autorizace používáme validační logiku napříč vrstvami - v uživatelském rozhraní, v obslužném programu nebo obslužném programu příkazů atd. Opět je jednodušší použít DRY s ověřením, pokud jde o samostatnou součást) Z praktického hlediska vyžaduje validace (zejména při použití rámců) odhalení dat, která by měla být zapouzdřena, a často vyžaduje, aby byly k polím a vlastnostem připojeny vlastní atributy. Hodně dávám přednost tomu, aby byly na jiných třídách než moje doménové modely.

Raději bych duplikoval některé vlastnosti do několika podobných tříd, než se pokusím donutit požadavky na validační rámec do mých entit. To nevyhnutelně skončí v nepořádku tříd entit.

Vytvoření objektu. Tovární třída versus tovární metody versus „nováčkování“ v instanci.

Používám jednu vrstvu přesměrování. V mých novějších projektech je to příkaz + obslužný program pro vytvoření něčeho, tj. CreateNewAccountCommand. Alternativou by mohlo být vždy použít továrnu (i když to může být nepříjemné, pokud jsou ostatní operace entity vystaveny třídě služeb, která je oddělená od tovární třídy).

Obecně se však snažím být flexibilnější při výběru návrhů pro vytváření objektů. new je snadné a známé, ale ne vždy dostačující. Myslím, že použití úsudku a umožnění různým částem systému používat různé strategie podle potřeby je důležité.

Vytrvalost. ... proč pro naši doménu nemáme metodu Uložit

To je zřídka dobrý nápad; Myslím, že existuje spousta sdílených zkušeností, které to podporují.

Pokud skončím s IAuthorizationService, IValidator, IFactory a IRepository pro můj agregovaný root, co zbude? Má metoda publikování, která mění stav objektu z konceptu na publikováno natolik, aby byla třída považována za neanemický doménový objekt ???

Možná je doménový model pro tuto část aplikace tou správnou volbou.

6
quentin-starin

Dobře, tady jde pro mě. Budu to vyprázdnit tím, že řeknu, že:

  • Předčasná optimalizace (a to včetně návrhu) může často způsobit problémy.

  • IANMF (nejsem Martin Fowler);)

  • Špinavé malé tajemství je, že na malých projektech (i když pravděpodobně na středně velkých) bude záležet na konzistenci vašeho přístupu.

Autorizace

Pro mě je autentizace a autorizace vždy průřezovým problémem. V mém šťastném malém světě Java=), který je delegován na jarní zabezpečení nebo na rámec Apache Shiro.

Validace Pro mě je validace součástí objektu, protože to považuji za definici toho, co je objekt.

např. Objekt Car má 4 kola (OK, jsou zde nějaké podivné výjimky, ale teď prozatím ignorujeme podivné 3 kolové auto). Auto prostě není platné, pokud nemá 4 (v mém světě), takže validace je součástí definice vozu. To neznamená, že nemůžete mít třídy pro pomocné ověřování.

V mém šťastném světě Java) používám ověřovací rámce Bean a používám jednoduché anotace na většině mých polí Bean. Je tedy snadné ověřit svůj objekt bez ohledu na to, v jaké vrstvě se nacházíte.

Vytvoření objekt

Prohlížím si tovární třídy s opatrností. Příliš často jsem viděl třídu xyxFactoryFactory;)

Mám sklon pouze vytvořit objekt new podle potřeby, dokud nenarazím na případ, kdy je závislost injekce zaručena (a protože se snažím dodržovat přístup TDD, toto se objevuje častěji než ne).

V mém šťastném světě Java), který je stále více Guice, ale Jaro je zde stále králem.

Perzistence

Takže toto je debata, která probíhá v kruzích a kruhových objezdech a já o tom vždycky uvažuji ve dvou myslích.

Někteří říkají, že když se podíváte na objekt „čistě“, vytrvalost není základní vlastností, je to pouze vnější zájem.

Jiní se domnívají, že vaše doménové objekty implicitně implementují rozhraní „vytrvalé“ (ano, vím, že se zde protahuji). Proto je v pořádku mít na sobě různé metody save, delete atd. Toto je viděno jako pragmatický přístup a mnoho technologií ORM (JPA v mém šťastném světě Java svět)) se tímto způsobem zabývá objekty.

Z průřezového bezpečnostního problému se ujišťuji, že oprávnění ke změně, mazání, přidávání/přidávání/cokoli jsou správně nastavena ve službě, která volá metodu uložit/aktualizovat/odstranit na objektu. Pokud jsem opravdu paranoidní, mohl bych dokonce nastavit oprávnění pro samotný objekt domény.

HTH!

4
Martijn Verburg

Jimmy Nilsson se tohoto tématu dotýká ve své knize o DDD. Začal s anemickým modelem, později přišel k neanemickým modelům a nakonec se usadil na anemických modelech. Zdůvodnil tím, že anemické modely lze znovu použít ve více službách s odlišnou obchodní logikou.

Kompromisem je nedostatek objevitelnosti. Metody, které můžete použít pro práci s vašimi anemickými modely, jsou rozloženy po celé řadě služeb, které se nacházejí jinde.

2
Todd Smith

Tato otázka byla položena již dávno, ale je označena návrhem řízeným doménou. Myslím si, že samotná otázka obsahuje zásadní nedorozumění celé praxe a odpovědi, včetně přijaté odpovědi, zachovávají zásadní nedorozumění.

V architektuře DDD neexistuje „doménový model“.

Vezměme si jako příklad autorizaci. Dovolte mi, abych vás požádal, abyste přemýšleli o otázce: představte si, že se ve vašem systému ověřují dva různí uživatelé. Jeden uživatel má oprávnění změnit určitou entitu, ale druhý ne. Proč ne?

Nesnáším jednoduché a vymyšlené příklady, protože často zaměňují více, než osvícují. Předpokládejme však, že máme dvě různé domény. První je platforma CMS pro marketingovou agenturu. Tato agentura má mnoho zákazníků, že všichni mají online obsah, který musí spravovat autoři kopií a grafici. Obsah zahrnuje blogové příspěvky i vstupní stránky pro různé zákazníky.

Druhou doménou je správa zásob pro obuvnickou společnost. Systém řídí zásoby od okamžiku, kdy dorazí od výrobce ve Francii, přes distribuční centra v kontinentálním USA, po maloobchodní prodejny na místních trzích a konečně k zákazníkovi, který nakupuje boty v maloobchodě.

Pokud si myslíte, že pravidla autorizace jsou stejná pro obě společnosti, pak ano, to by byl dobrý kandidát na službu mimo doménu. Pochybuji však, že pravidla autorizace jsou stejná. Dokonce i koncepce za uživateli by byly jiné. Určitě by to bylo jinak. Marketingová agentura má pravděpodobně role jako autor pošta a vlastník aktiv, zatímco obuvnická společnost má pravděpodobně role jako expediční úředník nebo vedoucí skladu nebo vedoucí skladu.

K těmto konceptům jsou pravděpodobně přiřazena všechna pravidla oprávnění, která je třeba modelovat v doméně. To však neznamená, že jsou součástí stejného modelu i ve stejné aplikaci. Protože si pamatujte, že existují různé ohraničené kontexty.

Možná by tedy někdo mohl považovat neanemický doménový model v kontextu autorizace za odlišný od kontextu směrování dodávek obuvi do obchodů s nízkým inventářem nebo směrování návštěvníků webu na příslušnou vstupní stránku v závislosti na reklamě, na kterou klikli.

Pokud se ocitnete s anemickými doménovými modely, možná budete muset před zahájením psaní kódu jednoduše strávit více času mapováním kontextu.

2
RibaldEddie