Aplikacja z podziałem na moduły

Odpowiedz Nowy wątek
2019-02-11 11:23
1

Zna ktoś jakąś aplikację open-source podzieloną na moduły? Mówi się na taką architekturę chyba architecture by feature. Chodzi mi o to, że mam np. projekt Modules.Customers i w nim wszystkie związane z klientami DTO, serwisy, komendy, zapytania, handlery itp.

Pozostało 580 znaków

2019-02-11 20:28
4

Zaznaczam ze mowiac moduly mam na mysli konteksty (bounded contexts). Kazdy modul powinien miec swoje dane- jak juz bylo wymienione- tak wiec i swoje encje. Czyli np. projekty Customers i Ordering beda mialy wlasne klasy reprezentujace klienta, w kazdym module oznaczajace co innego i posiadajace inne wlasciwosci. Byc moze beda nawet kryly sie pod inna nazwa (klient w Customers moze byc adresatem w Ordering). Moduly nie powinny sie ze soba bezposrednio komunikowac. Od tego jest integracja miedzy kontekstami za pomoca polecen (commands) i zdarzen (events, w MediatR kryjace sie pod notifications). Commands i Notifications mozesz umiescic w oddzielnych projektach, np. Messaging albo Integration. I tak np. project Customers bedzie mial odpowiadajacy temu projekt Customers.Integration. Inne moduly beda mialy referencje do projektu Customers.Integration, czyli tylko do commands i events. Same handlery umiesc w projektach modulowych.


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

Pozostało 580 znaków

2019-02-12 08:51
0

Proponowanego overengineeringu odnośnie podziału na moduły nie skomentuje :), natomiast zastanawia mnie jedna rzecz, po co w zaproponowanej architekturze dawać możliwość jednemu modułowi wysyłania komend do innego modułu? jakiś przykładowy scenariusz? bo nie mogę sobie tego wyobrazić.


Pozostało 580 znaków

2019-02-12 09:21
0

Overengineering bo? Chyba wyraźnie dyskusja dotyczy architektury w której cos takiego chce się stosować. Nie wnikam czy w tym konkretnym przypadku taka architektura ma sens czy nie, bo nie tego dotyczy dyskusja. Pytanie było o podział na moduły (modularny monolit) więc w tym kontekście odpowiedziałem. Ja nie proponuje aby stosować taki podział do napisania kalkulatora... Ale Ty oczywiście jesteś jednym z tych którzy z góry wiedzą o jakich wymaganiach mowa, i na wszystko mają złoty środek tak?

Po co wysyłanie komend? Po to żeby zapewnić loose coupling między modułami, wysyłać polecenia dokonania pewnych działań biznesowych (zarejestruj klienta, potwierdź/zaksięguj zamówienie) oraz komunikować zdarzenia (klient zarejestrowany, zamówienie zaksięgowane).

Proponuję poczytać o DDD, a konkretnie o bounded contexts, przechowywaniu danych dla każdego oraz komunikacji między kontekstami.

EDIT: A samą komunikację w oparciu o command/handler warto stosować nawet bez modularnosci, o czym pisałem już wcześniej.


Na każdy złożony problem istnieje rozwiązanie które jest proste, szybkie i błędne.
edytowany 1x, ostatnio: Aventus, 2019-02-12 09:34
@Aventus Z tego co rozumiem MediatR to wirtualna szyna komunikacyjna, czyli można zrobić coś podobnego oparte o rzeczywiste rozproszone moduły/serwisy? - Visual Code 2019-02-12 09:35
@Visual Code: bardziej szyna komunikacyjna w procesie. Chociaż samo określenie szyna komunikacyjna jest trochę na wyrost w tym przypadku. No ale tak, mniej więcej o to chodzi. I tak, można zrobić coś podobnego oparte o serwisy (mikroserwisy). Tylko że właśnie, po co to robić jeśli nie ma takiej potrzeby? Można mieć ładny, modularny monolit, ze wsparciem transakcyjnosci (przy używaniu jednej bazy danych) i jednocześnie bez overhead w postaci komunikacji sieciowej. - Aventus 2019-02-12 09:43
Natomiast jeśli wymagania wzrastają, system oparty o moduły można stosunkowo łatwo wypromować na system oparty o mikroserwisy. Bo architekturę już mamy, trzeba tyko dodać komunikację sieciową i każdy moduł przenieść do oddzielnego serwisu. - Aventus 2019-02-12 09:44
@Aventus: super, dzięki za odpowiedź 😄 - Visual Code 2019-02-12 10:02

