Il modello del "centro notifiche" incoraggia la progettazione di programmi buoni o cattivi?


13

A volte mi imbatto in queste API in stile hub di messaggi, ad esempio Cocoa NSNotificationCenter: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/Reference/Reference.html

Di solito queste API forniscono un punto di accesso globale su cui ti iscrivi o trasmetti messaggi / eventi. Sto pensando che questo sia un problema perché incoraggia un'architettura di programma piatta e non strutturata, in cui le dipendenze non sono esplicite nell'API, ma nascoste nel codice sorgente. Non sei obbligato a pensare alla proprietà e alle gerarchie degli oggetti, ma puoi piuttosto fare in modo che qualsiasi oggetto nel tuo programma dia luogo a qualsiasi codice venga chiamato ovunque. Ma forse questa è una buona cosa?

Questo schema generalmente incoraggia la progettazione di programmi buoni o cattivi, e perché? Rende il codice più difficile o più facile da testare?

Perdonami se questa domanda è troppo vaga o ampia. Sto cercando di avvolgere la mia testa sulle potenziali conseguenze di un ampio uso di un'API come questa e sui diversi modi in cui potresti usarla.

Modifica: Immagino che il mio problema più grande con questo modello sia che l'API "mente" su dipendenze e accoppiamenti di oggetti, e può essere illustrata con questo esempio:

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

Sei in dubbio questo esempio in particolare o il modello di ascolto in generale?
TheLQ

Credo che questo sia più ampio del modello dell'ascoltatore. Il modello di ascolto può essere implementato "in modo pulito" con una struttura di oggetti ben definita e registrando listener su oggetti specifici. La mia incertezza riguarda il modello globale di hub messaggio / evento.
Magnus Wolffelt,

Risposte:


6

Non direi che incoraggia una cattiva programmazione. Ma può essere facilmente utilizzato in modo improprio.

Bene, qual è l'idea reale?
La fonte della notifica effettua solo la sua notifica. Non fa ipotesi sull'esistenza di potenziali osservatori o altro. Un osservatore registra le notifiche che è stato progettato per gestire. L'osservatore non fa alcuna ipotesi su quante potenziali fonti ci siano per le notifiche che può gestire.

Questo è un modo per ottenere l'iniezione di dipendenza, senza che le fonti conoscano gli osservatori o che gli osservatori conoscano le fonti. Tuttavia, affinché l'intero sistema funzioni, è necessario collegare gli osservatori giusti per le giuste notifiche e questo sistema è persino vulnerabile ai refusi, poiché non è possibile controllare il tempo di compilazione.

Il pericolo più grande ovviamente è che qualcuno lo userà per rendere disponibili tonnellate di oggetti a livello globale per chiamate 1-1.


6

La messaggistica asincrona è un buon principio architettonico per i sistemi di grandi dimensioni che devono essere ridimensionati

L'equivalente Java di questo è JMS e generalmente considerato una buona cosa .

Questo perché promuove il disaccoppiamento del codice client dal codice che serve effettivamente il messaggio. Il codice cliente deve semplicemente sapere dove pubblicare il proprio messaggio. Il codice di servizio deve semplicemente sapere dove raccogliere i messaggi. Il cliente e il servizio non si conoscono reciprocamente e pertanto possono cambiare indipendentemente l'uno dall'altro, se necessario.

È possibile esternalizzare facilmente l'URI dell'hub dei messaggi per renderlo configurabile e non incorporato nel codice sorgente.


4

Questa è un'implementazione tipica del pattern Oberserver (o talvolta chiamata pattern Listener o talvolta denominata modello Subscriber / Publisher). Nelle applicazioni in cui questo comportamento è utile è un buon modello da implementare. Nessun modello deve essere implementato se non aggiunge valore alla soluzione.

Dalla tua domanda, sembra che tu sia preoccupato che tutto sappia del NotificationCenter e che le cose globali siano MALE. A volte, sì, le cose globali vanno male. Ma diamo un'occhiata all'alternativa. Diciamo che hai 2 componenti, per questo esempio non importa davvero cosa fanno o cosa sono. Il componente 1 ha alcuni dati su cui è stato agito o modificato in qualche modo. Componente2 desidera conoscere eventuali modifiche ai dati del tipo gestito da Compoent1. Component2 dovrebbe sapere dell'esistenza di Component1? O sarebbe meglio per Component2 iscriversi / ascoltare un messaggio che indica che un componente da qualche parte nell'app ha cambiato alcuni dati a cui è interessato? Ora prendi questo esempio e moltiplicalo per dozzine o più componenti e puoi vedere dove si trova il valore del modello.

È una soluzione perfetta per ogni situazione, no. Rende astratta la comunicazione tra i componenti e fornisce un accoppiamento più lento, sì.


1
Leggendo su Wikipedia, la definizione del modello di osservatore non sembra includere un hub eventi disponibile a livello globale. Se l'hub eventi fosse passato al costruttore / metodo di tutti gli oggetti interessati, lo considererei un buon modello. È davvero il punto di accesso globale e il suo stato che mi rende incerto.
Magnus Wolffelt,

0

È buono per i sistemi guidati da eventi ed è più bello dell'alternativa di avere un gruppo di osservatori che si osservano l'un l'altro, poiché è meno probabile che finisca con cicli infiniti involontari di osservatori che sparano eventi. Questo era un vero problema ai vecchi tempi VB, quando avevi i controlli ActiveX basati sugli eventi che potevano essere collegati tra loro con i gestori di eventi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.