Muszę iść na kompromis: OSUSZANIE, czy rozdzielanie zapytań i poleceń?

10

Niedawno refaktoryzowałem metodę, która była jednocześnie metodą polecenia i zapytania.

Po podzieleniu go na jedną metodę polecenia i jedną metodę zapytania, odkryłem, że w kodzie jest teraz wiele miejsc, w których wywołuję polecenie, a następnie uzyskuję wartość z zapytania, co wydaje się naruszać zasadę DRY.

Ale gdybym owinął ten wspólny kod w metodę, metoda ta byłaby zarówno poleceniem, jak i zapytaniem. Czy to jest dopuszczalne?

Kris Welsh
źródło
okej, nie wiedziałem, czy społeczność osiągnęła konsensus i nie mogłem znaleźć dyskusji na ten temat.
Kris Welsh
Jest to częściej nazywane CQRS google.com.au/…
Daniel Little
@DanielLittle - nie, nie jest. CQS i CQRS są wyraźnie różnymi podmiotami. CQRS jest znacznie bardziej zaangażowanym wzorcem architektonicznym, podczas gdy CQS jest bardziej wzorcem projektowym i jest znacznie łatwiejszy do uchwycenia i wdrożenia. Zobacz codebetter.com/gregyoung/2009/08/13/command-query-separation
Erik Funkenbusch
@Erik Funkenbusch Masz rację
Daniel Little

Odpowiedzi:

11

Zawsze istnieją kompromisy do rozważenia między sprzecznymi zasadami projektowania. Sposobem na rozwiązanie tego problemu jest przyjrzenie się podstawowym przyczynom zasad. W takim przypadku niemożność uruchomienia zapytania bez uruchomienia polecenia jest problematyczna, ale niemożność uruchomienia polecenia bez uruchomienia zapytania jest ogólnie nieszkodliwa. Tak długo, jak istnieje sposób na samodzielne uruchomienie zapytania, nie widzę powodu, aby nie dodawać wyniku zapytania do polecenia, zwłaszcza jeśli wykonałeś coś takiego:

QueryResult command()
{
   // do command stuff
   return query();
}
Karl Bielefeldt
źródło
4

Nie słyszałem wcześniej o rozdzielaniu zapytań i poleceń (CQS), ale wygląda na to, że odnosi się to do zasady pojedynczej odpowiedzialności (SRP), która stwierdza, że ​​funkcja / klasa idealnie powinna odpowiadać za wykonanie jednej rzeczy i tylko jednej rzeczy .

Jeśli twój kod komendy składa się z 20 linii kodu, a kod zapytania to kolejne 30 linii i wszystkie są w jednym ciele funkcji, najwyraźniej naruszasz SRP i zakładam, że również CQS, i te dwie logiki powinny być od siebie oddzielone .

Jednak idąc za twoim hipotetycznym przykładem, najprawdopodobniej stworzę metodę otoki, która połączy twoje polecenie i zapytanie, aby DRY nie zostało naruszone w wielu miejscach w kodzie. Nie uważałbym również, że jest to naruszenie SRP (i być może CQS), ponieważ opakowanie nadal ma tylko jedną odpowiedzialność: połączyć polecenie z zapytaniem i utworzyć abstrakcję wyższego poziomu, która jest łatwiejsza do konsumpcji.

Myślę, że metoda otoki jest rozwiązaniem całkowicie akceptowalnym. Aby to zilustrować, przejdźmy o krok dalej. Co by było, gdybyś musiał uruchomić 2 zapytania zamiast 1, a następnie wykonać na tej podstawie polecenie. Tak więc twoje 2 linie kodu miałyby 6 lub 8. Co gdyby było pewne sprawdzanie / sprawdzanie danych między jednym a drugim, więc teraz masz 15 linii kodu. Czy pomyślałbyś dwa razy o stworzeniu opakowania, które to wszystko robi, zamiast posypywania tych 15 wierszy wieloma plikami?

