Dlaczego ludzie używają autobusów komunikatów/zdarzeń w swoim kodzie?

Myślę, że słyszałeś o autobusach wiadomości / zdarzeń, jest to jedno miejsce, w którym przepływają wszystkie zdarzenia w systemie. Podobne architektury znajdują się w płytach głównych komputera i sieciach LAN. Jest to dobre podejście do płyt głównych i sieci, ponieważ zmniejsza liczbę przewodów, ale czy jest dobre dla rozwoju oprogramowania? Nie mamy takich ograniczeń jak elektronika.

Najprostszą implementacją magistrali komunikatów / zdarzeń może być:

class EventBus {
    void addListener(EventBusListener l}{...}
    void fireEvent(Event e) {...}
}

Zamieszczanie zdarzeń odbywa się za pomocą autobus.fireEvent( event), odbiór wiadomości jest możliwy przy pomocy magistrali.addListener (słuchacz). Takie architektury są czasami używane do tworzenia oprogramowania, na przykład MVP4G implementuje podobną magistralę komunikatów dla GWT.

Aktywne projekty:

Uśpione / martwe projekty:

To po prostu popularny wzór obserwatora (słuchacza) zrobiony "globalnie" - każdy obiekt w systemie może słuchać każdej wiadomości i myślę, że to źle, łamie zasadę enkapsulacji (każdy obiekt wie o wszystkim) i zasadę pojedynczej odpowiedzialności (np. gdy jakiś obiekt potrzebuje nowej wiadomości). typ wiadomości, szyna zdarzeń często wymaga zmiany na przykład w celu dodania nowej klasy Listener lub nowej metody w klasie Listener).

Z tych powodów uważam, że dla większości programów, Pattern Observer pattern jest lepszy niż event bus. Co sądzicie o event bus, czy ma to sens w typowych zastosowaniach?

EDIT: nie mówię o "dużych" rozwiązaniach korporacyjnych, takich jak ESB - mogą być przydatne (co więcej, ESB oferuje znacznie więcej niż tylko magistralę zdarzeń). Pytam o przydatności użycia magistrali komunikatów w "zwykłym" kodzie Javy do połączenia obiekt-obiekt - niektórzy tak robią, sprawdź linki powyżej. Magistrala zdarzeń jest prawdopodobnie najlepszym rozwiązaniem do komunikacji telefonicznej lub komputerowej, ponieważ każdy telefon (lub komputer) w sieci może zazwyczaj ze sobą rozmawiać, a magistrala zmniejsza liczbę przewodów. Ale obiekty rzadko ze sobą rozmawiają-ilu kolaborantów może mieć jeden obiekt-3, 5?

Author: Basil Bourque, 2010-10-21

7 answers

Niektórym się podoba, ponieważ jest ucieleśnieniem wzoru elewacji lub wzoru mediatora. Centralizuje działania przekrojowe, takie jak rejestrowanie, alarmowanie, monitorowanie, bezpieczeństwo itp.

Niektórym się to nie podoba, ponieważ często jest to pojedynczy punkt porażki. Każdy musi o tym wiedzieć.

 24
Author: duffymo,
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
2016-05-25 13:11:35

Rozważam użycie szyny zdarzeń w pamięci dla mojego zwykłego kodu java i moje uzasadnienie jest następujące

Każdy obiekt w systemie może odsłuchać każdą wiadomość i myślę, że to źle, łamie zasadę hermetyzacji (każdy obiekt wie o wszystko)

Nie jestem pewien, czy to prawda, Klasa I musi zarejestrować się na szynie zdarzeń, aby rozpocząć, podobnie jak obserwator pattern, gdy Klasa zarejestruje się na szynie zdarzeń, tylko metody, które prosimy o powiadomienie o odpowiednim podpisie i adnotacji.

I zasada jednej odpowiedzialności (np. gdy jakiś przedmiot musi nowy typ wiadomości, szyna zdarzeń często wymaga zmiany np. aby dodać nową klasę słuchacza lub nową metodę w klasie słuchacza).

Całkowicie się z tym nie zgadzam

Event bus często wymaga zmiany

Szyna zdarzeń nigdy się nie zmienia

Zgadzam się z

add a new Listener class or a new method in the Listener class

Jak to się łamie SRP ?, Mogę mieć BookEventListener, który subskrybuje wszystkie wydarzenia odnoszące się do mojej jednostki Książki, i tak mogę dodać metody do tej klasy, ale nadal ta klasa jest spójna ...

