Realizacja nowej funkcjonalności biznesowej często wykracza poza ramy jednego Modułu Monolitu. Jako że muszą się ze sobą komunikować m.in. w celu oddelegowania zadań dalej - warto przeanalizować sobie rodzaje komunikacji jakie możemy zaimplementować.
🔌 Wariant #1: Fasada
Moduł B jest całkowicie zależny od modułu A |
W tym przypadku moduł bieżący (B) w którym piszemy zleconą nam funkcjonalność musi oddelegować część prac do innego zewnętrznego modułu (A). Delegowanie pracy w praktyce polega na wywołaniu void'owskiej metody (Command) Fasady leżącej w zewnętrznym module.
W opisywanym przypadku moduł bieżący jest tym znajdującym się w dole strumienia. Całkowicie musi się on poddać kontraktowi komunikacji ustanowionego przez upstream'owy moduł zewnętrzny. Moduł A wie jakich składników będzie potrzebował do wykonania swojego zadania, dlatego stanowią one parametry metody Fasady. W gestii modułu downstream'owego leży to by takowe parametry dostarczyć - warto się zastanowić czy posiadanie przez niego takich informacji jest w ogóle poprawne.
Warto podkreślić, że moduł A nie wie nic o swoich klientach - udostepnia API (Interfejs Fasady) do komunikacji z innymi modułami i nie dba o to czy jest ich pięciu czy nie ma ani jednego. W tym przypadku to moduł zewnętrzny A jest niezależny od innych modułów. Idąc tym tropem: odpowiedzmy sobie najpierw na pytanie dlaczego moduł bieżący B do wykonania w pełni swojej funkcjonalności musi oddelegować część pracy do zewnętrznego modułu - czy granice zostały poprawnie wytyczone?
Moduł B z kolei wie dokładnie o istnieniu innego modułu A i jak się z nim komunikować (API Fasady). Jest to więc jawna deklaracja komunikacji jednostronnej:
- wiem co chcę zrobić,
- wiem kto to zrobi,
- wiem dokładnie jak zmusić tego kogoś do wykonania tej czynności.
📨 Wariant #2: Event'y
W tym wypadku moduł bieżący (A) w którym dodajemy funkcjonalność, informuje inne bliżej nieokreślone moduły o zaistnieniu pewnego zdarzenia wewnątrz swoich granic. Robi to emitując Event Aplikacyjny (Sync/Async) - nie troszcząc się o to kiedy i przez kogo zostanie on obsłużony.
Moduły B i C są całkowicie zależne od Modułu A |
Zaimplementowanie Event'u w Warstwie Aplikacji wychodzącego poza granicę bieżącego modułu jest swego rodzaju zdefiniowaniem kontraktu komunikacji.
Moduł bieżący (A) nie dba o to czy Event'y zostaną obsłużone, istotne jest to tylko dla zewnętrznych modułów (downstream'owych) które decydują się na nasłuchiwanie na tego typu zdarzenia.
Downstream'owe moduły B i C muszą dostosować się do kontraktu ustalonego przez moduł A. Muszą one być w stanie wykonać swoją pracę na postawie danych znajdujących się w Event'cie.
W tym wypadku, nie możemy powiedzieć że moduł A chce oddelegować część pracy do innych modułów. Jedynie daje im znać, że coś się u niego zdarzyło.
Jest to więc całkowicie inna sytuacja niż gdyby miał on skorzystać z Fasad modułów B & C wywołując ich metody void'owskie.
Możnaby ponownie wypisać stwierdzenia jak w przypadku poprzedniej sekcji - Stan bieżącego modułu uległ zmianie:
- nie wiem kogo to interesuje,
- nie wiem czy będzie miało to jakiekolwiek konsekwencje.
🔎 Porównanie
W przypadku korzystania z Fasady niejawnie zakładamy, że coś musi się zadziać i nie możemy obejść się bez tej funkcjonalności z zewnętrznego modułu. Wydaje się, że wybierając takie rozwiązanie funkcjonalność wykonywana za Fasadą (upstream) jest naprawdę ważna.
W przypadku emitowania Event'ów przez moduł bieżący - nie dbamy o to jaki klient/klienty obsłużą to zdarzenie. Zastanawiam się czy z takim podejściem, obsługujące to zdarzenie moduły downstreamo'we wykonują funkcjonalności drugorzędne... tak - ale tylko z perspektywy bieżącego modułu.
Bieżący moduł | komunikacja z Fasadą | emitowanie Event’ów |
---|---|---|
Hierarchia | downstream | upstream |
Czy tworzy kontrakt | nie | tak |
Czy wie kto będzie wykonywał czynność | tak | nie |
Czy mamy pewność wykonania zleconych prac | tak | nie |
Czy konsekwencje prac są znane | tak | nie |
Sposób komunikacji | Sync | Sync/Async |
Brak komentarzy:
Prześlij komentarz