Способствует ли шаблон «центр уведомлений» хорошему или плохому дизайну программы?

13

Иногда я сталкиваюсь с этими API-интерфейсами в стиле концентраторов сообщений, например, с Центром Какао NSNotificationCenter: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/Reference/Reference.html.

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

Этот шаблон в целом поощряет хороший или плохой дизайн программы, и почему так? Это делает код сложнее или проще для тестирования?

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

Редактировать: я думаю, моя самая большая проблема с этим шаблоном заключается в том, что API «лжет» о зависимостях и объектных связях, и может быть проиллюстрировано на этом примере:

myObj = new Foo();
myOtherObj = new Bar();
print myOtherObj.someValue; // prints 0
myObj.doSomething();
print myOtherObj.someValue; // prints 1, unexpectedly, because I never indicated that these objects had anything to do with each other
Магнус Вольффелт
источник
Вы ставите под сомнение этот пример конкретно или шаблон слушателя в целом?
TheLQ
Я считаю, что это шире, чем шаблон слушателя. Шаблон слушателя может быть реализован «чисто» с четко определенной структурой объекта и регистрации слушателей на определенных объектах. Моя неуверенность в глобальном шаблоне сообщений / событий.
Магнус Вольффелт

Ответы:

6

Я бы не сказал, что это поощряет плохое программирование. Но это может быть легко использовано неправильно.

Ну, какова реальная идея?
Источник уведомления только делает свое уведомление. Это не делает предположения о существовании потенциальных наблюдателей или чего-либо еще. Наблюдатель регистрируется для уведомлений, для которых он предназначен. Наблюдатель не делает никаких предположений о том, сколько потенциальных источников имеется для уведомлений, которые он может обработать.

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

Самая большая опасность, конечно, состоит в том, что кто-то будет использовать это, чтобы сделать тонны объектов глобально доступными для вызовов 1-1.

back2dos
источник
6

Асинхронный обмен сообщениями является хорошим архитектурным принципом для больших систем, которые должны масштабироваться

Java-эквивалент этого - JMS, и, как правило, считается хорошей вещью .

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

Вы можете легко экспортировать URI-концентратор сообщений, чтобы сделать его настраиваемым и не встроенным в исходный код.

Гэри Роу
источник
4

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

Из вашего вопроса звучит так, как будто вы обеспокоены тем, что все знают о NotificationCenter и что глобальные вещи ПЛОХО. Иногда да, глобальные вещи плохие. Но давайте посмотрим на альтернативу. Допустим, у вас есть 2 компонента, для этого примера не имеет значения, что они делают или чем они являются. Компонент1 имеет некоторые данные, которые были обработаны или изменены каким-либо образом. Компонент2 хотел бы знать о любых изменениях данных того типа, которым управляет Compoent1. Должен ли Компонент2 знать о существовании Компонента1? Или было бы лучше, если бы Component2 подписывался / слушал сообщение, сообщающее, что какой-то компонент в приложении изменил некоторые данные, которые его интересуют? Теперь возьмите этот пример и умножьте его на десятки или более компонентов, и вы сможете увидеть, где лежит значение шаблона.

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

Вальтер
источник
1
Читая википедию, определение шаблона наблюдателя, похоже, не включает глобально доступный концентратор событий. Если бы концентратор событий был передан в конструктор / метод всех соответствующих объектов, я бы счел это хорошим шаблоном. Это действительно глобальная точка доступа и ее состояние, которое делает меня неуверенным.
Магнус Вольффелт
0

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

TMN
источник