Pozostało 580 znaków

2019-02-12 10:00
1
Aventus napisał(a):

Overengineering bo? (...) Ale Ty oczywiście jesteś jednym z tych którzy z góry wiedzą o jakich wymaganiach mowa, i na wszystko mają złoty środek tak?

Żeby mieć modularny monolit nie jest potrzebny ani CQRS, ani mediator. Jest to jedna z opcji, ale jak zauważyłeś nie znamy wymagań, więc chyba najlogiczniej jest wtedy iść w minimalne rozwiązanie?

Aventus napisał(a):

Po co wysyłanie komend? Po to żeby zapewnić loose coupling między modułami, wysyłać polecenia dokonania pewnych działań biznesowych (zarejestruj klienta, potwierdź/zaksięguj zamówienie) oraz komunikować zdarzenia (klient zarejestrowany, zamówienie zaksięgowane).

Moje pytanie brzmiało po co wysyłać komendy pomiędzy modułami. Przykłady poleceń które podałeś idą od interfejsu użytkownika w tym wypadku API do modułów, więc ponawiam swoje pytanie, po co mają moduły wysyłać pomiędzy sobą komendy? Jakiś przykład?


edytowany 1x, ostatnio: neves, 2019-02-12 10:00
2019-02-12 10:16
2
neves napisał(a):

Żeby mieć modularny monolit nie jest potrzebny ani CQRS, ani mediator. Jest to jedna z opcji, ale jak zauważyłeś nie znamy wymagań, więc chyba najlogiczniej jest wtedy iść w minimalne rozwiązanie?

Tak, ale zauwaz ze ja zachecalem rowniez do zainteresowania sie DDD, nawet w lekkiej formie. W przeciwnym razie czym niby bedzie taki modularny monolit? Aplikacja rozbita na kilka projektow? Jesli tak, to czy naprawde mowa o modularnosci? Dla mnie to niby-modularnosc poprzez przeniesienie namespaceow (folderow) o poziom wyzej. Ale popraw mnie jesli sie myle, zawsze jestem chetny do nauki nowych rzeczy.

Moje pytanie brzmiało po co wysyłać komendy pomiędzy modułami. Przykłady poleceń które podałeś idą od interfejsu użytkownika w tym wypadku API do modułów, więc ponawiam swoje pytanie, po co mają moduły wysyłać pomiędzy sobą komendy? Jakiś przykład?

Jak najbardziej. Zalozmy ze mamy strone bookowania pokojow w hotelu. Dla uproszczenia przyjmijmy ze mamy 2 nastepujace konktesty: Rooms (do zarzadzania hotelami i pokojami, moze nie najlepsze imie w tym przypadku) oraz Bookings. UI wysyla polecenie ktore jest handlowane w konktescie Bookings- CreateBooking. Naturalnie, musimy zarezerwowac pokoje, ale to nie jest w gestii kontekstu Bookings. Od walidowania zasad biznesowych rezerwacji pokoju jest Rooms. W takim przypadku process odpowiadajacy za bookowanie w kontekscie Booking wysyla polecenie ReserveRooms, ktore jest handlowane w kontekscie Rooms. Jesli jakis pokoj nie moze byc zarezerowany, bo np. nie ma juz wolnych miejsc (ktos inny w miedzy czasie zdazyl zarezerwowac), proces w Rooms rzuca wyjatek (lub emituje event, zaleznie od przyjetego podejscia) i cala operacja bookowania zostaje przerwana.


