Nurkuję w projektowaniu opartym na domenie (DDD) i chociaż zagłębiam się w to, jest kilka rzeczy, których nie rozumiem. Jak rozumiem, głównym celem jest rozdzielenie logiki domeny (logiki biznesowej) od infrastruktury (DB, system plików itp.).
Zastanawiam się, co się dzieje, gdy mam bardzo złożone zapytania, takie jak Zapytanie dotyczące obliczania zasobów materialnych? W tego rodzaju zapytaniach pracujesz z ciężkimi operacjami ustawiania, dla których SQL został zaprojektowany. Wykonywanie tych obliczeń w warstwie domeny i praca z wieloma zestawami jest jak wyrzucenie technologii SQL.
Wykonywanie tych obliczeń w infrastrukturze również nie może się zdarzyć, ponieważ wzorzec DDD pozwala na zmiany w infrastrukturze bez zmiany warstwy domeny i wiedząc, że MongoDB nie ma takich samych możliwości jak np. SQL Server, co nie może się zdarzyć.
Czy to pułapka na wzór DDD?
źródło
... is like throwing away the SQL technology
To, że dana technologia może coś zrobić, nie oznacza, że jest to najlepszy wybór. To niepotwierdzone dowody, ale spotkałem o wiele za dużo firm, które przechowywały logikę biznesową w bazie danych i migrują z niej z powodu długotrwałych problemów związanych z utrzymaniem. Uproszczenie, ale bazy danych służą do przechowywania danych, a języki programowania służą do przekształcania danych. Nie chciałbym używać bazy danych do logiki biznesowej, niż chciałbym użyć mojej aplikacji do bezpośredniego przechowywania danych.Odpowiedzi:
Obecnie prawdopodobnie odczyty (zapytania) będą obsługiwane inaczej niż zapisy (polecenia). W systemie ze skomplikowanym zapytaniem jest mało prawdopodobne, aby samo zapytanie przeszło przez model domeny (który jest przede wszystkim odpowiedzialny za utrzymanie spójności zapisów ).
Masz absolutną rację, że powinniśmy renderować w SQL to, co jest SQL. Dlatego zaprojektujemy model danych zoptymalizowany wokół odczytów, a zapytanie tego modelu danych zwykle będzie zawierało ścieżkę kodu, która nie obejmuje modelu domeny (z możliwym wyjątkiem pewnej weryfikacji danych wejściowych - zapewniając parametry w zapytaniu są rozsądne).
źródło
To jest podstawa nieporozumienia: celem DDD nie jest rozdzielanie rzeczy twardą linią, np. „To jest na serwerze SQL, więc nie może być BL”, celem DDD jest oddzielanie domen i tworzenie barier między te, które pozwalają, aby elementy wewnętrzne domeny były całkowicie oddzielone od elementów wewnętrznych innej domeny i definiowały wspólne elementy zewnętrzne między nimi.
Nie myśl o „byciu w SQL” jak o barierze BL / DL - nie o to chodzi. Zamiast tego pomyśl o „to koniec domeny wewnętrznej” jako o barierze.
Każda domena powinna mieć zewnętrzne interfejsy API, które pozwolą jej współpracować ze wszystkimi innymi domenami: w przypadku warstwy przechowywania danych powinny mieć akcje odczytu / zapisu (CRUD) dla przechowywanych obiektów danych. Oznacza to, że sam SQL nie jest tak naprawdę barierą,
VIEW
aPROCEDURE
komponenty są. Nigdy nie powinieneś czytać bezpośrednio z tabeli: to jest szczegół implementacji DDD mówi nam, że jako konsument zewnętrzny nie powinniśmy się martwić.Rozważ swój przykład:
To jest dokładnie to, co powinno być w SQL, i to nie jest naruszenie DDD. Do tego stworzyliśmy DDD . Dzięki tym obliczeniom w SQL staje się ono częścią BL / DL. Co byś zrobił, to użyć oddzielnego view / procedura przechowywana / co-ma-ty, i zachować logika biznesowa oddzielona od warstwy danych, jako że to zewnętrzny interfejs API. W rzeczywistości warstwa danych powinna być kolejną warstwą domeny DDD, w której warstwa danych ma własne abstrakty do pracy z innymi warstwami domeny.
To kolejne nieporozumienie: mówi, że szczegóły implementacji mogą ulec zmianie bez zmiany innych warstw domeny. Nie oznacza to, że możesz po prostu wymienić cały element infrastruktury.
Ponownie, należy pamiętać, że DDD polega na ukrywaniu elementów wewnętrznych za pomocą dobrze zdefiniowanych zewnętrznych interfejsów API. To, gdzie są te interfejsy API, jest zupełnie innym pytaniem, a DDD tego nie definiuje. Określa po prostu, że te interfejsy API istnieją i nigdy nie powinny się zmieniać .
DDD nie jest skonfigurowane tak, aby umożliwić ad hoc zastępowanie MSSQL MongoDB - są to dwa zupełnie różne elementy infrastruktury.
Zamiast tego zastosujmy analogię do tego, co definiuje DDD: benzyna vs. samochody elektryczne. Oba pojazdy mają dwie zupełnie różne metody tworzenia napędu, ale mają te same API: włączanie / wyłączanie, przepustnicę / hamulec i koła do napędzania pojazdu. DDD mówi, że powinniśmy być w stanie wymienić silnik (gazowy lub elektryczny) w naszym samochodzie. Nie oznacza to, że możemy zastąpić samochód motocyklem, i tak właśnie jest MSSQL → MongoDB.
źródło
Jeśli kiedykolwiek brałeś udział w projekcie, w którym organizacja płacąca za hostowanie aplikacji uzna, że licencje warstwy bazy danych są zbyt drogie, docenisz łatwość migracji bazy danych / magazynu. Biorąc wszystko pod uwagę, chociaż tak się dzieje, nie zdarza się to często .
Możesz powiedzieć, co najlepsze z obu światów. Jeśli rozważasz wykonywanie złożonych funkcji w bazie danych jako optymalizację, możesz użyć interfejsu, aby wprowadzić alternatywną implementację obliczeń. Problem polega na tym, że musisz utrzymywać logikę w wielu lokalizacjach.
Odbiegając od wzoru architektonicznego
Jeśli znajdziesz się w sprzeczności z implementacją wzorca lub odejściem w jakimś obszarze, musisz podjąć decyzję. Wzór to po prostu szablonowy sposób robienia rzeczy, które pomagają zorganizować projekt. W tym momencie poświęć czas na ocenę:
Przekonasz się, że niektóre wzory architektoniczne dobrze pasują do 80-90% twojej aplikacji, ale nie tak bardzo do pozostałych bitów. Sporadyczne odstępstwa od zalecanego wzoru są przydatne ze względów wydajnościowych lub logistycznych.
Jeśli jednak okaże się, że skumulowane odchylenia stanowią ponad 20% architektury aplikacji, prawdopodobnie jest to po prostu złe dopasowanie.
Jeśli zdecydujesz się kontynuować architekturę, zrób sobie przysługę i udokumentuj, gdzie i dlaczego odstąpiłeś od zalecanego sposobu robienia rzeczy. Gdy zyskasz nowego entuzjastycznego członka swojego zespołu, możesz wskazać mu tę dokumentację, która zawiera pomiary wydajności i uzasadnienia. Zmniejszy to prawdopodobieństwo powtarzania próśb o naprawienie „problemu”. Ta dokumentacja pomoże również zniechęcić do szalejących odchyleń.
źródło
Ustawioną logikę manipulacji, w której dobrze posługuje się SQL, można bez problemu zintegrować z DDD.
Powiedzmy na przykład, że muszę znać jakąś wartość zagregowaną, całkowitą liczbę produktów według rodzaju. Łatwy do uruchomienia w sql, ale powolny, jeśli załaduję każdy produkt do pamięci i dodam je wszystkie.
Po prostu wprowadzam nowy obiekt Domain,
i metodę w moim repozytorium
Jasne, może teraz polegam na tym, że moja DB ma pewne umiejętności. Ale nadal technicznie mam separację i dopóki logika jest prosta, mogę argumentować, że nie jest to „logika biznesowa”
źródło
Query
jako parametry.repository.find(query);
. Przeczytałem to samo, ale zSpecs. That opens a door to leave
Query` jako abstrakcją i /QueryImpl
lub implementacją konkretnego zapytania do warstwy infrastruktury.I know some people do that
niektórzy ludzie są kluczowi i jego ramy. SpringFramework ma wiele tego :-). W każdym razie, jak sugeruje @VoiceOfUnreason, kluczem do DDD jest zachowanie spójności pism. Nie jestem pewien, czy wymuszam projektowanie za pomocą modeli domen, których jedynym celem jest zapytanie lub parametryzacja zapytań. Można to rozwiązać poza domeną za pomocą struktur danych (pocos, pojos, dtos, maperów wierszy, cokolwiek).Jednym z możliwych sposobów rozwiązania tego dylematu jest myślenie o SQL jako o asemblerze: rzadko, jeśli w ogóle, kodujesz bezpośrednio w nim, ale tam, gdzie liczy się wydajność, musisz być w stanie zrozumieć kod wygenerowany przez C / C ++ / Golang / Rust kompilator, a może nawet napisać mały fragment kodu w asemblerze, jeśli nie możesz zmienić kodu w swoim języku wysokiego poziomu, aby wygenerować pożądany kod maszynowy.
Podobnie w dziedzinie baz danych i SQL różne biblioteki SQL (niektóre z nich to ORM ), np. SQLAlchemy i Django ORM dla Python, LINQ dla .NET, zapewniają abstrakcje wyższego poziomu, ale w miarę możliwości używają wygenerowanego kodu SQL, aby osiągnąć wydajność. Zapewniają także pewną przenośność używanej bazy danych, prawdopodobnie mają różną wydajność, np. W Postgres i MySQL, z powodu niektórych operacji wykorzystujących bardziej optymalne SQL specyficzne dla bazy danych.
I podobnie jak w przypadku języków wysokiego poziomu, bardzo ważne jest zrozumienie, w jaki sposób działa SQL, nawet jeśli jest to po prostu zmiana kolejności zapytań wykonywanych za pomocą wyżej wymienionych bibliotek SQL, aby osiągnąć pożądaną wydajność.
PS Wolałbym, aby to był komentarz, ale nie mam do tego wystarczającej reputacji.
źródło
Jak zwykle jest to jedna z tych rzeczy, które zależą od wielu czynników. To prawda, że z SQL można wiele zrobić. Istnieją również problemy z korzystaniem z niego i pewne praktyczne ograniczenia relacyjnych baz danych.
Jak zauważa Jared Goguen w komentarzach, testowanie i weryfikacja SQL może być bardzo trudna. Głównymi czynnikami, które do tego prowadzą, jest to, że nie można go (ogólnie) rozłożyć na komponenty. W praktyce złożone pytanie musi być rozpatrywane w całości. Innym czynnikiem komplikującym jest to, że zachowanie i poprawność SQL jest wysoce zależna od struktury i zawartości twoich danych. Oznacza to, że testowanie wszystkich możliwych scenariuszy (a nawet określenie, jakie są) jest często niemożliwe lub niemożliwe. Refaktoryzacja SQL i modyfikacja struktury bazy danych jest również problematyczna.
Innym dużym czynnikiem, który doprowadził do odejścia od SQL, są relacyjne bazy danych, które skalują się tylko w pionie. Na przykład, gdy budujesz skomplikowane obliczenia w SQL, aby uruchomić je w SQL Server, będą one wykonywane w bazie danych. Oznacza to, że cała ta praca wykorzystuje zasoby w bazie danych. Im więcej robisz w języku SQL, tym więcej zasobów będzie potrzebować baza danych zarówno pod względem pamięci, jak i procesora. Często wykonywanie tych czynności na innych systemach jest mniej wydajne, ale nie ma praktycznego ograniczenia liczby dodatkowych maszyn, które można dodać do takiego rozwiązania. Takie podejście jest tańsze i bardziej odporne na uszkodzenia niż budowanie potwornego serwera bazy danych.
Problemy te mogą, ale nie muszą dotyczyć danego problemu. Jeśli jesteś w stanie rozwiązać problem z dostępnymi zasobami bazy danych, być może SQL jest odpowiedni dla twojego obszaru problemów. Musisz jednak wziąć pod uwagę wzrost. Dzisiaj może być dobrze, ale kilka lat później koszt dodania dodatkowych zasobów może stać się problemem.
źródło
Pozwól mi najpierw wyjaśnić kilka nieporozumień.
DDD nie jest wzorem. I tak naprawdę nie określa wzorów.
Przedmowa do książki Erica Evana DDD stwierdza:
Jest to więc sposób na podejście do tworzenia oprogramowania i modelowania domen oraz trochę technicznego słownictwa, które wspiera te działania (słownictwo, które obejmuje różne koncepcje i wzorce). To też nie jest coś zupełnie nowego.
Inną rzeczą, o której należy pamiętać, jest to, że model domeny nie jest implementacją OO, którą można znaleźć w twoim systemie - to tylko jeden ze sposobów wyrażenia go lub wyrażenia jego części. Model domeny to sposób, w jaki myślisz o problemie, który próbujesz rozwiązać za pomocą oprogramowania. To jak rozumiesz i postrzegasz rzeczy, jak o nich mówisz. To jest koncepcyjne . Ale nie w jakimś niejasnym sensie. Jest głęboki i wyrafinowany i jest wynikiem ciężkiej pracy i gromadzenia wiedzy. Jest on dalej udoskonalany i prawdopodobnie ewoluował w czasie, i obejmuje względy implementacyjne (niektóre z nich mogą ograniczać model). Powinny być udostępniane wszystkim członkom zespołu (i zaangażowani eksperci w dziedzinie) i powinien on decydować o sposobie wdrażania systemu, aby system ściśle go odzwierciedlał.
Nic w tym nie jest z natury pro lub anty-SQL, chociaż programiści OO są generalnie lepsi w wyrażaniu modelu w językach OO, a wyrażanie wielu koncepcji domen jest lepiej obsługiwane przez OOP. Ale czasami części modelu muszą być wyrażone w innym paradygmacie.
Ogólnie mówiąc, istnieją tutaj dwa scenariusze.
W pierwszym przypadku jakiś aspekt domeny naprawdę wymaga złożonego zapytania i być może ten aspekt najlepiej wyraża się w paradygmacie SQL / relacyjnym - więc użyj odpowiedniego narzędzia do zadania. Odzwierciedlaj te aspekty myślenia w swojej domenie i języka używanego do komunikowania pojęć. Jeśli domena jest złożona, być może jest to część subdomeny z własnym ograniczonym kontekstem.
Innym scenariuszem jest to, że postrzegana potrzeba wyrażenia czegoś w SQL jest wynikiem ograniczonego myślenia. Jeśli dana osoba lub zespół zawsze był zorientowany na bazę danych, może to być dla nich, z powodu bezwładności, trudność dostrzeżenie innego sposobu podejścia. Staje się to problemem, gdy stary sposób nie spełnia nowych potrzeb i wymaga nieco myślenia po wyjęciu z pudełka. DDD, jako podejście do projektowania, częściowo polega na tym, jak znaleźć wyjście z tego pudełka, gromadząc i destylując wiedzę na temat domeny. Ale wydaje się, że wszyscy ignorują tę część książki i koncentrują się na niektórych z technicznego słownictwa i wymienionych wzorców.
źródło
Sequel stał się popularny, gdy pamięć była kosztowna, ponieważ relacyjny model danych zapewniał możliwość normalizacji danych i skutecznego przechowywania ich w systemie plików.
Teraz pamięć jest stosunkowo tania, więc możemy pominąć normalizację i zapisać ją w formacie, w którym ją wykorzystujemy, lub nawet powielić wiele takich samych danych ze względu na szybkość.
Traktuj bazę danych jako proste urządzenie IO , które odpowiada za przechowywanie danych w systemie plików - tak, wiem, że trudno to sobie wyobrazić, ponieważ napisaliśmy wiele aplikacji z ważną logiką biznesową zapisanych w zapytaniach SQL - ale po prostu spróbuj wyobrazić sobie, że SQL Server to tylko kolejna drukarka.
Czy osadziłbyś generator PDF w sterowniku drukarki czy dodałeś wyzwalacz, który wydrukuje stronę dziennika dla każdego zamówienia sprzedaży wydrukowanego z naszej drukarki?
Zakładam, że odpowiedź brzmi „nie”, ponieważ nie chcemy, aby nasze aplikacje były powiązane z konkretnym typem urządzenia (nawet nie mówiąc o wydajności takiego pomysłu)
Czy w latach 70. i 90. baza danych SQL była wydajna? - Nie jestem pewien, w niektórych scenariuszach zapytanie asynchroniczne danych zwróci wymagane dane szybciej niż wiele połączeń w zapytaniu SQL.
SQL nie został zaprojektowany do skomplikowanych zapytań, został zaprojektowany do efektywnego przechowywania danych, a następnie zapewnia interfejs / język do przeszukiwania przechowywanych danych.
Powiedziałbym, że budowanie aplikacji wokół relacyjnego modelu danych przy użyciu skomplikowanych zapytań jest nadużywaniem silnika bazy danych. Oczywiście dostawcy silników baz danych są zadowoleni, gdy ściśle łączysz swoją firmę z ich produktem - z przyjemnością udostępnią więcej funkcji, które wzmocnią to powiązanie.
źródło