O padrão de “centro de notificação” incentiva o design do programa, bom ou ruim?

13

Às vezes, encontro essas APIs no estilo do hub de mensagens, por exemplo, o Cocoa NSNotificationCenter: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/Reference/Reference.html

Geralmente essas APIs fornecem um ponto de acesso global no qual você se inscreve ou transmite mensagens / eventos. Estou pensando que isso é um problema, porque incentiva uma arquitetura de programa simples e não estruturada, onde as dependências não são explícitas na API, mas ocultas no código-fonte. Você não é forçado a pensar em propriedade e hierarquias de objetos, mas pode fazer com que qualquer objeto em seu programa resulte em qualquer código que seja chamado em qualquer lugar. Mas talvez isso seja uma coisa boa?

Esse padrão geralmente incentiva o design bom ou ruim do programa e por que? Isso torna o código mais difícil ou mais fácil de testar?

Perdoe-me se esta pergunta é muito vaga ou ampla. Estou tentando entender as possíveis consequências do uso extensivo de uma API como esta e as diferentes maneiras de usá-la.

Edit: Eu acho que meu maior problema com esse padrão é que a API "mente" sobre dependências e acoplamentos de objetos e pode ser ilustrada com este exemplo:

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
Magnus Wolffelt
fonte
Você questionou este exemplo especificamente ou o padrão do ouvinte em geral?
TheLQ
Acredito que isso seja mais amplo que o padrão do ouvinte. O padrão do ouvinte pode ser implementado "de maneira limpa" com uma estrutura de objeto bem definida e registrando ouvintes em objetos específicos. Minha incerteza é sobre o padrão global de hub de mensagens / eventos.
Magnus Wolffelt

Respostas:

6

Eu não diria que isso encoraja uma programação ruim. Mas pode facilmente ser mal utilizado.

Bem, qual é a ideia real?
A fonte da notificação somente faz sua notificação. Não se assume a existência de potenciais observadores ou algo assim. Um observador registra as notificações que ele foi projetado para manipular. O observador não faz nenhuma suposição sobre quantas fontes potenciais existem para as notificações que ele pode manipular.

Essa é uma maneira de obter injeção de dependência, sem que as fontes conheçam os observadores ou os observadores conheçam as fontes. No entanto, para que todo o sistema funcione, você precisa conectar os observadores certos para as notificações corretas, e esse sistema é vulnerável a erros de digitação, porque não pode ser verificado o tempo de compilação.

O maior perigo, é claro, é que alguém o use para disponibilizar toneladas de objetos em todo o mundo para chamadas de 1 a 1.

back2dos
fonte
6

As mensagens assíncronas são um bom princípio de arquitetura para sistemas grandes que devem ser dimensionados

O equivalente em Java disso é JMS e geralmente é considerado uma coisa boa .

Isso ocorre porque promove a dissociação do código do cliente do código que realmente atende à mensagem. O código do cliente apenas precisa saber onde postar sua mensagem. O código de serviço apenas precisa saber onde pegar as mensagens. Cliente e serviço não se conhecem e, portanto, podem mudar independentemente um do outro, conforme necessário.

Você pode externalizar facilmente o URI do hub de mensagens para torná-lo configurável e não incorporado no código-fonte.

Gary Rowe
fonte
4

Essa é uma implementação típica do Padrão Oberserver (ou às vezes chamada de padrão de Ouvinte ou, às vezes, de padrão de Assinante / Editor). Nas aplicações em que esse comportamento é útil, é um bom padrão para implementar. Nenhum padrão deve ser implementado se não agregar valor à solução.

Com a sua pergunta, parece que você está preocupado com o fato de tudo saber sobre o NotificationCenter e de que as coisas globais são ruins. Às vezes, sim, as coisas globais são ruins. Mas vamos olhar para a alternativa. Digamos que você tenha 2 componentes; neste exemplo, não importa realmente o que eles fazem ou o que são. O componente1 possui alguns dados que foram acionados ou alterados de alguma maneira. O Component2 gostaria de saber sobre quaisquer alterações nos dados do tipo que o Compoent1 gerencia. O Component2 deve saber sobre a existência do Component1? Ou seria melhor para o Component2 assinar / escutar uma mensagem informando que algum componente em algum lugar do aplicativo alterou alguns dados nos quais está interessado? Agora pegue este exemplo e multiplique-o por dezenas ou mais componentes e você poderá ver onde está o valor do padrão.

É uma solução perfeita para todas as situações, não. Abstrai a comunicação entre os componentes e fornece um acoplamento mais flexível, sim.

Walter
fonte
1
Lendo na wikipedia, a definição de padrão de observador não parece incluir um hub de eventos disponível globalmente. Se o hub de eventos fosse passado para o construtor / método de todos os objetos envolvidos, consideraria isso um bom padrão. Na verdade, é o ponto de acesso global e seu estado que me deixa incerto.
Magnus Wolffelt 30/11
0

É bom para sistemas controlados por eventos e é mais agradável do que a alternativa de ter um monte de Observadores observando um ao outro, pois é menos provável que você acabe com loops infinitos inadvertidos de observadores disparando eventos. Esse era um problema real nos velhos tempos do VB, quando você tinha controles ActiveX controlados por eventos que podiam ser conectados entre si com manipuladores de eventos.

TMN
fonte