it-swarm-eu.dev

Jsou DDD agregáty opravdu dobrý nápad ve webové aplikaci?

Ponořuji se do Domain Driven Design a některé z konceptů, na které narazím, mají na povrchu hodně smysl, ale když o nich přemýšlím více, musím si položit otázku, jestli je to opravdu dobrý nápad.

Například koncept agregátů má smysl. Vytváříte malé domény vlastnictví, takže se nemusíte zabývat celým modelem domény.

Když si však o tom myslím v souvislosti s webovou aplikací, často zasáhneme databázi, abychom stáhli malé podmnožiny dat. Například stránka může uvádět pouze počet objednávek, s odkazy, na které kliknete, otevře objednávku a zobrazí její ID objednávky.

Pokud chápu správně agregované soubory, obvykle bych použil vzor úložiště k vracení OrderAggregate, který by obsahoval členy GetAll, GetByID, Delete a Save. Dobře, to zní dobře. Ale...

Pokud zavolám GetAll, abych vypsal všechny své objednávky, zdá se mi, že by tento vzor vyžadoval vrácení celého seznamu agregovaných informací, kompletních objednávek, řádků objednávek atd. Když potřebuji pouze malou podmnožinu těchto informací (pouze informace v záhlaví).

Uniká mi něco? Nebo existuje určitá úroveň optimalizace, kterou byste zde použili? Nedokážu si představit, že by někdo obhajoval vrácení celých agregátů informací, když je nepotřebujete.

Určitě by se dalo ve vašem úložišti vytvořit metody, jako je GetOrderHeaders, ale zdá se, že to na prvním místě znemožňuje použití vzoru, jako je úložiště.

Může mi to někdo objasnit?

ÚPRAVA:

Po mnohem dalším výzkumu si myslím, že odpojení je, že čistý vzor úložiště se liší od toho, co většina lidí považuje za úložiště.

Fowler definuje úložiště jako úložiště dat, které používá sémantiku sběru, a je obecně uchováván v paměti. To znamená vytvoření grafu celého objektu.

Evans mění úložiště tak, aby obsahovalo agregované kořeny, a úložiště se tedy amputuje, aby podporovalo pouze objekty v agregované soustavě.

Zdá se, že většina lidí uvažuje o repozitářích jako o oslavovaných objektech přístupu k datům, kde stačí vytvořit metody, jak získat jakákoli požadovaná data. To se nezdá být záměrem, jak je popsáno ve vzorcích Fowlerovy vzory podnikové aplikační architektury.

Ještě jiní si myslí, že úložiště je jednoduchá abstrakce používaná primárně k usnadnění testování a zesměšňování, nebo k oddělení perzistence od zbytku systému.

Myslím, že odpověď je, že se jedná o mnohem komplexnější koncept, než jsem si původně myslel.

43
Erik Funkenbusch

Nepoužívejte svůj doménový model a agregáty pro dotazování.

Ve skutečnosti je to, co se ptáte, dostatečně obyčejná otázka, že byl zaveden soubor zásad a vzorců, abychom tomu zabránili. Jmenuje se CQRS .

31
quentin-starin

Snažil jsem se a stále se potýkám s tím, jak nejlépe využít vzor úložiště v návrhu řízeném doménou. Po prvním použití jsem přišel s následujícími praktikami:

  1. Úložiště by mělo být jednoduché; je zodpovědný pouze za ukládání doménových objektů a jejich načítání. Veškerá další logika by měla být v jiných objektech, jako jsou továrny a doménové služby.

  2. Úložiště se chová jako kolekce, jako by se jednalo o paměť agregovaných kořenů v paměti.

  3. Úložiště není obecný DAO, každé úložiště má své jedinečné a úzké rozhraní. Úložiště má často specifické metody Finder, které vám umožňují prohledávat kolekci z hlediska domény (například: dejte mi všechny otevřené příkazy pro uživatele X). Samotné úložiště může být implementováno pomocí generického DAO.

  4. V ideálním případě metody Finder vrátí pouze agregované kořeny. Pokud je to neefektivní, může také vrátit hodnoty pouze pro čtení, než obsahovat přesně to, co potřebujete (i když je to plus, pokud lze tyto hodnotové objekty vyjádřit také v doméně). Jako poslední možnost lze úložiště použít také k vrácení podskupin nebo sbírek podskupin agregovaného kořenového adresáře.

  5. Volby, jako jsou tyto, závisí na použitých technologiích, protože musíte najít způsob, jak co nejúčinněji vyjádřit model vaší domény s použitými technologiemi.

