Manchmal finde ich diese APIs im Message Hub-Stil, zum Beispiel das Cocoa NSNotificationCenter: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/Reference/Reference.html
Normalerweise bieten diese APIs einen globalen Zugriffspunkt, an dem Sie Nachrichten / Ereignisse abonnieren oder senden. Ich denke, dies ist ein Problem, weil es eine flache und unstrukturierte Programmarchitektur fördert, bei der Abhängigkeiten nicht explizit in der API, sondern im Quellcode verborgen sind. Sie sind nicht gezwungen, über Objekteigentum und -hierarchien nachzudenken, sondern können jedes Objekt in Ihrem Programm dazu bringen, dass Code überall aufgerufen wird. Aber vielleicht ist das eine gute Sache?
Fördert dieses Muster im Allgemeinen ein gutes oder schlechtes Programmdesign und warum? Ist der Code schwieriger oder einfacher zu testen?
Verzeihen Sie mir, wenn diese Frage zu vage oder zu weit gefasst ist. Ich versuche, mich mit den möglichen Konsequenzen einer umfangreichen Verwendung einer solchen API und den verschiedenen Verwendungsmöglichkeiten auseinanderzusetzen.
Bearbeiten: Ich denke, mein größtes Problem mit diesem Muster ist, dass die API über Abhängigkeiten und Objektkopplungen "liegt" und mit diesem Beispiel veranschaulicht werden kann:
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
quelle
Antworten:
Ich würde nicht so weit gehen zu sagen, dass es schlechte Programmierung fördert. Aber es kann leicht missbraucht werden.
Nun, was ist die eigentliche Idee?
Die Quelle der Benachrichtigung macht nur seine Benachrichtigung. Es wird keine Annahme über die Existenz potenzieller Beobachter oder ähnliches gemacht. Ein Beobachter registriert sich für Benachrichtigungen, die er bearbeiten soll. Der Beobachter geht nicht davon aus, wie viele potenzielle Quellen für die Benachrichtigungen vorhanden sind, mit denen er möglicherweise umgeht.
Dies ist eine Möglichkeit, eine Abhängigkeitsinjektion zu erzielen, ohne dass Quellen jemals Beobachter kennen oder Beobachter Quellen kennen. Damit jedoch das gesamte System funktioniert, müssen Sie die richtigen Beobachter für die richtigen Benachrichtigungen anschließen. Dieses System ist sogar anfällig für Tippfehler, da es nicht auf Kompilierzeit überprüft werden kann.
Die größte Gefahr besteht natürlich darin, dass jemand damit Tonnen von Objekten weltweit für 1-1 Anrufe verfügbar macht.
quelle
Asynchrones Messaging ist ein gutes Architekturprinzip für große Systeme, die skaliert werden müssen
Das Java-Äquivalent dazu ist JMS und wird allgemein als eine gute Sache angesehen .
Dies liegt daran, dass die Entkopplung Ihres Client-Codes von dem Code gefördert wird, der die Nachricht tatsächlich verarbeitet. Der Client-Code muss lediglich wissen, wo er seine Nachricht veröffentlichen soll. Der Service-Code muss lediglich wissen, wo Nachrichten abgeholt werden sollen. Kunde und Service kennen sich nicht und können sich daher bei Bedarf unabhängig voneinander ändern.
Sie können den URI des Nachrichten-Hubs problemlos externalisieren, um ihn konfigurierbar und nicht im Quellcode eingebettet zu machen.
quelle
Dies ist eine typische Oberserver-Pattern-Implementierung (oder manchmal als Listener-Pattern oder manchmal als Subscriber / Publisher-Pattern bezeichnet). In Anwendungen, in denen dieses Verhalten nützlich ist, ist es ein gutes zu implementierendes Muster. Es sollte kein Muster implementiert werden, wenn es der Lösung keinen Wert hinzufügt.
Aus Ihrer Frage geht hervor, dass Sie besorgt sind, dass alles über das NotificationCenter Bescheid weiß und dass globale Dinge BAD sind. Manchmal sind globale Dinge schlecht. Aber schauen wir uns die Alternative an. Angenommen, Sie haben zwei Komponenten. In diesem Beispiel spielt es keine Rolle, was sie tun oder was sie sind. Component1 enthält einige Daten, die bearbeitet oder auf irgendeine Weise geändert wurden. Component2 möchte über Änderungen an Daten des von Compoent1 verwalteten Typs informiert werden. Sollte Component2 über die Existenz von Component1 Bescheid wissen? Oder ist es besser für Component2, eine Nachricht zu abonnieren / abzuhören, die besagt, dass eine Komponente irgendwo in der App Daten geändert hat, an denen sie interessiert ist? Nehmen Sie dieses Beispiel und multiplizieren Sie es mit Dutzenden oder mehr Komponenten. Sie können sehen, wo der Wert des Musters liegt.
Ist es eine perfekte Lösung für jede Situation, nein. Abstrahiert es die Kommunikation zwischen Komponenten und sorgt für eine lockere Kopplung, ja.
quelle
Es ist gut für ereignisgesteuerte Systeme und besser als die Alternative, wenn sich ein Haufen Beobachter gegenseitig beobachtet, da es weniger wahrscheinlich ist, dass unbeabsichtigte Endlosschleifen von Beobachtern Ereignisse auslösen. Dies war ein echtes Problem in den alten VB-Tagen, als es ereignisgesteuerte ActiveX-Steuerelemente gab, die mit Ereignishandlern miteinander verbunden werden konnten.
quelle