Почему люди используют шины сообщений / событий в своем коде?


Я думаю, что вы слышали о шинах сообщений/событий, это единственное место, когда все события в системе текут. Подобные архитектуры находятся в материнских платах компьютера и сетевых сетях. Это хороший подход для материнских плат и сетей, поскольку он уменьшает количество проводов, но хорош ли он для разработки программного обеспечения? У нас нет таких ограничений, как у электроники.

самая простая реализация шины сообщений / шины событий может быть такой:

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

публикации события делается с автобусом.fireEvent (событие), прием сообщений включен по шине.addListener (слушатель). Такие архитектуры иногда используются для разработки программного обеспечения, например MVP4G реализует аналогичную шину сообщений для GWT.

активные проекты:

Спящие / мертвые проекты:

это просто популярный шаблон наблюдателя (слушателя), сделанный "глобально" - каждый объект в системе может прослушивать каждое сообщение, и я думаю это плохо, это нарушает принцип инкапсуляции (каждый объект знает обо всем) и принцип единой ответственности (например, когда какой-то объект нуждается в новом типе сообщения, шина событий часто должна быть изменена, например, чтобы добавить новый класс слушателя или новый метод в классе слушателя).

по этим причинам я думаю, что для большинства программ шаблон наблюдателя лучше, чем шина событий. Что вы думаете о событийной шине, имеет ли она какой-либо смысл для типичного заявки?

EDIT: я не говорю о "больших" корпоративных решениях, таких как ESB - они могут быть полезны (более того, ESB предлагает гораздо больше, чем просто шину событий). Я спрашиваю о полезности использования шины сообщений в "обычном" Java-коде для подключения объекта к объекту-некоторые люди делают это, проверяют ссылки выше. Шина событий, вероятно, является лучшим решением для связи телефон-телефон или компьютер-компьютер связи, потому что каждый телефон (или компьютер) в сети может обычно разговаривают друг с другом, и шина уменьшает количество проводов. Но объекты редко разговаривают друг с другом - сколько сотрудников может иметь один объект - 3, 5?

7 59

7 ответов:

некоторым людям это нравится, потому что это воплощение фасад шаблон или шаблон медиатора. Он централизует межсекторальную деятельность, такую как ведение журнала, оповещение, мониторинг, безопасность и т. д.

некоторым людям это не нравится, потому что это часто Одноэлементная точка отказа. Все должны знать об этом.

Я рассматриваю возможность использования шины событий в памяти для моего обычного кода java, и мое обоснование выглядит следующим образом

каждый объект в системе можно прослушать каждое сообщение, и я думаю, что это плохо, это нарушает принцип инкапсуляции (каждый объект знает о все)

Я не уверен, что это действительно так, I класс должен зарегистрироваться на шине событий для начала, подобно шаблону наблюдателя, как только класс зарегистрировался на шине событий, уведомляются только те методы, которые имеют соответствующую подпись и аннотацию.

и принцип единой ответственности (например, когда какой-то объект должен новый тип сообщения, шины событий часто необходимо изменить, например чтобы добавить новый класс прослушивателя или новый метод в классе прослушивателя).

Я совершенно не согласен с

шину событий часто нужно менять

шина событий никогда изменилось

Я согласен с

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

как это нарушает SRP ?, У меня может быть BookEventListener, который подписывается на все события, относящиеся к моей сущности Book, и да, я могу добавить методы к этому классу, но все же этот класс является сплоченным ...

Почему я планирую использовать его ? Это помогает мне моделировать "когда" моего домена ....

обычно мы слышим что-то вроде отправки почты "для" книги, приобретенные

идем писать вниз

book.purchase();
sendEmail()

Затем нам говорят добавить журнал аудита, когда книга приобретена, мы переходим к приведенному выше фрагменту

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

тут OCP нарушил

Предпочитаю

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

затем продолжайте добавлять обработчики по мере необходимости открытые для расширения закрытые для модификации

спасибо

Я использую его в значительной степени в JavaScript. Там может быть так много различных виджетов, что все должны делать какие-то действия, когда что-то еще происходит-нет реальной иерархии владения объектами. Вместо того, чтобы передавать ссылки каждого объекта на каждый объект или просто делать каждый объект глобальным, когда что-то значительное происходит внутри конкретного виджета, я могу просто опубликовать "/ thisWidget / somethingHappened" -- вместо заполнения этого виджета всеми видами кода, специфичными для API других виджетов. У меня есть один класс, который содержит все "проводки" или "plubming", как они любят называть его в Java Spring framework. Этот класс содержит ссылки на все мои виджеты и имеет весь код для того, что происходит после каждого запуска различных событий.

Он централизован, прост в доступе и обслуживании, и если что-то меняется или я хочу, чтобы новый процесс происходил на определенном событии, мне не нужно искать через каждый класс / объект / виджет, чтобы попытаться найти где-то обрабатывается. Я могу просто пойти в свой класс "оператор" - тот, который обрабатывает всю" проводку", когда происходит конкретное событие, и увидеть все последствия этого события. В этой системе каждый отдельный виджет полностью агностик API других виджетов. Он просто публикует то, что с ним случилось или что он делает.

