我最近刚开始玩事件驱动的架构,来自一个非常标准的面向对象的思维模式。
我注意到的第一件事是,理解和追踪程序的难度似乎随着程序的大小呈指数级增长。虽然小型宠物项目很容易遵循,但感觉代码很快会变成意大利面。
我理解我是这种发展思维的新手,并不是所有我的面向对象的担忧都会延续下去。有没有关于编写可维护,可理解的事件驱动代码的资源?使用node.js或Twisted或Event Machine的人对此有何看法?
答案 0 :(得分:7)
我去年在雅虎做过a talk on this topic。
答案 1 :(得分:6)
答案 2 :(得分:6)
Martyn Loughran wrote an excellent short article完全是为了避免回调意大利面。
我对他的文章非常喜欢的是过程将意大利面条改进成美观干净的东西;一开始看起来似乎有点形式化,但当你看到最终结果时,我认为你会同意他用干净,清晰的代码展示真正的艺术性。
答案 3 :(得分:4)
我将使用Python作为示例,因为我正在使用它来构建大型分布式应用程序。
Twisted python允许使用inlinecallbacks或(稍微丑陋)deferredGenerator样式的非常命令式样式。这些方法允许您编写使用事件驱动的回调代码的过程,这些代码更易于阅读和理解。该实现将您的函数转换为一个延迟序列,产生一系列延迟。
具体来说,您不必构建一组深度嵌套的回调函数/ lambdas / closures,而是可以在任意点处将函数控制权返回给事件循环。如果您愿意,可以在心理上将其重新标记为协同程序或协作式多任务处理。它完成了工作。一个例子是(使用uglier deferredGenerator样式),如下所示:
@defer.deferredGenerator
def foo(arg):
bar = nonBlockingFunction(foo)
baz = waitForDeferred(aFunctionThatReturnsADeferredToo(bar))
yield baz #Returns control to the event loop
output = baz.getResult() #This gets the output of aFunctionThat...Too above
yield output #This is how we return a result instead of using return
@defer.deferredGenerator
def aFunctionThatReturnsADeferredToo(put_bar_here):
"""Stuff happens here...."""
...etc...
这里有另一个帖子显示了inlineCallbacks方法,它更干净,但需要python 2.5或更新版本(意思是不在Centos / RHEL 5系列中,我很遗憾地为我的应用程序停留)。如果你可以使用它,那么。
正如你所看到的,这看起来像你熟悉和喜爱的旧学校python命令,但如果没有大量的嵌套函数和lambda,它就更容易维护。我仍然希望python有阻止。
对于调试,您可以使用初始化代码中某处的defer.setDebugging(True)调用打开扭曲反应器调试。这将附加在您的代码中引发异常的原始回溯,以便您可以轻松地查看错误ACTUALLY发生的位置。只是记得在开始制作之前编辑setDebugging语句,因为它会产生大量的额外内省(如果你想完全恐惧的话,请在strace中观察它)。
答案 4 :(得分:4)
For Twisted,而不是使用旧的deferredGenerator我推荐使用inlineCallbacks;它允许您完全编写阻塞式代码,并且仍然可以很好地使用事件循环。
@defer.inlineCallbacks
def foo(arg):
bar = nonBlockingFunction(foo)
output = yield FunctionThatReturnsADeferredToo(bar)
defer.returnValue(output) #This is how we return a result instead of using return
答案 5 :(得分:1)
显然,随着时间的推移,已经有最佳实践和模型将继续发展。
然而,还要考虑规划编程为“小型宠物项目”提供相互交流的机会。想象一下,通过用户定义的回调,数千个分布式单个项目实时交互的世界。
用户和开发人员可以从上到下通过现有协议重新连接Web和应用程序,而不是依赖于现有的应用程序设计。然后,应用程序设计人员可以自由地专注于个别用例,而不是提供一刀切的解决方案或担心每一个可能的意外事件。
答案 6 :(得分:1)
我唯一的建议是认为功能性。