Załóżmy, że to co opisujesz jako moduły, to mikroserwisy systemu.
Moduł Ordering
potrzebuje danych z modułu Products
do jakiejś swojej logiki biznesowej (np. nie można dodać nieaktywnego produktu do zamówienia). Standardowym rozwiązaniem jest w takim przypadku emitowanie z modułu Products
eventu zawierającego ProductId
i IsActive
. Moduł Ordering
nasłuchuje na ten event, aktualizuje swoje dane i wszystko ładnie działa - nie musi odpytywać modułu Products
, żeby sprawdzić, czy produkt jest aktywny.
Pytanie w czym przeszkadza ci odpytanie Products? Jeżeli jest to jedynie prosta informacja na temat stanu, to na ogół w niczym, a dołożenie do tego kolejnego miejsca w którym przechowywane są dane powoduje zwiększenie kosztów wytworzenia i utrzymania systemu. Musisz miec miejsce pod kolejną bazę danych, zajmować się jej serwisowaniem. Kolejka może ci paść i dane przestana przepływać. Można z tym walczyć, ale to znowu jest praca.
Po jakimś czasie pojawia się kolejne wymaganie: jeśli zamówienie zawiera produkt z grupy lub podgrupy X
, wtedy zamówienie nie może zostać normalnie kontynuowane, tylko osoba Y musi dodatkowo zrobić Z. Żeby nie odpytywać modułu Products
, moduł Ordering
zawiera teraz dodatkowo hierarchię grup produktów aktualizowaną przez eventy z modułu Products
.
O... właśnie. Podatność na rozwój spada wraz z wielkością systemu.
Czas mija i pojawia się kolejne wymaganie. Otóż produkt może mieć coś takiego jak dopłaty (np. przedłużenie jakiegoś tam kabla wchodzącego w skład produktu). W Ordering
chcemy, żeby można było takie dopłaty wiązać z pozycjami zamówień. A czego potrzebujemy, by sprawdzić, czy daną dopłatę można powiązać z danym produktem? Oczywiście danych z modułu Products
.
I prościej jest mieć ten moduł products z API, które może zostać rozszerzone wraz z rozwojem systemu, niż zastanawiać się, czy jak zmienisz strukturę payload w evencie to wszystkie konsumujące to usługi padną.
Już chyba wiadomo, do czego zmierzam: wraz ze wzrostem złożoności systemu moduły potrzebują coraz więcej swoich wewnętrznych danych. Możemy te dane kopiować, tylko czy ma to sens? Czy Ordering
ma mieć wszystkie dane z Products
skopiowane u siebie, żeby móc pełnić swoją funkcję? Co na ten temat sądzicie? Niezależność modułów to fikcja?
Czy to ma sens, musisz sam ocenić. Są przypadki kiedy to ma sens i takie gdzie będzie to absurdem, bo nie realizuje to żadnego wymagania, jest bardziej skomplikowane, podatne na awarie. Podałeś szkolny przykład, który pokazuje co można zrobić, ale niekoniecznie jest w tym sens.
Załóżmy, że mamy coś odrobinę bardziej z życia, jakiś sklep komputerowy, ma oddziały stacjonarne, sklep internetowy. Chcesz, żeby w sklepie internetowym była widoczna dostępność jakiegoś produktu. Magazyn to zbiór rekordów przyjęciach i wydaniach produktów. Wielu ludzi przegląda witrynę sklepu, ale zamawiają znacznie rzadziej. Czyli musiałbyś w tym wypadku, ileś razy na sekundę odpytywać magazyn o stany różnych produktów, a ten przeglądałby wszystkie rekordy w DB, żeby policzyć czy coś jest, czy NIE MA na magazynie. Nie możesz sobie tego cache'ować po stronie sklepu, bo to nie on odpowiada za przyjęcia towarów i część wydań (sklepy stacjonarne). Odpytywać tez nie możesz, bo event sourcing nie wyrobi przy takim ruchu. Ponieważ masz dużo większy ruch na czytaniu, niż na zmianach, potrzebujesz jedynie drobnej części informacji (stanu obecnego) a nie historii, możesz zastosować jakiś event bus do powiadamiania wszystkich zainteresowanych o miejscu gdzie coś się zmieniło, lub nowych wartościach.
Czyli:
Sklep ma własną, ulotną bazę danych (np. Redis), która ma listę produktów ze stanami. Buduje ją sobie przy starcie korzystając z danych z Magazynu (odpytuje przez jakieś API). W momencie zmiany stanu, Magazyn emituje sygnał zawierający id zmienionego produktu, typ zmiany (zmiana ceny, zwiększenie stanu, zmniejszenie stanu, sklep odbiera sygnał, jeżeli zmiana jest dla niego istotna (cena, zmniejszenie stanu) odpytuje magazyn o nowe wartości. Możesz też wrzucić do sygnału nowy stan produktu (cena, stan magazynowy itd.) i wtedy nie trzeba juz pytać, wystarczy przetworzyć stan. W praktyce tak czy inaczej, byłby to pewnie osobny serwis odpowiedzialny wyłącznie za przechowywanie aktualnego stanu produktów i obsługę sygnałów o zmianach, udostępniający te dane na żądanie ze sklepu.