Dlaczego planuję go użyć ? Pomaga mi modelować "kiedy" mojej domeny ....

Zazwyczaj słyszymy coś takiego jak wysyłanie poczty "kiedy" książka jest kupowana

Zapisujemy

book.purchase();
sendEmail()

Następnie mamy dodać dziennik audytu po zakupie książki, przechodzimy do powyższego snippet

book.purchase();
sendEmail();
**auditBook();**

Right there OCP

Wolę

book.purchase();
EventBus.raiseEvent(bookPurchasedEvent);

Następnie dodawaj manipulatory w razie potrzeby otwarte dla rozszerzenia zamknięte dla modyfikacji

Dzięki

 65
Author: Sudarshan,
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
2012-01-24 09:28:52

Używam go mocno w JavaScript. Może być tak wiele różnych widżetów, że wszystkie muszą wykonać jakąś akcję, gdy dzieje się coś innego-nie ma prawdziwej hierarchii własności obiektów. Zamiast przekazywać odniesienia do każdego obiektu do każdego obiektu lub po prostu uczynić każdy obiekt globalnym, gdy coś znaczącego dzieje się wewnątrz konkretnego widżetu, mogę po prostu opublikować "/ thisWidget / somethingHappened " - zamiast wypełniać ten widżet wszystkimi rodzajami kodu specyficznego dla API inne widżety. Mam jedną klasę, która zawiera wszystkie "okablowanie", lub "plubming", jak to lubią nazywać w Java Spring framework. Ta klasa zawiera odniesienia do wszystkich moich widżetów i ma cały kod dla tego, co dzieje się po każdym wywołaniu różnych zdarzeń.

Jest scentralizowany, łatwy w dostępie i utrzymaniu, a jeśli jedna rzecz się zmieni lub chcę, aby pojawił się nowy proces w konkretnym zdarzeniu, nie muszę przeszukiwać każdej klasy / obiektu / widżetu, aby dowiedzieć się, gdzie coś się dzieje. Mogę po prostu pójść na zajęcia z "operatorem" - tą, która zajmuje się wszystkimi "okablowaniem", gdy wydarzy się określone wydarzenie, i zobaczyć każdy reperkusję tego wydarzenia. W tym systemie każdy pojedynczy widżet jest całkowicie niezależny od innych widżetów. Po prostu publikuje, co się z nim stało lub co robi.

 15
Author: Bal,
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
2010-10-21 15:01:09

Mam problem ze zrozumieniem, co naprawdę zadajesz w swoim pytaniu. Podajesz przykład prostej magistrali zdarzeń, która w rzeczywistości jest po prostu Observable o innej nazwie, wtedy mówisz;

Z tych powodów myślę, że dla większość oprogramowania, wzór obserwatora jest lepsze niż event bus. Co Ty pomyśl o event bus, czy to sprawia, że każdy dobry sens dla typowych aplikacje?

..ale biorąc pod uwagę Twój przykład, są takie same. To sprawia, że zastanawiam się jeśli kiedykolwiek używałeś czegoś takiego jak Enterprise Service Bus. Na poziomie podstawowym ESB logicznie robi to samo, co obserwator, ale produkty komercyjne dodają znacznie, znacznie więcej. To jak autobus imprezowy na sterydach. Są to skomplikowane produkty i oferta oprogramowania;

Odbiór wiadomości
Generowanie zdarzeń poprzez słuchanie różnych punktów końcowych. Punktem końcowym może być słuchacz (taki jak serwer HTTP), system wiadomości (taki jak JMS), baza danych lub prawie wszystko inne chcesz.

Message routing
Weź swoje wydarzenie i wyślij je do jednego / wielu punktów końcowych. Routing może być dość inteligentny, magistrala może kierować wiadomość w zależności od typu wiadomości, zawartości wiadomości lub innych kryteriów. Routing może być inteligentny i dynamiczny.

Transformacja Wiadomości
Przekształca wiadomość do innego formatu, może to być tak samo proste jak z XML do JSON lub z wiersza w tabeli bazy danych do żądania HTTP. Transformacja może nastąpić wewnątrz samych danych, na przykład Zamiana formatów daty.

Wzbogacanie Danych
Dodaje lub modyfikuje dane w wiadomości, dzwoniąc po drodze do usług. Na przykład, jeśli wiadomość zawiera kod pocztowy, magistrala może użyć usługi wyszukiwania kodów pocztowych do dodania danych adresowych.

..i wiele, wiele więcej. Kiedy zaczniesz przyglądać się szczegółom, możesz naprawdę zacząć widzieć Dlaczego ludzie używają tych rzeczy.

 13