8
Kdeveloper

Nemyslím si, že vaše metoda GetOrderHeaders vůbec neporuší účel úložiště.

DDD se zajímá (mimo jiné) o zajištění toho, že dostanete to, co potřebujete, prostřednictvím agregovaného kořenového adresáře (například byste neměli OrderDetailsRepository), ale neomezuje vás způsobem, jakým se zmiňujete.

Pokud je OrderHeader doménovým konceptem, měli byste ho mít definovaný jako takový a mít vhodné metody úložiště pro jejich načtení. Když to děláte, ujistěte se, že procházíte správným agregovaným kořenem.

6
Eric King

Moje použití DDD nemusí být považováno za „čisté“ DDD, ale upravil jsem následující strategie skutečného světa pomocí DDD proti DB datovému úložišti.

  • Agregovaný kořen má přidružené úložiště
  • Přidružené úložiště používá pouze tento agregovaný kořen (není veřejně dostupné)
  • Úložiště může obsahovat dotazy na dotazy (např. GetAllActiveOrders, GetOrderItemsForOrder)
  • Služba odhaluje veřejnou podmnožinu úložiště a další operace bez kriminálu (např. Převod peněz z jednoho bankovního účtu na druhý, LoadById, vyhledávání/vyhledávání, CreateEntity atd.).
  • Používám Root -> Service -> Repository stack. Služba DDD je používána pouze pro vše, co nemůže entita sama odpovědět (např. LoadById, TransferMoneyFromAccountToAccount), ale ve skutečném světě mám tendenci se držet i dalších služeb souvisejících s CRUD (Uložit, Smazat, Dotaz), i když root by měl být schopen „odpovědět/provést“ je sám. Uvědomte si, že není nic špatného s poskytováním přístupu subjektu k jiné agregované kořenové službě! Nezapomeňte však, že byste nezahrnovali službu (GetOrderItemsForOrder), ale zahrnuli byste ji do úložiště, aby ji mohla použít agregovaná kořenová složka. Služba by neměla vystavovat žádné otevřené dotazy, jako je úložiště.
  • Obvykle definuji úložiště abstraktně v doménovém modelu (prostřednictvím rozhraní) a poskytuji samostatnou konkrétní implementaci. Plně definuji službu v doménovém modelu vstřikování do konkrétního úložiště pro její použití.

** Nemusíte přinést zpět celý agregát. Pokud však chcete více, musíte se zeptat kořenového adresáře, nikoli jiné služby nebo úložiště. Toto je líné načtení a může být provedeno ručně se špatným líným načtením člověka (injektování příslušného úložiště/služby do kořenového adresáře) nebo pomocí a ORM, které to podporuje.

Ve vašem příkladu bych pravděpodobně poskytl volání úložiště, které přineslo pouze záhlaví objednávek, pokud bych chtěl načíst podrobnosti do samostatného hovoru. Mějte na paměti, že tím, že máme „OrderHeader“, vlastně do domény zavádíme další koncept.

4
Mike Rowley

Váš doménový model obsahuje obchodní logiku ve své nejčistší podobě. Všechny vztahy a operace, které podporují obchodní operace. Co vám chybí na vaší koncepční mapě, je myšlenka aplikační servisní vrstva servisní vrstva se ovine kolem doménového modelu a poskytuje zjednodušené zobrazení obchodní domény (projekce, pokud budete), která umožňuje model domény se podle potřeby mění bez přímého dopadu na aplikace využívající servisní vrstvu.

