CQRS i viewmodele

N0
  • Rejestracja:około 7 lat
  • Ostatnio:ponad 2 lata
  • Lokalizacja:Gdańsk
  • Postów:647
0

Czy w aplikacji MVC zgodnej z CQRS viewmodele i komendy (zapytania) powinny być reprezentowane przez różne klasy? Czy jeśli mam np. CreateXCommand, to powinienem też mieć CreateXViewModel? Przy takim podejściu komenda jedynie opakowuje model widoku, czyli trzeba tworzyć wiele "nadmiarowych" klas, ale jaka jest alternatywa? Dziedziczenie viewmodeli po ICommand (IQuery) albo przekazywanie komend (zapytań) do widoku raczej nie pachnie dobrze.

E9
  • Rejestracja:ponad 13 lat
  • Ostatnio:12 miesięcy
  • Postów:395
2

Do api mogą przychodzić spokojnie command i query, a kontroler może je wysyłać na szynę. Jeśli jednak command lub query potrzebują dodatkowych informacji niż to co przyszło z zewnątrz to powinny to być oddzielne klasy. O dziedziczeniu viewmodeli z ICommand zapomnij.

edytowany 1x, ostatnio: error91
N0
  • Rejestracja:około 7 lat
  • Ostatnio:ponad 2 lata
  • Lokalizacja:Gdańsk
  • Postów:647
0

Po dłuższym namyśle (wiem, dwa miesiące :p) stwierdzam, że MVC i CQRS (u mnie zaimplementowane przy użyciu MediatR) raczej do siebie nie pasują. Czy stosowanie MediatR jest warte duplikowania każdego viewmodelu? @Aventus Ty się znasz dobrze na MediatR. Co o tym sądzisz?

neves
  • Rejestracja:prawie 22 lata
  • Ostatnio:około 4 godziny
  • Lokalizacja:Kraków
  • Postów:1114
1

Jeśli nie robisz jakiegoś AOP w okół command/query, nie masz eventów, to nie potrzebujesz MediatR.
Do robienia CQRS, nie musisz mieć każdej komendy i query osobno, możesz jeśli to coś wniesie do systemu który tworzysz, a jak nic nie wnosi to tylko dodajesz nikomu niepotrzebnej złożoności przypadkowej.

title


edytowany 1x, ostatnio: neves
Zobacz pozostałe 2 komentarze
N0
Hmm, faktycznie ;) Ale co zrobić, jeśli te klasy staną się za długie?
Aventus
A nawet w myśl prezentacji Udi Dahan'a którą niedawno oglądałem, można mieć CQRS całkowicie bez zmieniania kodu :) wszystko zależy od skali i tego gdzie chcemy "widzieć" te CQRS. Ja jestem zwolennikiem rozdzielania klas na podstawie operacja, czyli oddzielna klasa command i handler na każdą akcję jaką chcemy wykonać w systemie. Ale fakt, można to robić inaczej.
Aventus
@nobody01: dla mnie używanie jednej klasy do np. wielu zapisów to próba nadania innej nazwy dla popularnego antywzorca w postaci managera. Taki "manager" od wszystkiego, w jednym miejscu. Osobiście odradzam.
neves
to samo co robisz gdy komendy urosną zbyt duże, czy jakikolwiek kod urośnie zbyt duży, czyli wydzielasz mniejsze kawałki i je nazywasz i zamykasz w postaci serwisów czy jakiś innych klocków których używasz do modelowania
neves
dodałem przykład jak wygląda serwis aplikacyjny w aplikacji którą obecnie piszę, serwis składa się z 3 komend i jednego zapytania i w sumie ma 84 linijki kodu
SZ
  • Rejestracja:prawie 11 lat
  • Ostatnio:około 3 godziny
  • Postów:1506
2
nobody01 napisał(a):

Po dłuższym namyśle (wiem, dwa miesiące :p) stwierdzam, że MVC i CQRS (u mnie zaimplementowane przy użyciu MediatR) raczej do siebie nie pasują. Czy stosowanie MediatR jest warte duplikowania każdego viewmodelu? @Aventus Ty się znasz dobrze na MediatR. Co o tym sądzisz?

Ale co w tym złego, że masz klasy osobno do zapisu, osobno do edycji osobno do wyświetlania? Dla mnie dużą zaletą jest to, że każdą operację mogę mieć w osobnej klasie a wywołuje to z jednego miejsca. I jak sama nazwa wskazuje wydaję mi się, że głównym celem mediatR jest zaimplementowanie wzorca mediator.

