Problem z szybkością działania mam taki, że chcę żeby operacje takie jak np. oznaczenie zadania jako wykonane na agregacie wykonywały się jak najszybciej.
Dlaczego? Czyżby synchroniczny strzał z frontendu który sprawia, że strona się "zawiesza" i pojawia się spinner na czas zapisywania danych, a użytkownik sobie cierpliwie czeka?
Jeżeli performance jest twoim priorytetem to może DDD z warstwą ORM-a nie jest najlepszym rozwiązaniem w tym przypadku? Z doświadczenia czasem logika przy zapisie agregatu może być skomplikowana i trwać dłużej wtedy najlepiej wydzielić to do osobnego procesu wrzucając komendę na kolejkę i obsłużyć to dedykowanym procesem w tle, który powiadomi główną aplikację o tym, że zadanie się wykonało i wtedy userowi pojawi się wiadomość w UI, że zakończono przetwarzanie zadania.
Dlatego wrócę do mojego posta wyżej i powtórzę, że DDD pasuje do twojego problemu jak "pięść do nosa". Zadaniem taktycznego DDD jest rozwiązywanie problemów biznesowych. Każdy kto pracował trochę z DDD ci powie, że zadaniem DDD nie jest rozwiązywanie problemów wydajnościowych i że czasem aby rozwiązać problem taki jak twój (tłusty agregat), trzeba skomplikować rozwiązanie dodając przetwarzanie asynchroniczne w tle oparte o na przykład kolejki. Można też odchudzić agregat rozbijając go na mniejsze, ale wtedy dochodzi problem spójności danych bo w ramach jednej transakcji biznesowej będziesz miał dwie osobne transakcje bazodanowe (po jednej na agregat, napisałem o tym niżej) i co gdy transkacja T1 się wykona a T2 rzuci błędem? Będzie boleć bo ani baza ani ty nie zrobi automatycznie ROLLBACK na bazie i przywróci poprzedni stan. Oj nie :)
Wg mnie, to dalej nie jest optymalny model bo muszę ładować te dwie listy, więc skłaniałbym się do tego żeby rozbić to jeszcze bardziej i wtedy CompletedTask byłby również aggregate rootem.
Dalej nie rozumiesz czym jest AR. Dobry AR nie ma silnej zależności do innego AR (romb w UML-u). Innymi słowy jak masz dwa agregaty A1 i A2 to A2 ma tylko ID agregatu A1 przez co nie możesz ich zapisać ORM-em w jednej transakcji. I tak ma być bo jak napisałem wyżej jeden AR jedna transakcja.
Z tego co wiem to repozytoria robi się tylko dla agregatów no i te repozytoria mająw sobie zawierać tylko proste metody do wyciagniecia agregatu i zapisania. Więc wszelkie wyciąganie agregatów na podstawie jakiś warunków w repozytorium powinno z miejsca dawać sygnał, że coś jest nie tak. Zgodzice się?
Dokładnie tak jest bo agregat to nie jest model odczytowy, żeby go wyciągać by Id, by Email, by Start and End Date i tak dalej.
Jak masz polisę ubezpieczeniową, którą chcesz zmodyfikować to kluczem do wyciągnięcia polisy (w zależności) od designu może być
a) Id polisy rozumiane jako unikalny identyfikator np GUID
b) coś customowo wygenerowane przez system jak HUD-2332-2111-23-1
I wtedy twoje repozytorium przyjmuje takie ID (które nie musi i często nie powinno być kluczem PK bazy danych), zwraca ci agregat na którym wykonujesz logikę i zapisujesz go z powrotem do bazy.
Jak twój AR jest duży to możesz rozbić go na mniejsze ale wtedy obsługujesz je niezależnie, czyli jeżeli masz dwa agregaty A1 i A2, to przykładowo
- Pobierasz A1 z bazy za pomocą repozytorium R1
- Wykonujesz na A1 logikę
- Zapisujesz A1
- Publikujesz zdarzenie domenowe E1
- W reakcji na zdarzenie E1 listener agregatu A2 odpala dedykowany dla A2 serwis lub handler S2
- S2 pobiera z repozytorium R2 agregat A2
- Wykonuje na A2 logikę biznesową
- Zapisuje A2 do bazy za pomocą repozytorium R2
- Zastanawiasz się co zrobić jak zapis agregatu A2 się wywali i w systemie powstaną niespójne dane.
Ktoś wspomniał, że nie powninenem się interesować bazą jak robię DDD - niby tak. U mnie model domenowy jest jednocześnie modelem bazodanowym
I to jest złe podejście bo model dziedzinowy powinien wiedzieć jak najmniej o bazie danych bo jego zadaniem jest rozwiązywanie problemów biznesowych a nie bazy danych, dlatego niektórzy stosują podejście, gdzie mają osobne modele: bazodanowy i dziedzinowy. Czasem się to sprawdza, czasem nie. Zależy od use case'a.
Podsumowanie. Jak widzisz stosowanie DDD zgodnie ze sztuką wprowadza duży narzut pracy i niesamowicie komplikuje całe rozwiązanie, dlatego DDD stosuje się tam, gdzie zysk >> koszty potrzebne na jego implementację które nie są małe. W większości projektów robienie DDD sprawia że koszty >> zysk biznesowy bo zamiast skupiać się na rozwiązywaniu problemu biznesowego i dostarczeniu funkcjonalności jak najszybciej, żeby zarabiała na siebie pieniądze skupiamy się na rozwiązywaniu problemów technicznych uprawiając tzw "onanizm techniczny".
Dlatego oszczędź sobie czasu i nerwów, zrób anemiczny model dziedziny, a logikę umieść w dedykowanych serwisach bo twój przypadek to nie jest use case dla DDD.