DXM
źródło
Myślę, że „pojedyncza zasada” opakowania powinna polegać na utrzymywaniu razem pozostałych metod, które wymagają polecenia i zapytania.
Droogans,
Google CQRS: google.com.au/…
Daniel Little
Chociaż rozwiązanie tego problemu przez Karla jest lepsze, uważam, że twoje opracowanie na temat dłuższych funkcji opakowania jest bardzo dobrym punktem.
Kris Welsh
-3

SUSZENIE jest ważniejsze, ponieważ zaspokaja znacznie bardziej fundamentalną potrzebę - unikanie zbędnego, skutecznie zmarnowanego wysiłku. Jest to podstawowa rzecz - nie trzeba być programistą, aby to zrozumieć.

CQS jest odpowiedzią na trudność, w językach bez obsługi efektów śledzenia, zrozumienia kodu wykonywanego zarówno dla jego wyników, jak i efektów. Jednak:

  1. Konieczności wykonania kodu dla jego wyników nie można uniknąć, ponieważ jest to podstawa do komponowania dużych programów z małych jednostek.

  2. Konieczności wykonania kodu dla jego efektów nie można również uniknąć, ponieważ poza matematyką i informatyką teoretyczną wartość uruchamiania programu zależy od tego, co może on dla nas zrobić.

  3. Nie można uniknąć konieczności wywoływania efektów i tworzenia wyników w tym samym kodzie, ponieważ w praktyce potrzebujemy zarówno efektów, jak i kompozycyjności, a nie tylko jednego lub drugiego.

Rzeczywistym rozwiązaniem problemu śledzenia efektów zbyt trudnych dla nieuzbrojonych ludzi jest oczywiście to, że komputery pomagają nam ludziom ! Podobną rzecz można powiedzieć o śledzeniu zawiłych relacji między wartościami środowiska wykonawczego (takich jak ważność indeksów tablic), dla których wyjątki i umowy wymuszane przez środowisko wykonawcze stanowią rozwiązania (nie).

Podsumowując, „rozwiązania” takie jak CQS przeszkadzają w projektowaniu programów zgodnie z rozsądnymi zasadami opartymi na rzeczywistości. Idź po SUCHO.

pyon
źródło
Czasami trzeba unikać łączenia, aby zmniejszyć złożoność. Powinieneś spojrzeć na CQRS.
Daniel Little
@Lawinski: Najlepszym narzędziem do unikania złożoności (nie zmniejszania jej, co jest daremne) jest abstrakcja - oddzielenie ogólnej istoty problemów, które rozwiązujemy, od konkretnych szczegółów przykładów wspomnianych problemów ogólnych. Magiczne przepisy (lub „wzorce projektowe”, jak słyszę, jak się je nazywa) w najlepszym wypadku mogą zapobiec wyrządzaniu zbyt dużych szkód, gdy źle zrobisz projekt, ale nie mogą zmienić niewłaściwego projektu we właściwy.
pyon
@Lawinski: W odniesieniu do CQRS, poprawnym koncepcyjnie rozwiązaniem alternatywnym jest 1. zrozumienie modelu danych (żadna liczba warstw obiektowych nie może wyeliminować konieczności tego), 2. zakodowanie tylu właściwości poprawności, jak to możliwe w schemacie bazy danych. (Niestety, najpopularniejsze RDBMS zapewniają raczej ograniczone wsparcie dla tych ostatnich, nie wspominając już o tych NoSQL, które jeszcze bardziej się mylą. Moje obecne badania dostarczają lepszego rozwiązania tego problemu.)
py
CQRS działa całkowicie zgodnie z Domain Driven Design. Sugeruję, abyś przeprowadził trochę badań. Domena wewnątrz aplikacji powinna wymuszać poprawność, a nie magazyn danych.
Daniel Little
1
@ EduardoLeón: Jeśli chcesz udowodnić, że Twój projekt jest poprawny, spróbuj napisać testy dla swojego programu. Gwarantuję ci, że wyrzucenie CQS tylko utrudni twoje wysiłki.
Stefan Billiet