edytowany 1x, ostatnio: szydlak
Aventus
  • Rejestracja:około 9 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:UK
  • Postów:2235
2

.Czy stosowanie MediatR jest warte duplikowania każdego viewmodelu?

Troche blednie zadane pytanie. Podejrzewam ze w Twoim przypadku to nie wzorzec mediator wymusza "duplikowanie" view modelu, a fakt ze - calkiem slusznie- masz podzial na warstwy i warstwa domeny nie wie nic o widoku. Tak wiec naturalnie rezutatem zwracanym z handlera bedzie zwykle DTO bez danych metadancyh o widoku.Gdybys wszystko wrzucil do jednego worka to bys mogl zwracac sam model widoku, ale tego oczywiscie nie powinno sie raczej robic. Chyba ze piszesz naprawde prosty CRUD.

Druga sprawa to ze przy stosowaniu API i oddzielnego frontu zwracanym rezultatem bedzie wlasnie DTO, wiec zazwyczaj nawet nie trzeba nic duplikowac ani mapowac. W Twoim jednak przypadku pytasz o MVC- zastanowmy sie. Zwracasz jakies DTO jako wynik requestu/polecenia, oraz w warstwie UI mapujesz to na view model. Moim zdaniem nie ma w tym problemu, poniewaz Twoj view model moze miec dodatkowe informacje na temat chociazby formatowania wyswietlanych danych czy tez dodatkowe wlasciwosci zwracajace dane zbudowane z kilku innych juz gotowych wlasciwosci. Tak wiec czy jest sens posiadania dwoch klas tak zwiazanych (jedna tylko posrednio) z widokiem modelu? Tak, jesli chcesz zachowac odpowiedni podzial miedzy warstwami.

Jesli zas chodzi o komunikacje w druga strone, czyli wyslanie czegos z kontrolera do domeny to sprawa wyglada tak samo. Dodatkowo moim zdaniem komendy oraz zwracane obiekty powinny byc niemutowalne, a view model zazwyczaj posiada settery.


Na każdy złożony problem istnieje rozwiązanie które jest proste, szybkie i błędne.
edytowany 1x, ostatnio: Aventus
HA
ViewModel ma setery bo jest to zależność od frameworka. Jeśli bardzo chcesz to możesz sobie binder nadpisać :P
Aventus
Jak najbardziej, ja jedynie stwierdziłem fakt że właśnie zazwyczaj posiadają settery. Zresztą nie widzę w tym nic złego ponieważ zakres i cykl życia modelu widoku jest krótki.
HA
A co to ma do długości cyklu życia.?
N0
  • Rejestracja:około 7 lat
  • Ostatnio:ponad 2 lata
  • Lokalizacja:Gdańsk
  • Postów:647
0

@Aventus: Wracam z innego tematu, bo za duży offtopic się zrobił ;) Chodziło mi o to, że zwracanie z handlera DTO, a następnie mapowanie go na ViewModel, który zawiera te same dane co DTO + metadane dla widoku, jak dla mnie jest oznaką przeinżynierowania w sytuacji, gdy mamy tylko MVC jako jedyną warstwę prezentacji. Chociaż korzyści wynikające z podziału na warstwy i projekty (czytelność kodu) są większe, to jednak są obecne klasy (DTO), które istnieją tylko po to, aby ten podział mógł mieć miejsce. Chociaż pewnie to jest zło konieczne. ;)

Aventus
  • Rejestracja:około 9 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:UK
  • Postów:2235
1

Tak, jest to zlo konieczne (w pewnym sensie). Do tego dochodza elementy ktore juz kiedys wymienialem:

  • Niemutowalnosc DTO
  • Dodatkowe, specyficzne dla widoku elementy w view modelu (np. atrybuty walidacji i formatowania)

Rowniez tak jak wspomnialem w innym watku, to co pisalem brzmialo jakbys mial zle wszystko porozdzielane. Ale moze to oddzielny temat. Reasumujac- tak, taki podzial moze nie miec sensu przy prostych aplikacjach, nigdzie tez do stosowania tego w takich przypadkach nie zachecalem. Natomiast kiedy tylko dochodzi bardziej rozbudowana logika biznesowa to szybko ujawniaja sie zalety takiej architektury.


Na każdy złożony problem istnieje rozwiązanie które jest proste, szybkie i błędne.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.