Keresse meg a DDD összesített gyökerét
On február 1, 2021 by adminHadd játsszák mindenki kedvenc játékát, keresse meg az Aggregátum gyökerét. Használjuk a kanonikus Ügyfél / Megrendelés / Rendelési sorok / Termék problématerületet. Hagyományosan az Ügyfél, a megrendelés és a termék az AR, amelyeknél a OrderLines a megrendelés alá tartozó entitás. A logika az, hogy azonosítania kell az ügyfeleket, a megrendeléseket és a termékeket, de a OrderLine nem létezne Rendelés nélkül. Tehát problémás tartományunkban van egy üzleti szabály, amely szerint az Ügyfélnek csak egy kézbesítetlen megrendelése lehet. egyszerre.
Ez áthelyezi a megrendelést az ügyfél összesített gyökér alá? Azt hiszem, hogy igen. De ezáltal az Ügyfél AR-ja meglehetősen nagy lesz, és később párhuzamossági problémák merülhetnek fel benne.
Vagy mi lenne, ha lenne olyan üzleti szabályunk, amely kimondja, hogy az ügyfél életében csak egyszer rendelhet meg egy adott terméket. Ez több bizonyíték arra szólítja fel az ügyfelet, hogy birtokolja a megrendelést.
De amikor ez megtörténik a szállításhoz nem a vevővel, hanem a Megrendeléssel kapcsolatos összes tevékenységüket végzik. Néma dolog, hogy az egész Megrendelőt fel kell tölteni ahhoz, hogy az egyedi Megrendelést kézbesítettnek lehessen jelölni.
Ez amit javasolok:
class Customer { public Guid Id {get;set;} public string Name { get; set; } public Address Address { get; set; } public IEnumerable<Order> Orders { get; set; } public void PlaceOrder(ThingsInTheOrder thingsInTheOrder) { // Make sure there aren"t any pending orders already. // Make sure they aren"t ordering a Widget if they"ve already ordered a Widget in the past. // Create an Order object and add it to the collection. Raise a domain event to trigger emails and other stuff } } class Order { public Guid Id { get; set; } public IEnumerable<OrderLine> OrderLines { get; set; } public ShippingData {get;set;} public void Ship(ShippedByPerson shippedByPerson, string trackingCode) { // Create a new ShippingData object and assign it from the data passed in. // Publish a domain event } }
A legnagyobb gondot a párhuzamossági probléma és az a tény képezi, hogy maga a Rend is jellemző s az összesített gyökérből.
Válasz
Melyek az összesítés meghatározásának kritériumai?
Térjünk vissza a nagy kék könyv alapjaira:
Összesítés: Olyan társított objektumok klasztere, amelyeket egységként kezelnek az adatváltozások céljából . A külső hivatkozások az AGGREGATE egy gyökérként kijelölt tagjára korlátozódnak. Az AGGREGATE határain belül egy sor konzisztencia-szabály érvényes.
A cél az invariánsok fenntartása. De a helyi identitás megfelelő kezelése is, vagyis azoknak az objektumoknak az azonosítása, amelyeknek önmagában nincs jelentése. “>
véglegesen egy ilyen fürthöz tartozik. Például:
- Egy
Order
törléséhez az összes sorának törlése szükséges. - Egy sor törléséhez szükség lehet a következő sorok újraszámozására.
- Új sor hozzáadásához meg kell határozni a nulber vonalat az azonos sorrendű összes többi sor alapján.
- Egyes rendelési információk, például a pénznem megváltoztatása befolyásolhatja a sorok árának jelentését (vagy megkövetelheti az árak újraszámítását).
Tehát itt a teljes összesítés a következetességi szabályok és az invariánsok biztosításához szükséges.
Mikor kell megállni?
Most leír néhány üzleti szabályt, és azzal érvel, hogy ezek biztosítása érdekében figyelembe kell vennie az ügyfelet az összesítés részeként:
Van egy üzletünk szabály, amely szerint az Ügyfélnek egyszerre csak egy kézbesítetlen megrendelése lehet.
Természetesen miért ne. Lássuk a következményeket: a megrendeléshez mindig az ügyfélen keresztül férhet hozzá. Ez valós élet? Amikor a dolgozók kitöltik a dobozokat a megrendelés leadásához, el kell-e olvasniuk az ügyfél vonalkódját és a megrendelés vonalkódját a megrendeléshez való hozzáféréshez ? Valójában általában egy megrendelés identitása globális és nem lokális az ügyfél számára, és ez a viszonylagos függetlenség azt sugallja, hogy őt az aggregátumon kívül kell tartani.
Ezenkívül ezek az üzleti szabályok inkább politikának tűnnek: a társaság önkényes döntése, hogy folyamatát e szabályokkal futtatja. Ha nem tartják be a szabályokat, a főnök elégedetlen lehet, de az adatok nem igazán következetlenek. Ezenkívül egyik napról a másikra ” ügyfélenként egy kézbesítetlen megrendelés egyszerre ” ” ügyfélenként tíz kézbesítetlen megrendelés ” vagy akár ” az ügyféltől függetlenül, raktáron száz kézbesítetlen megrendelés “, így előfordulhat, hogy az összesítés már nem lesz igazolható.
Válasz
Rövid változat
A DDD indoklása az, hogy a tartományi objektumok olyan absztrakciók, amelyeknek meg kell felelniük a funkcionális tartomány követelményeinek – ha a tartományi objektumok nem képesek könnyen teljesíteni ezeket a követelményeket, az azt sugallja, hogy helytelen absztrakciót használ.
A Entity Nouns ot használó domainobjektumok oda vezethet, hogy ezek az objektumok szorosan összekapcsolódnak egymással, és duzzadt „isten” objektumokká válnak, és olyan kérdéseket vethetnek fel, mint a kérdés ebben a kérdésben. mint “Hol a megfelelő hely a p msgstr “a CreateOrder metódus?”
A “megfelelő” összesített gyökér azonosításának megkönnyítése érdekében fontoljon meg egy másik megközelítést, ahol a tartományi objektumok a funkcionális magas szintű üzleti követelményeken alapulnak – azazolyan főneveket válasszon, amelyek utalnak azokra a funkcionális követelményekre és / vagy viselkedésre, amelyeket a rendszer felhasználóinak végre kell hajtaniuk.
Hosszú verzió
A DDD az OO Design megközelítése, amelynek célja a tartományi objektumok grafikonjának létrehozása a üzletben Rendszerének rétege – A tartományi objektumok felelősek a magas szintű üzleti követelmények teljesítéséért, és ideális esetben képesnek kell lenniük az adatrétegre támaszkodni olyan dolgokban, mint a mögöttes állandó adattár teljesítménye és integritása.
A megtekintés másik módja lehet a lista felsorolási pontja.
- Az entitásnevek általában adatattribútumokat javasolnak.
- A domainneveknek viselkedésre kell utalniuk.
- A DDD és az OO modellezés a funkcionális követelményeken és az alapvető tartományon / üzleti logikán alapuló absztrakciókkal foglalkozik.
- Az üzleti logikai réteg felelős a magas szintű tartományi követelmények kielégítéséért.
A DDD-vel kapcsolatos egyik általános tévhit, hogy a tartományi objektumoknak valamilyen fizikai valóságon kell alapulniuk. világ “dolog” (azaz valamilyen főnév, amelyre a való világban rámutathat, mindenféle adattal / tulajdonsággal tulajdonítva), azonban a valós dolgok adatai / attribútumai nem feltétlenül jelentenek jó kiindulópontot, amikor megpróbálják szögezni funkcionális követelményeket.
Természetesen az üzleti logikának kell használnia ezeket az adatokat, de maguknak a Domain objektumoknak absztrakcióknak kell lenniük, amelyek a funkcionális tartományi követelményeket és viselkedést képviselik.
Például; az olyan főnevek, mint a Order
vagy a Customer
, nem jelentenek semmilyen viselkedést, ezért általában nem hasznos absztrakciók az üzleti logika és a Domain objektumok ábrázolásához.
Ha olyan típusú absztrakciókat keres, amelyek hasznosak lehetnek az üzleti logika képviseletében, vegye figyelembe azokat a tipikus követelményeket, amelyeknek elvárható, hogy a rendszer teljesüljön:
- Értékesítőként én megrendelést szeretnék létrehozni egy új ügyfél számára, hogy számlát generálhassak az értékesítendő termékekről az árakkal és mennyiséggel együtt.
- Ügyfélszolgálati tanácsadóként szeretnék törölni egy függőben lévő megrendelést, hogy a A megrendelést a Raktárkezelő nem teljesíti.
- Ügyfélszolgálati tanácsadóként szeretnék visszaküldeni egy rendelési sort, hogy a termék beállítható legyen a készletbe, és a fizetés visszatérítésre kerüljön az ügyfél eredeti fizetésén keresztül. módszer.
- Raktárkezelőként szeretnék megtekinteni egy függőben lévő megrendelés összes termékét és a szállítási információkat, hogy kiválaszthassam a termékeket és a futár útján szállíthassam őket.
- stb.
Domainkövetelmények modellezése DDD megközelítéssel
A fenti lista alapján vegye figyelembe néhány lehetséges tartományi objektumot ts egy ilyen Orders rendszer esetében:
SalesOrderCheckout PendingOrdersStream WarehouseOrderDespatcher OrderRefundProcessor
Tartományobjektumként ezek olyan absztrakciókat jelentenek, amelyek a viselkedési tartomány különféle követelményeinek tulajdonjogát képezik; főneveik erősen utalnak az általuk teljesített konkrét funkcionális követelményekre.
(Lehet, hogy ott is van további infrastruktúra, például egy EventMediator
értesítések azoknak a megfigyelőknek, akik tudni akarják, mikor jött létre egy új megrendelés, vagy mikor küldtek megrendelést stb.).
Például SalesOrderCheckout
valószínűleg kezelni az ügyfelekről, a szállításról és a termékekről szóló adatokat, azonban nem foglalkozik a szállítási megrendelések, a függőben lévő megrendelések válogatásával vagy a visszatérítések kiadásával kapcsolatos magatartással.
For SalesOrderCheckout
domain követelményeinek teljesítése magában foglalja ezen üzleti szabályok betartatását, például megakadályozza az ügyfelek számára, hogy túl sok terméket rendeljenek, esetleg végezzenek valamilyen ellenőrzést, és esetleg értesítéseket küldjenek a rendszer más részeire vonatkozóan – mindezeket megteheti anélkül, hogy feltétlenül szüksége lenne a bármelyik másik objektum.
DDD Entity Nouns használatával a domain objektumok ábrázolásához
Ther Ezek számos potenciális veszélyt jelentenek az egyszerű főnevek, például Order
, Customer
és Product
tartományi objektumokként; ezen problémák között vannak azok, amelyekre a kérdésben utal:
- Ha egy módszer egy
Order
elemet kezel, akkor egyCustomer
és egyProduct
, melyik Domainobjektumhoz tartozik? - Hol található az összesített gyökér ennek a 3 objektumnak?
Ha a entitásneveket választja a tartományobjektumok képviseletére, akkor számos dolog történhet:
-
Order
, ésProduct
veszélyben van, hogy” isten “objektummá nőnek - Egyetlen Isten-objektum, hogy mindent összekössön.
- Ezek az objektumok azt a kockázatot jelenthetik, hogy szorosan összekapcsolódnak egymással – nehéz lehet teljesíteni a tartomány követelményeit anélkül, hogy átadnák a
this
(vagyself
) - A “szivárgó” absztrakciók – pl.a tartományobjektumok várhatóan tucatnyi
get
/set
metódust tesznek ki, amelyek gyengítik a kapszulázást (vagy ha nem, akkor más programozó valószínűleg később …). - Annak a kockázata, hogy a Domainobjektumok felduzzadnak az üzleti adatok (pl. felhasználói adatok bevitele felhasználói felületen keresztül) és az átmeneti állapot (pl. a felhasználói műveletek “előzményei”) összetett keverékével amikor a sorrendet módosították).
DDD, OO Design és sima modellek
A DDD és az OO Design kapcsán gyakori tévhit, hogy a “sima” modellek valahogy ” rossz “vagy” anti-minta “. Martin Fowler cikket írt a vérszegénység-tartomány modellről – de ahogy a cikkben világossá teszi, a DDD-nek is nem “ellentmond” a rétegek közötti tiszta elválasztás megközelítésének.
“Azt is érdemes hangsúlyozni, hogy a viselkedésnek a domain objektumokba való beillesztése nem mondhat ellent az a szilárd megközelítés, hogy a réteget használjuk a szepához értékelje a domain logikáját olyan dolgokból, mint a kitartás és a bemutatási felelősség A tartományobjektumban szereplő logika a tartománylogika – ellenőrzések, számítások, üzleti szabályok – bárhogy is hívja. “
Más szavakkal, a sima modellek használata a más rétegek között továbbított üzleti adatok (pl. Egy felhasználói alkalmazás által átadott Rendelési modell, amikor a felhasználó új megrendelést akar létrehozni) használata nem ugyanaz, mint az „anémiás tartománymodell”. A “sima” adatmodellek gyakran a legjobb módszerek az adatok nyomon követésére és az adatok rétegek közötti átvitelére (például REST webszolgáltatás, perzisztencia tároló, alkalmazás vagy felhasználói felület stb.).
Az üzleti logika feldolgozhatja a adatok ezekben a modellekben, és nyomon követhetik őket az üzleti állapot részeként – de nem feltétlenül veszi át a tulajdonjogát ezeknek a modelleknek.
Az összesített gyökér
Újra megnézve a példa tartományobjektumokat – SalesOrderCheckout
, PendingOrdersStream
, WarehouseOrderDespatcher
, OrderRefundProcessor
még mindig nincs nyilvánvaló összesített gyökér, de ez így van Ez valójában nem számít, mert ezeknek a Domain Objektumoknak vadonatúj feladataik vannak, amelyek nem látszanak átfedésben.
Funkcionálisan nincs szükség arra, hogy a SalesOrderCheckout
beszéljen a PendingOrdersStream
vel, mert az előbbi feladata akkor fejeződik be, amikor új rendelést adott hozzá az adatbázishoz; másrészt a PendingOrdersStream
lekérheti az új megrendeléseket az adatbázisból. Ezeknek az objektumoknak valójában nem kell kölcsönhatásba lépniük mindegyikkel közvetlenül más (Talán egy Eseményközvetítő értesítéseket küldhet a kettő között, de azt várnám, hogy az objektumok közötti összekapcsolás nagyon laza lesz)
Talán az összesített gyökér egy IoC-tároló lesz, amely egy vagy több ezek a tartományobjektumok egy felhasználói felület vezérlőjébe, más infrastruktúrát is ellátva, például EventMediator
és Repository
. Vagy talán valamilyen könnyű Orchestrator Service ül majd az üzleti réteg tetején.
Az összesített gyökérnek nem feltétlenül kell objektumnak lennie. A tartományobjektumok közötti aggályok elválasztásának megőrzése érdekében általában jó dolog, ha az összesítés A root egy külön logika nélküli objektum.
Megjegyzések
- Lemondtam a szavazatokat, mert válasza összemossa az Entity Framework fogalmakat, amely egy Microsoft-specifikus technológia, és a domain alapú tervezéssel, amely egy könyvből származik. az azonos nevű Eric Evans írta. Van néhány olyan állítás a válaszodban, amelyek közvetlenül ellentmondanak a DDD könyvnek, és ez a kérdés nulla említést tesz az Entity Framework-ről, de kifejezetten DDD-vel van ellátva. ‘ s egyáltalán nem említi a kitartást a kérdésben, ezért nem látom ‘ t, hogy az adatbázis-táblák hol relevánsak.
- @RibaldEddie Köszönöm, hogy időt szánt a válasz és a megjegyzés áttekintésére, egyetértek a tartós adatok megemlítésével nem kell ‘ valóban szerepelnie a válaszban, ezért ‘ ezt átfogalmazva eltávolította ezt. A válasz fókuszát úgy lehet összefoglalni, hogy ” Entitásnevek gyakran ‘ nem nagyon jó Domain Object osztálynevek, szorosan összekapcsolt dagadt istenobjektummá válnak “, remélhetőleg a WRT funkcionális követelményeinek / viselkedésének az üzenete és érvelése egyértelműbb?
- A DDD könyv nem ‘ nincs ez a koncepció IIRC. Vannak Entitásai, amelyek pusztán olyan osztályok, amelyek példányosításakor állandó és egyedi identitásuk van, így két elválasztott példány két egyedi és tartósan képes dolgot jelent, ami ellentétben áll az Értékobjektumokkal, amelyek nem ‘ nincs személyazonosságuk, és nem maradnak fenn az idõben. A könyvben mind az Entitások, mind az Érték objektumok tartományi objektumok.
Válasz
a problémás tartományunkban, üzleti szabály, miszerint az Ügyfélnek egyszerre csak egy kézbesítetlen megrendelése lehet.
Mielőtt túl mélyen elmennél abba a nyúllyukba, át kell nézned Greget A (z) készlet konzisztenciájának megbeszélése és különösen:
Milyen üzleti hatása van a kudarcnak?
Mivel sok esetben a helyes válasz nem próbálja megakadályozni rossz dolog történhet, ehelyett kivételjelentéseket generál , ha probléma merülhet fel.
De feltételezve, hogy több kézbesítetlen megrendelés is jelentős felelősség a vállalkozása iránt ….
Igen, ha meg akarja győződni arról, hogy csak egy kézbesítetlen megrendelés van, akkor valamilyen összesítésre van szükség, amely az ügyfél összes megrendelését láthatja .
Ez az összesítés nem feltétlenül az ügyfél összesítése .
Lehet, hogy valami olyan, mint egy rendelési sor vagy egy rendelési előzmény, ahol egy adott rendelés összes rendelése vevő ugyanabba a sorba kerül. Amit mondott, annak nincs szüksége az ügyfél összes profiladatára, így annak nem kellene része lennie ennek az összesítésnek.
De amikor a szállításról van szó, akkor a megrendeléssel kapcsolatos összes tevékenységüket nem az ügyfél, hanem a megrendelés során hajtják végre.
Igen, amikor Ön valóban teljesítéssel dolgozik és lapok húzása, az előzmény nézet nem különösebben releváns.
Az előzmény nézetnek az invariánsának érvényesítéséhez csak a rendelésazonosítóra és annak aktuális feldolgozási állapotára van szüksége. Ennek nem feltétlenül kell ugyanannak az aggregátumnak lennie, mint a megrendelés – ne feledje, az összesített határok a változás kezeléséről szólnak, nem pedig a nézetek strukturálásáról.
Tehát előfordulhat, hogy a sorrendet összesítettként kezeli. és a rendelési előzményeket önálló összesítésként, és koordinálja a tevékenységet a kettő között.
Válasz
Beállította szalma ember példa. Túl egyszerű, és kétlem, hogy a valós rendszert tükrözi. Nem modellezném ezeket az entitásokat és a hozzájuk kapcsolódó viselkedést az általad megadott módon.
Az osztályainak meg kell modellezni a egy megrendelés állapota oly módon, amely több aggregátumban is megjelenik. Például amikor az ügyfél a rendszert abba az állapotba hozza, ahol az ügyfél megrendelési kérelmét feldolgozni kell, akkor létrehozhatok egy
vagy vagy akár csakCustomerOrder
, vagy bármilyen nyelvet használ az üzlet, és ez mutatót tarthat mind az Ügyfél, mind a OrderLines számára, és ezután rendelkezhet olyan módszerrel, mint acanCustomerCompleteOrder()
, amelyet a szolgáltatási réteg hív meg.
Ez a tartományobjektum tartalmazza az üzleti logikát annak megállapításához, hogy a megrendelés érvényes-e.
Ha a megrendelés érvényes és feldolgozott lenne, akkor lenne valamilyen módom az objektum átállítására egy másik objektumra, amely a feldolgozott sorrendet képviselné.
Úgy gondolom, hogy a megértésével az a probléma, hogy egy kitaláltat használ túlságosan leegyszerűsített példa az aggregátumokról. Egy PendingOrder
lehet saját aggregátuma, elkülönítve egy UndeliveredOrder
-től, és elkülönülve egy vagy egy CancelledOrder
vagy bármi más.
Megjegyzések
- Bár a kísérlet A nemi szempontból semleges nyelv mulatságos, megjegyezném, hogy a nők soha nem állnak a mezőkön a varjak elriasztására.
- @RobertHarvey, hogy ‘ furcsa dolog, amire összpontosítani kell a hozzászólásomban. A madárijesztők és a képmások mind rendszeresen női formában jelentek meg a történelem során.
- Nem tettél volna megkülönböztetést a bejegyzésedben, ha nem tetted volna meg ‘ nem tartja fontosnak. Nyelvészeti szempontból a kifejezés ” szalmabogár; ” a szexizmussal kapcsolatos minden fenntartást szinte biztosan megdönti a ” miről beszél a saját kifejezésének kitalálásával létrehozott ” tényezőről.
- @RobertHarvey, ha valaki tudja, milyen szalma az ember azt jelenti, hogy én ‘ biztos vagyok abban, hogy ki tudják találni, mit jelent a szalma ember, ha nem hallanak ‘ ezt a kifejezést. Koncentrálhatunk a hozzászólásom lényegére, kérem, írja be a szoftvert?
Válasz
Vaughn Vernon ezt említi “A tartományvezérelt tervezés megvalósítása” című könyv a 7. fejezet elején (Szolgáltatások):
“Gyakran a legjobb jelzés arra, hogy a tartománymodellben létre kell hozni egy szolgáltatást, amikor az elvégzendő művelet nem érzi jól magát hely metódusként egy összesített elemen vagy egy értékobjektumon “.
Tehát ebben az esetben létezhet egy “CreateOrderService” nevű tartományi szolgáltatás, amely felveszi az Ügyfél példányát és a rendelés tételek listáját.
class CreateOrderService { public Order CreateOrder(Customer customer, ThingsInTheOrder thingsInTheOrder) { // Get all the orders for the customer // Check if any of the things to be ordered exist in previous orders // If none have been previously ordered, create the order and return it // Otherwise return null } }
Megjegyzések
- Tudná elmagyarázni, hogy a domain szolgáltatás hogyan segíthet a kérdésben a párhuzamossági problémák kezelésében?
Vélemény, hozzászólás?