Na każdy złożony problem istnieje rozwiązanie które jest proste, szybkie i błędne.
Dopiero zauważyłem jak głupio brzmi spolszczenie handling na handlowanie. Wybaczcie, mam nadzieję że wiadomo o co mi chodziło... - Aventus 2019-02-12 10:37

Pozostało 580 znaków

2019-02-12 11:17
0

Nie trafia do mnie ten przykład :), wystarczy dać jakiś process manager/sage która będzie orkiestrowała przebieg procesu i potrzeba komunikacji pomiędzy Bookings a Rooms kompletnie znika. I wtedy nie mamy loose coupling, tylko no coupling at all. W wersji synchronicznej taki proces można orkiestrować z poziomu kontrolera, albo serwisu aplikacyjnego jak się dorobiliśmy warstwy logiki aplikacji. Aczkolwiek wtedy można dysputować czy logika biznesowa nie wycieka nam poza model domenowy, ale z drugiej strony mamy w pełni autonomiczne moduły, a to znacznie ułatwia życie, skalowanie i testowanie.


edytowany 1x, ostatnio: neves, 2019-02-12 11:17

Pozostało 580 znaków

2019-02-12 11:26
0

@neves: Alez oczywiscie, process manager/saga to bardzo dobre rozwiazanie przy bardziej rozbudowanej domenie i integracji miedzy kontekstami. Specjalnie o tym nie wspominalem bo omawiamy jednak troche prostsze scenariusze. Fakt, wtedy nie wysylasz polecen dla jednego kontekstu bezposrednio z innego. Co nie zmienia faktu ze komunikacja miedzy konktestami sie odbywa, tylko ze posrednio. No i PM/Saga to dodatkowa warstwa, w prostszych komunikacjach miedzydomenowych mogaca przyniesc niepotrzebna komplikacje. Nie zapominaj jednak, ze i tak pewna komunikacja bedzie sie odbywac. Kontekst A bedzie konsumowal eventy z konktestu B, chociazby w celu denormalizacji danych. Moim zdaniem (nie tylko moim zreszta) w modularnych aplikacjach o jakich tutaj mowa raczej nie ma potrzeby na wprowadzanie PM/Sagas. Oczywiscie podkreslam- wszystko zalezy od wymagan i zlozonosci systemu.

Tutaj troche na ten temat

When should I use a process manager?
When your bounded context uses a large number of events and commands that would be difficult to manage as a collection point-to-point interactions between aggregates.

EDIT: Rowniez tutaj ciekawy artykul

EDIT 2: Wprowadzajac PM/Saga musimy juz wprowadzic eventual consistency. Nie wazne ze komunikacja w modularnym monolicie nadal odbywa sie w ramach jednego procesu- PM bedzie oczekiwal na eventy aby wyslac kolejne polecenia. W takiej sytacji musimy juz rozwazyc zmiany architektury UI, zapewne bedzie potrzebna komunikacja dwu-kierunkowa miedzy serwerem a klientem, poniewaz skonczony proces (np. bookowania) nie "powroci" do kontrolera. Potrzebna bedzie dodatkowa infrastruktura odpowiedzialna za wyslanie komunikatu do klienta o zakonczonej (z powodzeniem lub nie) operacji, np. przy uzyciu SignalR. To z kolei bedzie wymagac korelacji poczatkowego requestu od klienta ze wszystkimi operacjami wykonywanymi w trakcie, az do zwrocenia wyniku do klienta na podstawie tejze wlasnie korelacji.


Na każdy złożony problem istnieje rozwiązanie które jest proste, szybkie i błędne.
edytowany 5x, ostatnio: Aventus, 2019-02-12 11:36
no właśnie tak myślałem że ten przykład z CQRS Journey wziąłeś ;) bo tam też problemem rezerwacji się zajmują ;) - neves 2019-02-12 11:35
A nie, akurat przyklad z hotelem to dla tego ze wlasnie nad tym pracuje w wolnym czasie :P - Aventus 2019-02-12 11:36

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0