Czym różni się wzorzec publikowania i subskrybowania od gotos?

11

Rozumiem, że stwierdzenia Goto są na ogół niezadowolone . Ale wzorzec publikowania i subskrybowania wydaje się być koncepcyjnie podobny, ponieważ kiedy fragment kodu publikuje komunikat, wykonuje jednostronne przekazanie kontroli. Programista może nie mieć pojęcia, które części programu subskrybują ten komunikat.

Widziałem coś podobnego w wielu programach JavaScript, w których zdarzenia służą do wygodnego „przeskakiwania” między modułami. Czy brakuje mi czegoś na temat wzorców publikowania-subskrybowania lub zdarzeń?

gwg
źródło
5
return, try/catch, break, continue, switch- to wszystko goto z różnymi poziomami ograniczeń zbudowany w Goto uważane za szkodliwe jest szkodliwe dla myślenia o tym, jak prace kod..
@MichaelT: W przeważającej większości przypadków istnieją alternatywy dla goto, które ułatwiają rozumowanie kodu. Nie ma nic złego w docenieniu tego faktu. Szkoda wyrządzona jest tylko wtedy, gdy nie użyjesz goto, gdy jest to uzasadnione (co zwykle nie jest), lub jeśli użyjesz goto niedbale. Uważam, że Apple pokazał nam dobry przykład tego drugiego.
back2dos
... nie mam pojęcia, które części programu subskrybują ... : Pierwsza główna różnica gotopolega na s na końcu części . Druga ważna różnica nie ma pojęcia . Trzecia główna różnica polega na tym, że jest to koncepcyjnie a gosubnie a goto.
mouviciel
1
Jest bliżej „pochodzić” z INTERCAL.
CodesInChaos
@ back2dos to także dobry przykład tego, dlaczego wolę używać nawiasów klamrowych nawet dla bloków kodu o 1 linii.
MetaFight,

Odpowiedzi:

19

Tak, zdecydowanie czegoś brakuje . Gotos byłby zwykle używany, jak powiedziałeś, do wykonania jednokierunkowego przekazania kontroli.

Jednak wydarzenia tego nie robią. Kiedy kod uruchamia zdarzenie, doskonale wie, że po opublikowaniu zdarzenia (lub przetworzeniu, umieszczeniu w kolejce, odpaleniu itp.) Wykonanie kodu zostanie wznowione w następnym wierszu kodu, który wygenerował zdarzenie.

Zastosowanie goto tworzy bardzo ścisłe powiązanie między kodem, który wywołuje tę instrukcję, a kodem po stronie odbierającej. Deweloper musi posiadać dogłębną znajomość obu miejsc, aby móc korzystać z goto.

Z drugiej strony, kod uruchamiający zdarzenia zwykle nie wiedziałby ani nie obchodziło, kto jest zainteresowany słuchaniem tego zdarzenia. Nie mogło być słuchaczem. Lub może być 100 słuchaczy lub 0. Ci słuchacze mogą być w tym samym programie, w którym uruchomiono zdarzenie, mogą być w zupełnie innej aplikacji lub mogą znajdować się na innym komputerze. Jeśli chodzi o wydawcę, to po wygenerowaniu zdarzenia jego praca jest wykonywana.

Jeśli jesteś ze mną do tej pory, to, co opisałem powyżej, jest idealnym przypadkiem wzoru pub / sub. Niestety w prawdziwym świecie rzeczy nie zawsze są idealne i zdarzają się przypadki, w których wydawcy generują zdarzenie, subskrybent zostaje wywołany, zmienia cały szereg stanów i do czasu, gdy wykonanie kodu wraca do wydawcy, „świat” wydaje się mieć został wywrócony do góry nogami. I jestem pewien, że napotkałeś to w przeszłości, ponieważ ten warunek często pojawia się, gdy wzór pub / sub jest wdrażany w bardzo prosty sposób (np. Poprzez użycie delegatów lub zdarzeń w C # lub wskaźników funkcji / interfejsu w C / C ++).

Ale ten problem niekoniecznie jest wzorcem pub / sub, ale raczej jego implementacją. Właśnie dlatego wiele systemów polega na kolejkach, dlatego gdy wydarzenie jest publikowane, jest ono po prostu w kolejce, aby można je było później wywołać, dając wydawcy szansę na zakończenie wykonywania, gdy świat jest cały czas nietknięty. Po zakończeniu pracy wydawcy pętla zdarzeń (inaczej pętla wysyłania) wyskoczy ze zdarzeń i wywoła subskrybentów.

DXM
źródło
+1 publikowanie / subskrybowanie umożliwia luźne łączenie; goto nie
Fuhrmanator
6

Istnieje kilka różnic. Po pierwsze, gdy kod wykonuje GOTO, rezygnuje z kontroli i nie ma gwarancji, że odzyska kontrolę. Wydawca w pubie / sub będzie jednak nadal działał i wykonywał swoją logikę, wysyłając odpowiednio wiadomości. Jego zachowanie jest zrozumiałe i przewidywalne.

Po drugie, subskrybent będzie odbierał wiadomości i w przeciwieństwie do GOTO, sama wiadomość ma kontekst. Zarówno rodzaj wiadomości, jak i wszelkie przenoszone przez nią właściwości, pomagają subskrybentowi wykonać swoją rolę. Po obsłużeniu wiadomości subskrybent nadal może odbierać nowe wiadomości. Więc jego zachowanie jest zrozumiałe i przewidywalne.

Duża różnica polega na tym, że wydawca i subskrybent mają dobrze zdefiniowany przebieg wykonywania i zasadniczo będą wykonywać pętle i wykonywać swoje zadania podczas wysyłania i odbierania wiadomości. Kod z GOTO może być dobrze napisany i uporządkowany, ale może również ulec degradacji i nie ma tej samej gwarancji jasno zrozumiałego zachowania.

Ale masz rację. Ktoś mógłby napisać system pub / sub z tak wieloma wiadomościami i tyloma małymi skokami, że śledzenie przebiegu przetwarzania może stać się koszmarem. Z drugiej strony możesz napisać system z GOTO, który zachowuje się bardzo uporządkowany i łatwo go zrozumieć. (Myślę o kodzie asemblera dla bardzo złożonych systemów przed przejęciem języków symbolicznych).

Ale zwykle oddzielenie od produkcji uzyskane z publikacji / sub upraszcza problem rozproszonego przetwarzania i rozdziela logikę w systemie. Zwykle proste GOTO zwykle tworzą skomplikowane systemy, w których zrozumienie przepływu kontroli staje się problematyczne.

Obrabować
źródło