Wie unterscheidet sich das Publish-Subscribe-Muster von Gotos?


11

Mein Verständnis ist, dass Goto-Aussagen im Allgemeinen verpönt sind . Das Publish-Subscribe-Muster scheint jedoch konzeptionell ähnlich zu sein, da ein Code, der eine Nachricht veröffentlicht, eine einseitige Übertragung der Kontrolle durchführt. Der Programmierer hat möglicherweise keine Ahnung, welche Teile des Programms diese Nachricht abonnieren.

Ich habe etwas Ähnliches in vielen JavaScript-Programmen gesehen, in denen Ereignisse verwendet werden, um bequem über Module hinweg zu "hüpfen". Fehlt mir etwas an den Publish-Subscribe- oder ereignisgesteuerten Mustern?


5
return, try/catch, break, continue, switch- das sind alle goto mit verschiedenen Ebenen der Beschränkung gebaut in Goto als schädlich zu überlegen , wie der Code funktioniert schädlich ist..

@MichaelT: In den allermeisten Fällen gibt es Alternativen zu goto, die es einfacher machen, über Code nachzudenken. Es schadet nicht, diese Tatsache zu würdigen. Schaden entsteht nur, wenn Sie goto nicht verwenden, wenn dies gerechtfertigt ist (was normalerweise nicht der Fall ist), oder wenn Sie goto nachlässig verwenden. Ich glaube, Apple hat uns ein gutes Beispiel für Letzteres gezeigt.
back2dos

... keine Ahnung, welche Teile des Programms abonniert sind ... : Der erste große Unterschied gotoliegt im s am Ende der Teile . Der zweite große Unterschied liegt in keiner Ahnung . Der dritte große Unterschied ist, dass es konzeptionell ein gosub, nicht ein ist goto.
Mouviciel

1
Es ist näher an INTERCALs "kommen von".
CodesInChaos

@ back2dos ist auch ein gutes Beispiel dafür, warum ich es vorziehe, geschweifte Klammern auch für einzeilige Codeblöcke zu verwenden.
MetaFight

Antworten:


19

Ja, Ihnen fehlt definitiv etwas . Gotos werden normalerweise, wie Sie sagten, verwendet, um eine Einweg-Kontrollübertragung durchzuführen.

Ereignisse tun dies jedoch nicht. Wenn der Code das Ereignis auslöst, weiß er genau, dass die Codeausführung nach Veröffentlichung (oder Verarbeitung, Warteschlange, Auslösung usw.) in der nächsten Zeile des Codes, der das Ereignis generiert hat, fortgesetzt wird.

Die Verwendung von goto schafft eine sehr enge Kopplung zwischen dem Code, der diese Anweisung aufruft, und dem Code, der sich auf der Empfangsseite befindet. Entwickler müssen beide Orte genau kennen, um goto verwenden zu können.

Auf der anderen Seite würde Code, der Ereignisse auslöst, normalerweise nicht wissen oder sich nicht darum kümmern, wer daran interessiert ist, auf dieses Ereignis zu warten. Es könnte einen Zuhörer geben. Oder es können 100 oder 0 Listener vorhanden sein. Diese Listener befinden sich möglicherweise im selben Programm, in dem das Ereignis ausgelöst wurde, oder sie befinden sich in einer völlig anderen Anwendung oder auf einem anderen Computer. Für den Verlag ist seine Arbeit erledigt, sobald er das Ereignis generiert.

Wenn Sie bisher bei mir sind, ist das, was ich oben beschrieben habe, der ideale Fall für ein Pub / Sub-Muster. Leider sind die Dinge in der realen Welt nicht immer ideal und es gibt Fälle, in denen Publisher ein Ereignis generieren, ein Abonnent aufgerufen wird, eine ganze Reihe von Status ändert und zu dem Zeitpunkt, an dem die Codeausführung zum Publisher zurückkehrt, "die Welt" zu haben scheint wurde auf den Kopf gestellt. Und ich bin sicher, dass Sie in der Vergangenheit darauf gestoßen sind, da diese Bedingung häufig auftritt, wenn Pub / Sub-Muster auf sehr einfache Weise implementiert werden (z. B. durch Verwendung von Delegaten oder Ereignissen in C # oder Funktions- / Schnittstellenzeigern in C. / C ++).

Dieses Problem ist jedoch nicht unbedingt das Pub / Sub-Muster, sondern die Implementierung. Aus diesem Grund sind viele Systeme auf Warteschlangen angewiesen, sodass ein veröffentlichtes Ereignis einfach in die Warteschlange gestellt wird, um später aufgerufen zu werden, sodass der Herausgeber die Ausführung beenden kann, während die Welt noch intakt ist. Wenn der Herausgeber seine Arbeit erledigt hat, wird eine Ereignisschleife (auch als Versandschleife bezeichnet) die Ereignisse abbrechen und Abonnenten aufrufen.


+1 Publish / Subscribe ermöglicht lose Kopplung; goto nicht
Fuhrmanator

6

Es gibt einige Unterschiede. Erstens, wenn ein Code GOTO ausführt, gibt er die Kontrolle auf und es gibt keine Garantie dafür, dass er die Kontrolle wiedererlangt. Ein Publisher in Pub / Sub wird jedoch weiterhin ausgeführt und führt seine Logik aus und sendet gegebenenfalls Nachrichten aus. Sein Verhalten ist verständlich und vorhersehbar.

Zweitens empfängt der Teilnehmer Nachrichten, und im Gegensatz zu GOTO trägt die Nachricht selbst den Kontext. Sowohl der Nachrichtentyp als auch die darin enthaltenen Eigenschaften helfen dem Abonnenten, seine Rolle auszuführen. Nach der Bearbeitung einer Nachricht kann der Teilnehmer weiterhin neue Nachrichten entgegennehmen. Auch das Verhalten ist verständlich und vorhersehbar.

Der große Unterschied besteht darin, dass der Herausgeber und der Abonnent einen genau definierten Ausführungsfluss haben und im Wesentlichen weiterhin Schleifen ausführen und ihre Arbeit erledigen, während sie Nachrichten senden und empfangen. Code mit GOTOs kann gut geschrieben und ordentlich sein, aber er kann sich auch verschlechtern, und es gibt nicht die gleiche Garantie für klar verstandenes Verhalten.

Du hast aber recht. Jemand könnte ein Pub / Sub-System mit so vielen Nachrichten und so vielen kleinen Sprüngen schreiben, dass das Verfolgen des Verarbeitungsflusses zu einem Albtraum werden könnte. Andererseits könnten Sie ein System mit GOTOs schreiben, das sich äußerst ordentlich verhält und leicht zu verstehen ist. (Ich denke an Assembler-Code für sehr komplexe Systeme, bevor symbolische Sprachen übernommen wurden.)

In der Regel vereinfacht die Entkopplung von Pub / Sub das Problem der verteilten Verarbeitung und entkoppelt die Logik in Ihrem System. In der Regel neigen geradlinige GOTOs dazu, komplizierte Systeme zu erstellen, bei denen das Verständnis des Kontrollflusses problematisch wird.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.