Мне трудно понять, что ты действительно задавая свой вопрос. Вы приводите пример простой шины событий, которая на самом деле просто Observable с другим именем, то вы говорите;

по этим причинам я думаю, что для большинств программное обеспечение, картина наблюдателя лучше, чем автобус событий. Что вы подумайте о шине событий, делает ли это любой здравый смысл для типичного заявки?

..но учитывая ваш пример, они тот же. Это заставляет меня задаться вопросом, если вы когда-либо использовали что-то вроде корпоративной сервисной шины. На базовом уровне ESB логически делает то же самое, что и шаблон наблюдателя, но коммерческие продукты добавляют гораздо больше. Это как автобус событий на стероидах. Они являются сложными программными продуктами и предложение;

самовывоз в сообщении
Генерируйте события, прослушивая различные конечные точки. Конечной точкой может быть прослушиватель (например, сервер HTTP), система обмена сообщениями (например JMS), база данных или почти все, что вы хотите.

маршрутизация сообщений
Возьмите свое событие и отправьте его в одну/несколько конечных точек. Маршрутизация может быть довольно умной, шина может маршрутизировать сообщение в зависимости от типа сообщения, содержимого сообщения или любых других критериев. Маршрутизация может быть интеллектуальной и динамичной.

Преобразование Сообщения
Преобразует ваше сообщение в другой формат, это может быть как simnple, как из XML в JSON или из строки в таблице базы данных в HTTP-запрос. Преобразование может происходить внутри самих данных,например, при замене форматов дат.

Обогащение Данных
Добавляет или изменяет данные в сообщении, вызывая службы по пути. Например, если сообщение содержит почтовый индекс, шина может использовать службу поиска почтового индекса для добавления адресных данных.

..и еще много-много чего. Когда вы начинаете смотреть в детали, вы действительно можете начать видеть почему люди используют эти вещи.

потому что это может быть важным шагом на пути к отделению модулей приложения к архитектура на основе сервиса.

поэтому в вашем случае, если у вас нет намерения отделить модули вашего приложения в изолированные службы, то собственная реализация шаблон Observer сделает его более простым решением.

но если вы хотите построить допустим архитектура микроуслуг event-bus позволит чтобы получить преимущества этого стиля архитектуры, чтобы вы могли, например, обновить и развернуть только какую-то часть вашего приложения, не затрагивая другие, потому что они просто подключены через шину событий.

Итак, главный вопрос здесь-желаемый уровень разъединение компонентов приложения.

некоторые ссылки об этом:

хорошая аналогия - это телефонная станция, где каждый телефон может набирать номер на любой другой телефон. Скомпрометированный телефон может настроиться на другие разговоры. Программное управление течет как провода (цикломатическая сложность никому!) Это похоже на требование наличия соединения / физической среды между двумя конечными точками. Это так для N телефонов вместо того, чтобы иметь NC2 (комбинаторная логика) потоки для каждого нового телефона мы, как правило, получаем N потоков.

снижение сложности подразумевает легкий для понимания код. Давайте начнем с наиболее заметных точек, которые вы выделили: 1. Глобальные знания 2. Интрузивные модификации.

глобальное знание: рассматривайте событие сообщения как конверт. С точки зрения обработчика/отправителя событий данные не отображаются, он видит оболочку (если производный класс не пытается выполнить некоторую проверку с помощью проверок "instanceof"). В хорошем дизайне ООП это никогда не произойдет.

интрузивные модификации: вместо того, чтобы иметь подход к прослушиванию событий, можно использовать глобальный подход к обработке событий. Таким образом, у нас есть глобальный тип события (на котором данные копятся и отбрасываются вниз). Это очень похоже на модель PropertyBeanSupport в Java. С одним типом события мы должны иметь один тип отправителя и слушателя. Это означает, что вам не нужно изменять шину/слушателей каждый раз, когда вы видите что-то новое. Уродливый вниз кастинг может быть успокоен с помощью шаблона адаптера (пожалуйста, не начинайте, что другой уровень перенаправление цитата!). Программисты могут писать ассемблеры на любом языке. Так что потребность в здравом смысле и смекалке не может быть заменена. Все, что я намерен заявить, это может быть эффективным инструментом.

фактические приемники событий могут легко использовать слушателей (композиция / прокси). В такой базе кода Java слушатели будут выглядеть как автономные объявления внутреннего класса (с неиспользуемым предупреждением, помеченным в определенных IDE). Это сродни двум игрокам на пляже, играющим в мяч, игроки не реагируйте, пока они не увидят мяч.

'@duffymo 'указывает на еще один интересный аспект: "одна точка отказа". Это будет / может теоретически повлиять на любой объект, находящийся в памяти(ОЗУ) и не специфичный для обработчиков сообщений.

в качестве практического примера, наше приложение синхронизируется с веб-службой каждые x минут, и если какие-либо новые данные получены, нам нужно обновить графический интерфейс. Теперь, поскольку SyncAdapter работает в фоновом потоке, вы не можете просто указать на textview и изменить его свойства, вы должны всплывать событие. И единственный способ убедиться, что вы поймали это событие, - это если у вас есть общий (статический,одноэлементный) объект, передающий это событие для обработки подписчиками.