Author: Qwerky,
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
2010-10-21 13:38:05

Ponieważ może to być ważny krok na drodze do oddzielenia modułów aplikacji do architektury opartej na usługach .

Więc w Twoim przypadku, jeśli nie masz zamiaru oddzielić modułów aplikacji do izolowanych usług, to natywna implementacja wzorca Observer uczyni to prostszym rozwiązaniem.

Ale jeśli chcesz zbudować architekturę mikrousług event-bus pozwoli Ci czerpać z tego korzyści styl architektury, dzięki czemu można na przykład zaktualizować i wdrożyć tylko część aplikacji bez wpływu na inne, ponieważ są one po prostu połączone za pośrednictwem magistrali zdarzeń.

Więc głównym pytaniem jest tutaj pożądany poziom komponentów aplikacji odsprzęgających.

Kilka referencji na ten temat:

 3
Author: brunocrt,
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
2016-09-22 17:40:40

Dobrą analogią jest ta z centrali telefonicznej, gdzie każda słuchawka może wybrać każdą inną słuchawkę. Uszkodzona słuchawka może dostroić się do innych rozmów. Sterowanie programem płynie jak przewody(cyklomatyczna złożoność każdego!) Jest to podobne do wymogu posiadania połączenia / medium fizycznego między dwoma punktami końcowymi. Tak jest dla N słuchawek zamiast mieć NC2 (Combinatorial logic) przepływy dla każdego nowego słuchawki mamy tendencję do otrzymywania N przepływów.

Redukcja złożoności implikuje łatwy do zrozumienia kod. Zacznijmy od wyróżnionych punktów: 1. Wiedza globalna 2. Inwazyjne modyfikacje.

Wiedza globalna: Uznaj Zdarzenie wiadomości za otoczkę. Z perspektywy obsługi zdarzenia/nadawcy nie ma żadnych danych, jest to Widok otoczki (chyba że klasa pochodna próbuje wykonać inspekcję za pomocą sprawdzeń 'instanceof'). W dobrym projekcie OOP, to nigdy nie nastąpi.

Inwazyjne modyfikacje: zamiast mieć specyficzne dla danego zdarzenia podejście słuchacza, można użyć globalnego podejścia do obsługi zdarzeń. Jako takie mamy globalny typ zdarzenia (na którym dane są kopiowane i kopiowane w dół). Jest to podobne do modelu PropertyBeanSupport w Javie. W przypadku pojedynczego typu zdarzenia wymagane jest posiadanie jednego typu nadawcy i słuchacza. Oznacza to, że nie musisz modyfikować magistrali / słuchaczy za każdym razem, gdy widzisz coś nowego. Brzydki down-casting można ukoić za pomocą wzoru adaptera (proszę nie zaczynać, że kolejny poziom przekierowania cytat!). Programiści mogą pisać assembly w dowolnym języku. Tak więc potrzeba zdrowego rozsądku i sprytu nie może być zastąpiona. Chcę tylko powiedzieć, że to może być skuteczne narzędzie.

Rzeczywiste odbiorniki zdarzeń mogą łatwo korzystać ze słuchaczy (skład/proxy). W takiej bazie kodu Java, słuchacze wyglądaliby jak samodzielne wewnętrzne deklaracje klas (z nieużywanym ostrzeżeniem oznaczanym w niektórych Idach). To jest akeen do dwóch graczy na plaży gra w piłkę, gracze nie reagują, dopóki widzą piłkę.

' @ duffymo 'zwraca uwagę na inny interesujący aspekt: 'pojedynczy punkt porażki'. Teoretycznie może to wpłynąć na dowolny obiekt znajdujący się w pamięci(RAM), a nie specyficzny dla Messagehandlerów.

 1
Author: questzen,
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
2010-10-23 12:31:01

Jako praktyczny przykład, nasza synchronizacja aplikacji jest z usługą internetową Co x liczba minut, a jeśli jakieś nowe dane są odbierane, musimy zaktualizować GUI. Teraz, ponieważ SyncAdapter działa w wątku tła, nie można po prostu wskazać widoku tekstu i zmodyfikować jego właściwości, trzeba bubble up zdarzenia. Jedynym sposobem,aby upewnić się, że przechwycisz to zdarzenie, jest posiadanie współdzielonego (statycznego, singletonowego) obiektu przekazującego to zdarzenie do obsługi subskrybentów.

 0
Author: Captain Kenpachi,
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-01-10 12:23:08