DDD a referencje pomiędzy agregatami - C#+ EF Core

0

Cześć,

Mam pytanie bo w sumie nie do końca jestem pewny jak to poprawnie rozwiązać C# + EF Core
Sytuacja uproszczona: Mamy 2 agregaty - Item i Warehouse. Każdy z nich ma ExternalId (Guid) po to żeby identyfikować je na zewnątrz i Id bazodanowe. Item jest przypisany do Warehouse i podczas tworzenia Itemu musi być też znany Warehouse.

Czy podczas tworzenia (i updateu) itema powinno przekazywać się cały obiekt Warehouse, czy tylko jego Id (bazodanowe) ?
Np:

public Item(Warehouse warehouse,..)

czy

public Item(long warehouseId,..)

Podobnie z innymi operacjiami które wymagają tylko znajomości samego Warehousu a nie jego specyficznych właściwości.

Mam z tym problem bo z jednej strony czytam że agregat nie pownien przechowywać referencji do innego agregatu, a z drugiej przekazywanie Id bazodanowego do agregatu agregatu jest wyciekiem szczegółu implementacji (relacyjna baza jako sposób przechowywania) do domeny. Moim zdaniem lepszą opcją jest wersja pierwsza, ale poprawcie mnie jeśli się mylę.
Przekazywanie ExternalId :

public Item(Guid warehouseId,..)

nie wchodzi w grę bo w zasadzie nie rozwiązuje żadnego problemu - kluczami w bazie są id bazodanowe a nie ExternalId

1

Warehouse powinien być aggregate root, a więc posiadać kolekcję itemów. Co za tym idzie każdy item musi posiadać ID warehouse'u do którego należy. W takim przypadku nie ma nic złego w wstrzykiwaniu warehouseId przez konstruktor item'u. Item nie powinien posiadać natomiast referencji do swojego aggregate root.

0

@Aventus: Zarówno Warehouse jak i Item są osobnymi aggretage rootami. Przykład z konstruktorem jest średnio trafny. Zamiast konstruktora załóżmy metodę AssignToWarehouse po stronie Itema.
czy poprawne jest :

public void AssignToWarehouse(Warehouse warehouse,..)

czy :

public void AssignToWarehouse(long warehouseId,..)

1

Tak, uzytkownik wyzej jest trollem. Nie wdaje sie z nim w dyskusje, ale ciezko sie nie ustosunkowac jesli odnosi sie do moich wypowiedzi. Jest trollem ktory w dodatku bardzo malo wie a swoj brak wiedzy i racjonalnego myslenia probuje przerzucac na innych i siac ferment. Gdyby bylo inaczej, to ja bym byl wielokrotnie banowany a nie on. Miej to prosze na uwadze @W2K, bo moze Cie latwo wprowadzic w blad. Nawet jesli gdzies moze miec racje (co normalne) to nigdy nie mozesz byc pewny czy w konkretnej wypowiedzi tak jest, czy po prostu wcisnie Ci jakas glupote i bedziesz pozniej myslal ze to prawda. To tyle w tej kwesti, wiecej sie nie odnosze do tego dziwnego osobnika ktorego ciagnie do mnie jak nazgule do pierscienia :)

Wracajac do tematu, jesli item to rowniez aggregate root to tym bardziej nie powninen miec referencji do warehouse. Aggregate root wyznacza granice transakcyjnosci w obrebie swojego kontekstu i zapewnia spojnosc danych w tymze. Posiadanie referencji miedzy rootami bylo by pogwalceniem tej spojnosci, dla tego roots powinny miec do siebie "referencje" w postaci ID. Zmieniajac wiec warehouse item'u mozesz- tak jak wspomniales- miec po prostu jakas metode przyjmujaca ID nowego warehouse'u. Nie wiem o co codzi z tym external ID- warehouse jak i ID maja ID, nawet jesli w bazie uzywasz innych ID to w kontekscie domenowym to nie ma znaczenia. Tak wiec Twoj drugi przyklad jest wlasciwy. Zaznaczam jednak ze jest to ogolnie przyjeta praktyka a nie jakis odgorny dogmat. Nikt Cie nie powstrzyma przed wstrzyknieciem referencji obiektu, tym bardziej ja nie jestem zwolennikiem teorii "nie bo nie". Natomiast warto jednak zadac sobie pytania:

  • Czy musze miec referencje do obiektu warehouse w itemie?
  • Jesli tak to dla czego? Czy nie ryzykuje pogwalcenia transakcyjnosci miedzy tymi rootami?

