发布-订阅模式与gotos有何不同?


11

我的理解是,Goto语句通常不被接受。但是,发布-订阅模式在概念上似乎是相似的,因为一段代码发布一条消息时,它将执行单向控制转移。程序员可能不知道程序的哪些部分正在订阅此消息。

我在许多JavaScript程序中都看到了类似的东西,在这些程序中,事件用于方便地跨模块“跳跃”。我是否缺少有关发布-订阅或事件驱动模式的信息?


5
returntry/catchbreakcontinueswitch-这些 goto与各级建成后藤限制认为有害有害如何代码工作的思考。

@MichaelT:在绝大多数情况下,goto都有替代方法,可以使推理代码变得更容易。赞赏这一事实没有任何害处。仅当您在有保证的情况下不使用goto(通常通常不使用)或不小心使用goto时,才会造成危害。我相信苹果公司向我们展示了后者的一个很好的例子
back2dos

...不知道程序的哪些部分正在订阅...:与第一个主要的不同之goto处在于s 部分的末尾。第二个主要区别在于不知道。第三个主要区别是,从概念上讲,它gosub不是a goto
mouviciel 2014年

1
它更接近INTERCAL的“来自”。
CodesInChaos

@ back2dos也是一个很好的示例,说明了为什么即使对于1行代码块,我还是更喜欢使用花括号。
MetaFight 2014年

Answers:


19

是的,您肯定缺少某些东西。如您所说,通常将Gotos用于执行控制的单向转移。

但是,事件不会那样做。当代码触发事件时,它完全知道一旦事件被发布(或处理,排队,触发等),代码执行将在生成事件的代码的下一行继续执行。

goto的使用在调用该语句的代码和接收端的代码之间建立了非常紧密的耦合。开发人员必须对这两个地方都有深入的了解才能使用goto。

另一方面,引发事件的代码通常将不知道或不在乎谁有兴趣监听该事件。有可能是一个倾听者。或可能有100个侦听器或0个侦听器。这些侦听器可能位于触发事件的同一程序中,或者可能位于完全不同的应用程序中,或者可能位于其他计算机上。就发布者而言,一旦产生事件,他的工作就完成了。

如果您到目前为止与我在一起,那么我上面描述的就是发布/订阅模式的理想情况。不幸的是,在现实世界中,事情并不总是那么理想,在某些情况下,发布者会生成事件,订阅者被调用,改变整个状态,并且等到代码执行返回发布者时,“世界”似乎已经被颠倒了。而且我敢肯定,您过去曾经遇到过这种情况,因为当以非常简单的方式实现pub / sub模式时(例如,通过在C#中使用委托或事件,或者在C中使用函数/接口指针),常常会出现这种情况/ C ++)。

但是这个问题并不一定是pub / sub模式,而是它的实现。这就是为什么许多系统都依赖队列,以便事件发布后,只需将其排队等待稍后调用,就可以使发布者有机会在世界完好无损的情况下完成执行。发布者完成工作后,将弹出一个事件循环(又称为调度循环),退出事件并调用订阅者。


+1个发布/订阅允许松散耦合;转到不
Fuhrmanator

6

有几个区别。首先,当代码执行GOTO时,它将放弃控制,并且无法保证它将重新获得控制权。但是,发布/订阅中的发布者将继续运行并执行其逻辑,并在适当时发送消息。它的行为是可以理解和可预测的。

其次,订户将接收消息,并且与GOTO不同,消息本身带有上下文。消息的类型及其所携带的任何属性都有助于告诉订户执行其角色。并且,在处理一条消息之后,订户仍然能够接收新消息。因此,它的行为也是可以理解和可预测的。

最大的区别在于,发布者和订阅者具有定义明确的执行流程,并且实质上,他们将在发送和接收消息的同时保持循环并执行其工作。使用GOTO 编写的代码可以编写得井井有条,但是也会降级,并且不能保证行为得到清晰的理解。

你说的没错。有人可能会编写一个发布/订阅系统,其中包含许多消息和许多小跳转,因此跟踪处理流程可能会成为噩梦。另一方面,您可以编写一个具有GOTO的系统,该系统的行为极为有序且易于理解。(我正在考虑在符号语言接管之前为非常复杂的系统汇编代码。)

但是通常,您从pub / sub中获得的解耦简化了分布式处理的问题,并使系统内的逻辑解耦。同样,通常,直接的GOTO倾向于创建复杂的系统,在这些系统中,了解控制流变得很困难。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.