Zajmuję się projektowaniem opartym na domenie i niektóre koncepcje, które napotykam, mają sens z pozoru, ale kiedy myślę o nich bardziej, muszę się zastanawiać, czy to naprawdę dobry pomysł.
Na przykład koncepcja agregatów ma sens. Tworzysz małe domeny własności, abyś nie musiał zajmować się całym modelem domeny.
Kiedy jednak myślę o tym w kontekście aplikacji internetowej, często odwiedzamy bazę danych, aby wycofać małe podzbiory danych. Na przykład strona może zawierać tylko liczbę zamówień wraz z linkami do kliknięcia, aby otworzyć zamówienie i zobaczyć jego identyfikatory.
Jeśli jestem zrozumienia Kruszywa rację, ja zazwyczaj korzystają z repozytorium wzór do zwracania OrderAggregate które zawierają członków GetAll
, GetByID
, Delete
, i Save
. Ok, to brzmi dobrze. Ale...
Jeśli zadzwonię do GetAll, aby wyświetlić listę wszystkich moich zamówień, wydaje mi się, że ten wzorzec wymagałby zwrócenia całej listy zagregowanych informacji, kompletnych zamówień, linii zamówień itp. Gdy potrzebuję tylko niewielkiego podzbioru tych informacji (tylko informacje w nagłówku).
Czy coś brakuje? Czy jest jakiś poziom optymalizacji, którego byś użył? Nie wyobrażam sobie, aby ktokolwiek opowiadałby się za zwracaniem całych informacji, gdy nie są one potrzebne.
Z pewnością można tworzyć takie metody w twoim repozytorium GetOrderHeaders
, ale wydaje się, że to pokonuje cel polegający na użyciu wzorca takiego jak repozytorium.
Czy ktoś może mi to wyjaśnić?
EDYTOWAĆ:
Po wielu dalszych badaniach wydaje mi się, że rozłączenie polega na tym, że czysty wzorzec repozytorium różni się od tego, co większość ludzi uważa za repozytorium.
Fowler definiuje repozytorium jako magazyn danych, który korzysta z semantyki kolekcji i ogólnie jest przechowywany w pamięci. Oznacza to utworzenie całego wykresu obiektowego.
Evans zmienia repozytorium, aby uwzględnić korzenie agregatów, a zatem repozytorium jest amputowane, aby obsługiwać tylko obiekty w agregacji.
Wydaje się, że większość ludzi myśli o repozytoriach jako o uwielbianych obiektach dostępu do danych, w których po prostu tworzysz metody uzyskiwania dowolnych danych. Nie wydaje się, aby taka była intencja, jak opisano w wzorcach architektury aplikacji korporacyjnych Fowlera.
Jeszcze inni uważają repozytorium za prostą abstrakcję używaną przede wszystkim w celu ułatwienia testowania i wyśmiewania się lub w celu oddzielenia trwałości od reszty systemu.
Wydaje mi się, że odpowiedź jest taka, że jest to znacznie bardziej złożona koncepcja, niż początkowo myślałem.
źródło
Odpowiedzi:
Nie używaj modelu domeny ani agregatów do tworzenia zapytań.
W rzeczywistości to, co zadajesz, jest dość powszechnym pytaniem, że ustanowiono zestaw zasad i wzorców, aby tego uniknąć. Nazywa się to CQRS .
źródło
Walczyłem i wciąż mam problemy z tym, jak najlepiej wykorzystać wzorzec repozytorium w projekcie opartym na domenie. Po użyciu go teraz po raz pierwszy wymyśliłem następujące praktyki:
Repozytorium powinno być proste; odpowiada tylko za przechowywanie obiektów domeny i ich odzyskiwanie. Cała inna logika powinna znajdować się w innych obiektach, takich jak fabryki i usługi domenowe.
Repozytorium zachowuje się jak kolekcja, tak jakby była kolekcją zagregowanych korzeni w pamięci.
Repozytorium nie jest ogólnym DAO, każde repozytorium ma swój unikalny i wąski interfejs. Repozytorium często ma określone metody wyszukiwania, które pozwalają przeszukiwać kolekcję pod względem domeny (na przykład: daj mi wszystkie otwarte zamówienia dla użytkownika X). Samo repozytorium można zaimplementować za pomocą ogólnego DAO.
W idealnym przypadku metody wyszukiwania zwrócą tylko zagregowane korzenie. Jeśli jest to nieefektywne, może również zwracać obiekty tylko do odczytu, niż zawierać dokładnie to, czego potrzebujesz (chociaż jest to plus, jeśli te obiekty wartości można również wyrazić w kategoriach domeny). W ostateczności repozytorium może być również używane do zwracania podzbiorów lub kolekcji podzbiorów zagregowanego katalogu głównego.
Takie wybory zależą od zastosowanych technologii, ponieważ musisz znaleźć sposób, aby najskuteczniej wyrazić swój model domeny przy użyciu zastosowanych technologii.
źródło
Nie sądzę, żeby twoja metoda GetOrderHeaders w ogóle pokonywała cel repozytorium.
DDD zajmuje się (między innymi) zapewnieniem, że dostaniesz to, czego potrzebujesz, za pomocą zagregowanego katalogu głównego (na przykład nie będziesz mieć OrderDetailsRepository), ale nie ogranicza Cię w sposób, o którym wspominasz.
Jeśli OrderHeader jest pojęciem domeny, powinieneś go zdefiniować jako taki i mieć odpowiednie metody repozytorium do ich odzyskania. Po prostu upewnij się, że przechodzisz przez prawidłowy zagregowany katalog główny.
źródło
Moje użycie DDD może nie być uważane za „czyste” DDD, ale dostosowałem następujące strategie w świecie rzeczywistym, używając DDD do magazynu danych DB.
** Nie musisz przywracać całego agregatu. Jeśli jednak chcesz uzyskać więcej, musisz zapytać użytkownika root, a nie jakiejkolwiek innej usługi lub repozytorium. Jest to leniwe ładowanie i może być wykonane ręcznie przy leniwym ładowaniu ubogiego człowieka (wstrzykiwanie odpowiedniego repozytorium / usługi do katalogu głównego) lub przy użyciu i ORM, który to obsługuje.
W twoim przykładzie prawdopodobnie podałbym wywołanie repozytorium, które przyniosło tylko nagłówki zamówień, gdybym chciał załadować szczegóły do osobnego wywołania. Zauważ, że posiadając „OrderHeader”, w rzeczywistości wprowadzamy dodatkową koncepcję do domeny.
źródło
Twój model domeny zawiera logikę biznesową w najczystszej postaci. Wszystkie relacje i operacje wspierające operacje biznesowe. To, czego brakuje ci w mapie koncepcyjnej, to idea warstwy usługi aplikacji, która warstwa usługi otacza model domeny i zapewnia uproszczony widok domeny biznesowej (jeśli jest to możliwe), który pozwala na zmianę modelu domeny w razie potrzeby bez bezpośredniego wpływu na aplikacje korzystające z warstwy usług.
Idąc dalej. Ideą agregatu jest to, że istnieje jeden obiekt, główny agregat, odpowiedzialny za utrzymanie spójności agregatu. W twoim przykładzie zamówienie będzie odpowiedzialne za manipulowanie jego wierszami zamówienia.
Na przykład warstwa usług ujawniłaby operację taką jak GetOrdersForCustomer, która zwróciłaby tylko to, co jest potrzebne do wyświetlenia listy podsumowań zamówień (jak je nazywasz OrderHeaders).
Wreszcie wzorzec repozytorium nie jest TYLKO kolekcją, ale umożliwia także deklaratywne zapytania. W języku C # możesz użyć LINQ jako Obiektu Zapytania , lub większość innych O / RM również podaje specyfikację Obiektu Zapytania.
Widząc, że możesz tworzyć zapytania na podstawie repozytorium, sensowne jest również zapewnienie wygodnych metod obsługi typowych zapytań. To znaczy, jeśli chcesz tylko nagłówki swojego zamówienia, możesz utworzyć zapytanie, które zwraca tylko nagłówek i udostępnić go z wygodnej metody w swoich repozytoriach.
Mam nadzieję, że pomoże to wyjaśnić.
źródło
Wiem, że to stare pytanie, ale wydaje się, że doszedłem do innej odpowiedzi.
Kiedy tworzę repozytorium, zwykle owija niektóre buforowane zapytania.
Trzymaj te repozytoria w swoich serwerach. Nie tylko przechodzą przez obiekty do bazy danych!
Jeśli korzystam z aplikacji internetowej ze stroną z listą zamówień, którą możesz kliknąć, aby zobaczyć szczegóły, są szanse, że chcę, aby moja strona z listą zamówień zawierała szczegółowe informacje na temat zamówień (identyfikator, nazwa, kwota, data) aby pomóc użytkownikowi zdecydować, na który chce spojrzeć.
W tym momencie masz dwie opcje.
Możesz wysłać zapytanie do bazy danych i pobrać dokładnie to, czego potrzebujesz, aby utworzyć listę, a następnie ponownie wykonać zapytanie, aby pobrać poszczególne szczegóły, które powinny być widoczne na stronie szczegółów.
Możesz wykonać 1 zapytanie, które pobiera wszystkie informacje i buforuje je. Na następnej stronie prośba czytasz z serwerów ram zamiast bazy danych. Jeśli użytkownik wróci do poprzedniej strony lub wybierze następną stronę, nadal wykonujesz zero podróży do bazy danych.
W rzeczywistości sposób, w jaki to wdrażasz, to tylko to i szczegóły implementacji. Jeśli mój największy użytkownik ma 10 zamówień, prawdopodobnie chcę przejść do opcji 2. Jeśli mówię o 10 000 zamówień, potrzebna jest opcja 1. W obu powyższych przypadkach iw wielu innych przypadkach chcę, aby repozytorium ukryło ten szczegół implementacji.
Idąc dalej, jeśli dostanę bilet informujący użytkownika, ile wydali na zamówienia ( dane zagregowane ) w ostatnim miesiącu na stronie z listą zamówień, wolałbym napisać logikę, aby obliczyć to w SQL i zrobić kolejną podróż w obie strony do DB, czy wolisz go obliczyć na podstawie danych, które są już w pamięci RAM serwerów?
Z mojego doświadczenia wynika, że agregaty domen oferują ogromne korzyści.
źródło