W wiekszosci przypadkow nie powinno byc w ogole potrzeby posiadania referencji do innego root obiektu. W Twoim konkretnym przypadku tylko pomysl- niby jak jakas zmiana transakcyjna w obrebie itemu ma wplynac na warehouse? Przeciez nie zmienisz adresu/nazwy/cokolwiek warehouse'u zmieniajac cos w itemie ;)

3

@Arab @Aventus proszę się uspokoić. Nie zamierzam rozsądzać kto tu ma racje, bo przecież to walka sekciarzy z DDD, więc wiadomo ze nie ma tu żadnej logiki...
@W2K DDD=rak i nawet sami jego twórcy nie rozumieją pojęć i dogmatów które DDD promuje ;) Zalecam nie zawracać sobie głowy filozoficznymi dywagacjami, tylko pisać porządny kod :)

2

@Shalom:
Trochę przesadziłeś, jak widzisz napisałem wyraźnie że nie będę się odnosił do jego wypowiedzi ale ciężko w ogóle nic nie napisać skoro mnie oczernia. Gdzie widzisz walkę dwóch sekciarzy? Ja tu widzę powracajacego trolla który się uczepił. Mi nie musisz wierzyć na słowo ale spytaj @somekind i @Patryk27. Także nazywanie mnie sekciarzem mogłeś sobie darować... Dzięki za zrownywanie mnie z trollem po tych kilku latach na forum, a to wszystko bo masz swoje negatywne zdanie na temat DDD. Nie spodziewałem się czegoś takiego po wydawało by się szanowanym tutaj moderatorze. Aż się odechciewa tutaj udzielać...

5

Przepraszam, że się wtryniam w wątek, żeby nie było, scruma nie cierpię (tego dobrego, złego, średniego i w ogóle żadnego). Ale DDD zrobione pod projekt (a nie pod książkę z roku X), z Event Stormingiem (czekam aż tu zaraz ktoś pomiesza nazewnictwa i mi odpowie na coś innego, co pojawia się po słowie Event) to IMO zupełnie inna para kaloszy.

Zresztą, co ja tu ten tego, jak ktoś uważa, że to rak, to chętnie poznam jego proces rozumowania i projektowania architektury złożonej z większej ilości elementów niż 3 (mikroserwisów, monolitów, stereolitów czy czego tam) i dochodzenia do ewentualnych edge kejsów, zanim wystąpią one na poziomie pisania porządnego kodu, czyli wtedy, kiedy będzie już dawno "pozamiatane" i inwestorzy/klienci niestety nie podzielą naszego entuzjazmu, że przecież o to mamy clean code, lintery na zielono, good practik, a że koszty przepisania sporej części projektu z nienacka strzeliły nas obuchem to taki skutek uboczny.[1]

[1]Tak, tak, pamiętam - należy pisać porządny kod bez błędów... związanych z architekturą.

1

Warehouse powinien być aggregate root, a więc posiadać kolekcję itemów. Co za tym idzie każdy item musi posiadać ID warehouse'u do którego należy.

Jak to posiadać kolekcję itemów.?
Agregat root to nie jest żadną kolekcją na itemy. To aggregat Warehouse i aggregat Item ma posiadać referencje do jednego id w tym wypadku warehouseId... Mówisz tak, że nie wiadomo czy ci chodzi o encje czy o co?

W takim przypadku nie ma nic złego w wstrzykiwaniu warehouseId przez konstruktor item'u

Mówisz o przekazaniu zależności, a nie o wstrzykiwaniu. Wstrzykiwanie odbywa się na poziomie komponentów a nie przekazaniu wartości w metodzie.

Item nie powinien posiadać natomiast referencji do swojego aggregate root.

Czyli item ma posiadać warehouseId, ale nie może mieć referencji do swojego aggregate root....?

Jakiego swojego agregatu nic z tego nie rozumiem. Może ty mylisz założenia modelu...?
Przecież ewidentnie Item jest Aggregatem i Warehouse również
Ty chyba nie odróżniasz Aggregatu od Value Objectu albo Encji.
Bardzo proszę czy mógł byś się wyrazić jaśniej.?

1 użytkowników online, w tym zalogowanych: 0, gości: 1