2012-07-19 15 views
18

Stwierdziłem, że DDD jest czymś naturalnym, jeśli pracuję nad aplikacją typu operacyjnego/transakcyjnego. Jednak zawsze mam do czynienia z rozsądnym sposobem obsługi funkcji raportowania.W jaki sposób Domain Driven Design obsługuje raportowanie?

Raportowanie, o którym mówię, nie wiąże się z generowaniem raportów, ale także z funkcjami, które wykonują stosunkowo skomplikowane zapytania. (np. podając podsumowanie wszystkich zamówień, które zrobił przedsiębiorca, lub wyświetlić podsumowanie konta dla kont handlowych mających określone akcje, itp.). Mogą to być po prostu pewne zapytania lub funkcje wspierające, które są używane razem z tymi funkcjami operacyjnymi.

Dla takich funkcji jest całkiem naturalne, jeśli możemy wykonać sprzężenie w SQL (lub innym języku zapytań), uzyskać kolumny, które nas interesują, i zwrócić masowo zestaw wyników. Wydaje się jednak, że nie ma się tak dobrze z DDD: potrzebujemy dodatkowego specjalnego repozytorium lub posiadania najbardziej powiązanego repozytorium zwracającego specjalny "obiekt/obiekt wartości" (który jest wyspecjalizowanym zbiorem wyników). Tego rodzaju specjalne "byty" nie mają w rzeczywistości żadnego znaczenia domeny.

Jeśli chcemy skorzystać ze znaczącej warstwy domenowej, może to prowadzić do wielu dodatkowych wyszukiwań z różnych repozytoriów, a także do wielu prac agregacyjnych w domenie lub warstwie usług, co z łatwością spowoduje pogarszanie się wydajności.

Pomyślałem również o posiadaniu kolejnej "ścieżki" dla tego rodzaju funkcji, która nie przechodzi przez "ścieżkę DDD", mając własny sposób pobierania danych z bazy danych, komponowania wyników do wyświetlenia. Jednak sprawi to, że aplikacja będzie niepotrzebnie skomplikowana, a co gorsza, zapewniamy dodatkową ścieżkę, aby programiści, którzy są bardziej przyzwyczajeni do tradycyjnego programowania zorientowanego na bazy danych, mogą korzystać z tej ścieżki nawet wtedy, gdy jest to niewłaściwe.

Uważam, że taka sytuacja jest dość powszechna (zwykle duży system nie zawiera funkcji operacyjnych, ale także raportowania i zapytania), chciałbym wiedzieć, jak ludzie sobie z tym radzą?

Odpowiedz

2

Niedawno zaczęliśmy używać DDD do programowania systemu. Miałem takie same obawy jak twoje, ale ostatecznie zdecydowałem się na Segregację Odpowiedzialności Zapytania (CQRS) [Fowler, Young, Dahan]. Mimo że wymaga "ścieżki db" do wysyłania zapytań, nie odczuwam wcale, że kuszenie się robi bezpośrednio do DB dla komend (tych, które zmieniają stan domeny). Oddzielenie jest bardzo jasne - polecenia przechodzą przez domenę, zapytania kierują się bezpośrednio do DB.

+0

Szczerze mówiąc, trudno jest zdecydować, który z nich jest poprawny, ale używanie CQRS wydaje się być najbardziej rozsądne (i jest to najbardziej przekonująca odpowiedź, którą otrzymuję również z domaindrivendesign.org) –

1

Jednym ze sposobów byłoby posiadanie osobnego systemu raportowania, który uruchamiałby dane ze sklepu danych aplikacji, aby przechowywać kolejną kopię danych w bardziej relacyjnym formacie.

Skrót, którego użyłem, to utworzenie widoku lub procedury przechowywanej w celu zwrócenia połączonych danych w prosty, głupi obiekt.

+0

W rzeczywistości dwie sugestie, które podjąłeś, są tym, co zasugerowałem w moim oryginalnym pytaniu. Chciałbym wyjaśnić lub uzasadnić, aby rozwiązać moje zmartwienia. I, aby podkreślić ponownie, "raportowanie", o którym mówię, nie jest konieczne, aby być "raportem", ale także niektórymi funkcjami zapytania, które są ściśle używane z funkcjami operacyjnymi. –

0

stosunkowo skomplikowane zapytania. (np. podsumowanie wszystkich zamówień, które wykonał przedsiębiorca, lub wyświetlić podsumowanie kont dla kont handlowych mających określone akcje, itp.)

Powszechnie repozytoriom jest wykonywanie takich zadań. Myślę, że martwisz się, jak skutecznie to wdrożyć, a odpowiedzią na to jest "leniwe ładowanie".

Weźmy na przykład "podsumowanie wszystkich zamówień, które zrobił przedsiębiorca". "Podsumowanie" jest zadaniem raportowania, więc odłóżmy to na bok. Zadanie domeny to "znajdź wszystkie zamówienia dla handlowca". Możliwe, że masz taką metodę repozytorium:

List<Order> findOrdersByTrader(Trader trader); 

Możesz to wdrożyć, ładując tylko minimum informacji (podsumowanie) dla każdego zamówienia. Jeśli następnie wstrzykniesz interfejs repozytorium do jednostki Order, sama jednostka może wywołać repozytorium w celu załadowania dodatkowych jednostek podrzędnych w razie potrzeby.


Aktualizacja: Twój komentarz sprawia problem jaśniej - ja źle część agregacji wcześniej. Wygląda na to, że "podsumowanie zamówień" naprawdę należy do Twojej domeny. Czasami nie jest oczywiste, że pojęcie jest częścią domeny, ale jeśli jest to funkcja, o której mówią użytkownicy ("chcę wyświetlić podsumowanie zamówień złożonych przez tego handlowca") i nie ma istniejącego obiektu, który mógłby to zrobić to znak ukrytej koncepcji w Twojej domenie. W końcu potrzebujesz jakiegoś obiektu o numerze, aby śledzić "liczbę zamówień dla każdego zasobu" i nie ma powodu, dla którego obiekt ten nie może być częścią Twojej domeny.

+1

ale właśnie to mnie niepokoi w mojej drugiej alternatywie: skorzystaj z modelu domeny i wykonaj agregacje itp. W domenie/warstwie usługi. Na przykład, funkcja musi określać, ile zamówień dla każdego stada ma przedsiębiorca. Jeśli możemy zrobić w zapytaniu, jest to prawdopodobnie "stosunkowo złożony" sql (nie jest to jednak skomplikowane), z dziesiątkami wyników. Jeśli otrzymujemy wszystkie zamówienia podmiotu handlowca i sami dokonamy agregacji, to tak, jakbyśmy otrzymywali tysiące rekordów. Różnica w wydajności jest dość oczywista (biorąc pod uwagę, że wciąż mówię w uproszczonym przypadku) –

+0

@AdrianShum: Zobacz moją aktualizację. – casablanca

18

Pod względem DDD Raportowanie w większości przypadków jest oddzielnym kontekstem ograniczonym i wspierającą poddomią, w której projekt oparty na domenie byłby przesadą. Zapamiętaj najważniejszą koncepcję DDD: Skoncentruj swoje wysiłki w zakresie modelowania na Core Domain i implementuj wszystko inne, korzystając z najprostszego możliwego rozwiązania.

Powiązane problemy