Jdeme dál. Myšlenka agregátu je, že existuje jeden objekt, kořen agregátu, zodpovědný za udržování konzistence agregátu. Ve vašem příkladu by objednávka odpovídala za manipulaci s řádky objednávky.

Pro příklad například vrstva služeb odhalí operaci, jako je GetOrdersForCustomer, která vrátí pouze to, co je potřeba pro zobrazení souhrnného výpisu objednávek (jak jim říkáte OrderHeaders).

Konečně vzor úložiště není JUST kolekcí, ale také umožňuje deklarativní dotazy. V C # můžete použít LINQ jako Query Object , nebo většina ostatních O/RM poskytuje také specifikaci Query Object.

Úložiště zprostředkovává mezi vrstvami mapování domény a mapování dat a chová se jako kolekce objektů domény v paměti. Klientské objekty sestavují specifikace dotazů deklarativně a odešlou je do úložiště ke spokojenosti. (z stránka Fowlerova úložiště )

Vzhledem k tomu, že můžete vytvářet dotazy proti úložišti, je také rozumné poskytnout metody pohodlí, které zpracovávají běžné dotazy. Tj. pokud chcete pouze záhlaví vaší objednávky, můžete vytvořit dotaz, který vrací pouze záhlaví a vystavit jej pohodlnému způsobu v úložištích.

Doufám, že to pomůže objasnit věci.

3
Michael Brown

Vím, že je to stará otázka, ale zdá se, že jsem přišel na jinou odpověď.

Když vytvořím úložiště, obvykle zabalí některé v mezipaměti dotazy.

Fowler definuje úložiště jako úložiště dat, které používá sémantiku sběru, a je obecně uchováván v paměti. To znamená vytvoření grafu celého objektu.

Uchovávejte tyto úložiště ve svých serverech. Nejsou to jen procházet objekty do databáze!

Pokud jsem ve webové aplikaci s objednávkami se seznamem stránek, na které můžete kliknout, abyste viděli podrobnosti, je pravděpodobné, že budu chtít, aby moje stránka se seznamem objednávek měla podrobnosti o objednávkách (ID, jméno, částka, datum) pomoci uživateli rozhodnout se, na kterého z nich se chtějí podívat.

Nyní máte dvě možnosti.

  1. Můžete vyhledávat v databázi a stahovat přesně to, co potřebujete k vytvoření seznamu, a poté znovu dotazovat a vytáhnout jednotlivé podrobnosti, které byste měli vidět na stránce podrobností.

  2. Můžete vytvořit 1 dotaz, který stáhne zpět všechny informace a uloží je do mezipaměti. Na další stránce požádejte, abyste místo databáze přečetli ze serveru ram. Pokud uživatel narazí zpět nebo vybere další stránku, stále děláte nulové výlety do databáze.

Ve skutečnosti, jak to implementujete, je to právě toto a detaily implementace. Pokud má můj největší uživatel 10 objednávek, pravděpodobně chci jít s možností 2. Pokud mluvím 10 000 objednávek, je nutná volba 1. V obou výše uvedených případech a v mnoha dalších případech chci, aby úložiště skrývalo tento implementační detail.

Do budoucna, pokud dostanu lístek, který uživateli sdělí, kolik utratili za objednávky ( agregovaná data ) za poslední měsíc na stránce se seznamem objednávek, bych raději napsat logiku pro výpočet, že v SQL a udělat ještě další zpáteční cestu do DB, nebo byste raději spočítat pomocí dat, která je již v serverech RAM?

Podle mých zkušeností nabízejí agregáty domén obrovské výhody.

  • Jsou to obrovské opakované použití kódu části, které ve skutečnosti funguje.
  • Zjednodušují kód tím, že udržují obchodní logiku přímo v základní vrstvě namísto toho, aby museli procházet vrstvou infrastruktury, aby to server SQL umožnil.
  • Mohou také výrazně zkrátit dobu odezvy snížením počtu dotazů, které potřebujete udělat, protože je můžete snadno ukládat do mezipaměti.
  • SQL, který píšu, je často mnohem lépe udržovatelný, protože často požaduji všechno a počítám na straně serveru.
0
WhiteleyJ