Jak repozytoria pasują do CQR?

Według Fowlera ( tutaj ), repozytorium " pośredniczy między warstwami mapowania domeny i danych, działając jak kolekcja obiektów domeny w pamięci."Tak więc, na przykład w aplikacji usługi kurierskiej, gdy przesyłane jest nowe uruchomienie, moja usługa aplikacji tworzy nowy obiekt Run aggregate root, wypełnia go wartościami z żądania, a następnie dodaje go do RunRepository przed wywołaniem jednostki pracy, aby zapisać zmiany w bazie danych. Gdy użytkownik chce wyświetlić listę current runs, odpytuję to samo repozytorium i zwracam denormalizowane DTO reprezentujące informacje.

Jednakże, patrząc na CQRS, zapytanie nie trafiłoby do tego samego repozytorium. Zamiast tego, być może pójdzie bezpośrednio przeciwko przechowywaniu danych i zawsze będzie denormalizowana. A moja strona poleceń ewoluowałaby do NewRunCommand i Handlera, który tworzyłby i wypełniał obiekt domeny NewRun, a następnie przechowywał informacje do magazynu danych.

więc pierwsze pytanie brzmi, gdzie repozytoria pasują do modelu CQRS, jeśli nie utrzymujemy kolekcji w pamięci (pamięci podręcznej, jeśli wolisz) obiektów domeny?

Rozważ przypadek, w którym informacje przesłane do usługi Moje aplikacje zawierają tylko serię wartości ID, które usługa musi rozwiązać, aby zbudować obiekt domain. Na przykład żądanie zawiera ID # kuriera przypisanego do biegu. Usługa musi wyszukać rzeczywisty obiekt kuriera na podstawie wartości ID i przypisać obiekt do NewRun za pomocą metody AssignCourier (która waliduje kuriera i wykonuje inną logikę biznesową).

inne pytanie brzmi, biorąc pod uwagę rozdzielenie zapytań i potencjalny brak repozytoriów, w jaki sposób usługa aplikacji wykonuje wyszukiwanie, aby znaleźć obiekt domeny Kuriera?

UPDATE

Bazując na dodatkowej lekturze i przemyśleniu po komentarzu Dennisa, przeformułuję swoje pytania.

Wydaje mi się, że CQRS zachęca repozytoria, które są jedynie fasadą nad mechanizmami dostępu do danych i przechowywania danych. Dają one" wygląd " zbioru (jak opisuje Fowler), ale nie zarządzają bytami w pamięci (Jak zauważył Dennis). Oznacza to, że każda operacja w repozytorium jest przepuszczana, tak?

Jak jednostka pracy wpisuje się w to podejście? Zazwyczaj UoW jest używany do zatwierdzania zmian wprowadzonych do repozytorium (prawda?) ale jeśli repozytorium nie utrzymuje encji in-memory, to jaką rolę ma UoW?

w odniesieniu do operacji "write", czy program obsługi poleceń miałby odniesienie do tego samego repozytorium, innego repozytorium lub może UoW zamiast repozytorium?

Author: SonOfPirate, 2012-04-07

2 answers

Czytałem o systemach CQRS, które utrzymują prosty magazyn wartości klucza po stronie poleceń, aby reprezentować stan aplikacji, i innych, które po prostu korelują wiadomości (używając pewnego rodzaju sagi) i używają magazynu zapytań do reprezentowania stanu aplikacji. Tak czy inaczej, z tymi podejściami bez wątpienia będzie związana technologia persistence, ale wzorzec repozytorium w takich przypadkach byłby niepotrzebną abstrakcją.

Moje doświadczenie z CQRS ma byliśmy tylko z event sourcing, gdzie odtworzyliśmy poprzednie wydarzenia, aby odbudować agregaty, które zawierają i wymuszają logikę biznesową i niezmienniki. W tym przypadku wzorzec repozytorium jest znaną abstrakcją, która może zapewnić prostszy sposób pobierania dowolnego z tych agregatów.

Jeśli chodzi o stronę zapytań to polecam jak najbliżej magazynu danych, przez to mam na myśli unikanie jakichkolwiek repozytoriów, usług, fasad itp. pomiędzy Twoim UI (cokolwiek to może być) i przechowywania danych.

Może pomóc zobaczyć przykład tych podejść w użyciu. Może przyjrzyjmy się następującym projektom:

W przypadku NES repozytorium zapewnia jedynie znajomy interfejs do dodawania i odczytywania agregatów bezpośrednio do i z jednostki pracy.

Jeszcze kilka linków, które mogą pomóc:

 7
Author: Elliot Ritchie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:30:47

Nie jestem pewien, jak ortodoksyjne to jest-ale w bieżącym projekcie mam repozytorium dla mojego zagregowanego korzenia encji. To repozytorium ma tylko dwie metody: Get i ApplyEvents.

Wszystkie zdarzenia implementują wspólny interfejs dla ich typu - dla zamówień są OrderEvents, itp. Osobiście układam logikę biznesową każdego zdarzenia w metodę polimorficzną, dzięki czemu dodawanie nowych typów zdarzeń staje się bardzo proste.

Dla Get, repozytorium przechodzi do magazynu zdarzeń i pobiera wszystkie zdarzenia w zakresie rodzaju (np. zamówienia w jednej lokalizacji sklepu). Następnie wykonuje powtórkę wydarzeń, aby osiągnąć aktualny stan bytu dla wszystkich wydarzeń, które otrzymuje. Może również działać z migawki, więc nie odtwarzasz każdego zdarzenia za każdym razem, gdy ładujesz. Możesz również mieć ogólne repozytorium zdarzeń, aby nawet wyodrębnić sposób przechowywania zdarzeń i pobrać je na podstawie specyfikacji.

ApplyEvents pobiera listę zdarzeń, a następnie zmienia stan encji na ich podstawie i zwraca je. Zauważ, że dajesz repozytorium opcję odtworzenia encji, a nie tylko jej zmiany! To działa dobrze z funkcyjnym typem programowania, ale oznacza, że najlepiej unikać równości obiektów (obj1 == obj2) w C# lub Javie. Twierdzę, że tylko ValueObjects, a nie byty, powinny mieć równość i tak.

Oto Jak to działa w praktyce( C#) - mam zamówienia i chcę dodać element. currentOrder.Items zwraca pustą listę. Wtedy Ja do

Assert.IsFalse(newEvent.Items.Any())
IOrderEvent newEvent = eventFactory.CreateOrderItemEvent(myItemID);
currentOrder = orderRepository.ApplyEvents(currentOrder, newEvent);
Assert.IsTrue(newEvent.Items.Any())

Powinienem zobaczyć currentOrder.Pozycje mają jeden wpis.

Wadą jest to, że całe moje przetwarzanie odbywa się poprzez zdarzenia, a nie posiadanie mojej logiki biznesowej w jednostce. Jednak w moim przypadku, gdzie prawie wszystkie moje obiekty muszą być serializowalne (w zasadzie POCOs) i pracować na wielu systemach, to faktycznie działa dobrze.

 1
Author: Mathieson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-13 17:57:54