CQRS (Command Query Responsibility Segregation) ma wiele odmian. Jeden napisze tak, drugi napisze inaczej. I FIGHT – święta wojna gotowa. O podstawach CQRS, z odrobiną historii i przykładami, wkrótce jeszcze napiszę. Dziś: o esencji, o “corze”, o serduszku <3.
[blogvember2016 no=”18″]
O co spór?
Różnice w implementacji podejścia CQRS zaobserwować można na każdym kroku. Każdy programista ma swoje racje i nie ma jednej poprawnej drogi. Jak to zwykle bywa: “whatever works“. Z dopiskiem: “in a given context“.
Niedawno zaprezentowałem na blogu swoje podejście do składowych komponentów CQRS i ich rejestracji w kontenerze DI. Niedługo pojawi się kolejny, dłuższy, tekst na podobny temat. Można tam poczytać o takim tworze jak ICommandBus – komponencie, którego rolą jest dystrybucja wiadomości w danym systemie. Dla mnie to piękna koncepcja, niosąca bardzo wiele korzyści i praktycznie pozbawiona wad. Znajdą się jednak zwolennicy teorii, że czegoś takiego jak “szyna komend” w ogóle nie powinno się implementować. I git, nie ma się o co bić.
W moich projektach, na moje potrzeby, w MOIM KONTEKŚCIE, zrównoleglanie operacji najczęściej nie było potrzebne. Wyznaję zasadę, aby wszystko było tak proste jak to tylko możliwe. Jeśli da się więc osiągnąć założenia biznesowe bez wielowątkowości, komunikacji między procesami czy asynchroniczności, to tak właśnie zrobię. Można jednak natknąć się stwierdzenia, że “implementowanie CQRS na jednym wątku jest bez sensu“. Hmm… U mnie tak to właśnie działało: komenda -> handler -> event -> handler -> event -> handler – wszystko na jednym wątku, bez zrównoleglania. I sprawdziło się wyśmienicie.
Wreszcie: “jakie dane powinny zwracać komendy?“. W MOIM podejściu: żadnych (o tym też się jeszcze rozpiszę). Komenda to VOID, i już. Ileż razy byłem jednak przekonywany, że to bardzo ograniczające i nieprawidłowe podejście…
Wiesz co? Wszystkie powyższe spory to tylko szczegóły implementacyjne.
Esencja CQRS
Samo serce CQRS to jedno proste przykazanie: oddziel zapis od odczytu. Tylko tyle i aż tyle.
CQRS = oddzielenie zapisu od odczytu
Jeśli masz problemy opisane powyżej, to jest już dobrze. To są problemy, które fajnie jest mieć. Przynajmniej w porównaniu z alternatywą.
W CQRS bierzemy to:
Czyli JEDEN MODEL, służący do wszystkiego. I do zapytań, i do wykonywania logiki, i do reprezentacji danych. Duży zestaw skomplikowanych klas. Zestaw, który się nie sprawdza.
Zamieniamy to na:
Uświadamiamy sobie, że potrzebujemy więcej niż jeden model. Potrzebujemy przynajmniej dwa modele: jeden przystosowany do odczytu danych i jeden dedykowany do przetwarzania/zapisu.
Jak je zaimplementujemy? To kwestia drugorzędna. Ja mam swój sposób, Ty możesz mieć inny sposób. Po takiej operacji i tak jesteśmy w o wiele lepszej pozycji, niż jeszcze niedawno.
Bo:
Asking a question should not change the answer
Bertrand Meyer
BUM. Koniec.
Bonus 1
O CQRS możesz posłuchać w moim podkaście nagranym z jednym z dwóch “ojców” tego podejścia: DevTalk#14 – CQRS with Udi Dahan. Bardzo ciekawa audycja w kontekście mniej technicznym, takie treści trudno znaleźć więc bardzo polecam.
Bonus 2
Dlaczego ten obrazek pasuje do dywagacji o CQRS? :)