DDD - Czy repozytorium głównego agregatu obsługuje zapisywanie agregatów?

27

Używam podejścia podobnego do DDD dla modułu greenfield istniejącej aplikacji; nie jest to 100% DDD ze względu na architekturę, ale staram się użyć niektórych koncepcji DDD. Mam ograniczony kontekst (myślę, że to właściwy termin - wciąż uczę się o DDD) składający się z dwóch jednostek: Conversationi Message. Rozmowa jest korzeniem, ponieważ Wiadomość nie istnieje bez rozmowy, a wszystkie wiadomości w systemie są częścią rozmowy.

Mam ConversationRepositoryklasę (chociaż tak naprawdę bardziej przypomina bramę, używam terminu „repozytorium”), który znajduje konwersacje w bazie danych; gdy znajdzie konwersację, tworzy również (za pośrednictwem fabryk) listę wiadomości dla tej konwersacji (udostępnionych jako właściwość). Wydaje się to być prawidłowym sposobem radzenia sobie z różnymi rzeczami, ponieważ wydaje się, że nie ma potrzeby tworzenia pełnowymiarowej MessageRepositoryklasy, ponieważ istnieje ona tylko po odzyskaniu konwersacji.

Jednak jeśli chodzi o zapisywanie wiadomości, jest to obowiązkiem ConversationRepository, ponieważ jest to zagregowany katalog główny wiadomości? Mam na myśli to, czy powinienem mieć metodę na ConversationRepository o nazwie powiedzmy, AddMessagektóra pobiera komunikat jako parametr i zapisuje go w bazie danych? Czy powinienem mieć osobne repozytorium do wyszukiwania / zapisywania wiadomości? Logiczną rzeczą wydaje się być jedno repozytorium na jednostkę, ale słyszałem również „Jedno repozytorium na kontekst”.

Wayne Molina
źródło

Odpowiedzi:

25

Niebieski książka na pewno warto przeczytać, jeśli chcesz uzyskać najlepsze podejścia DDD. Wzorce DDD nie są trywialne, a poznanie istoty każdego z nich pomoże ci zastanowić się, kiedy użyć tego wzorca, jak podzielić aplikację na warstwy, jak zdefiniować swoje agregaty i tak dalej.

Grupa 2 encji, o których wspominasz, nie jest ograniczonym kontekstem - prawdopodobnie jest to agregat. Każdy agregat ma główny agregat, jednostkę, która służy jako pojedynczy punkt wejścia do agregatu dla wszystkich innych obiektów. Zatem nie ma bezpośredniego związku między Jednostką a inną Jednostką w innym Agregacie, który nie jest Korzeniem Agregacji.

Repozytoria są potrzebne do przechwycenia bytów, które nie są łatwo dostępne przez przechodzenie przez inne obiekty. Repozytoria zwykle zawierają zagregowane korzenie, ale mogą też istnieć repozytoria zwykłych jednostek.

W twoim przykładzie konwersacja wydaje się być korzeniem zagregowanym. Być może rozmowy są punktem początkowym twojej aplikacji, a może chcesz je zapytać o szczegółowe kryteria, aby nie były w zadowalający sposób dostępne poprzez proste przechodzenie przez inne obiekty. W takim przypadku możesz utworzyć dla nich repozytorium, które da kodowi klienta złudzenie zestawu konwersacji w pamięci, z których można wyszukiwać, dodawać lub usuwać bezpośrednio. Z drugiej strony, wiadomości można łatwo uzyskać przez przejście do konwersacji i możesz nie chcieć otrzymywać ich zgodnie ze szczegółowymi kryteriami, tylko wszystkie wiadomości z konwersacji na raz, więc mogą nie potrzebować repozytorium.

ConversationRepository będzie odgrywać rolę w utrwalaniu wiadomości, ale nie będzie tak bezpośrednią, jak wspomniałeś. Zatem nie ma AddMessage () w ConversationRepository (ta metoda raczej należy do samej Conversation), ale zamiast tego za każdym razem, gdy Repozytorium będzie utrzymywać konwersację, dobrym pomysłem jest utrzymywanie wiadomości w tym samym czasie, albo w sposób przezroczysty, jeśli używasz frameworku ORM takie jak (N) Hibernacja, używanie ad hoc SQL, jeśli tak wybierzesz itp.

guillaume31
źródło
1
Jeśli zagregowany katalog główny, taki jak Rozmowa, ma w sobie wiele różnych typów bytów, takich jak Wiadomość, Thingies i Wingies, to kiedy zapisujesz rozmowę, np. ConversationRepo.save (rozmowa), skąd wiesz, które podmioty w niej potrzebują być uratowanym? W powyższym przykładzie plakatów należy zapisać tylko jednostki wiadomości. Czy przeglądasz wszystkie możliwe kolekcje w zagregowanym katalogu głównym, aby znaleźć jednostki bez identyfikatorów?
Chris-Richards
3

Można utworzyć ConversationService i wstrzyknąć IConversationRepository i IMessageRepository w jego konstruktora. Używaj repozytoriów do prostych operacji CRUD i usług do wszystkiego innego (buforowanie, zapisywanie logiki itp.)

šljaker
źródło
1
nie zapisuje CRUD logiki?
Timothy Groote,