为什么快速失败型计划比防御型计划短?
我读过有关 Erlang 等语言的快速失败编程风格如何导致程序比大多数其他语言中的防御风格短得多的程序。这对于所有类型的程序都是正确的吗?其原因是什么?
I have read about how the fail-fast style of programming in languages like Erlang end up with much shorter programs than the defensive style found in most other languages. Is this correct for all types of programs and what is the reasoning for this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
快速失败程序不一定比防御式程序短:它取决于使防御性代码安全所需的实现和措施。
就 Erlang 而言,由于声明式风格以及 VM 确保为您生成错误情况的方式,快速失败程序通常更短。例如,在函数中:
传递给函数的任何意外值都将导致错误,该错误可以由另一个进程(即:主管)捕获和处理。此类错误也永远不会危及整个系统,并且不需要将代码添加到函数本身中——这一切都是通过预定行为在正常执行路径之外完成的。
在快速失败不是常态的动态语言中,您必须手动检查边界并自己抛出异常。然后,如果您不希望整个系统崩溃,则必须在本地捕获异常(包括顶级 try ... catch)。错误处理代码通常必须插入到整个正常执行路径中。
在快速失败不是常态的静态语言中,代码的长度将在很大程度上取决于您拥有的类型系统。如果语言允许定义编译器最终检查边缘情况的类型,那么您通常不必在代码内部、非确定性事件(文件不起作用、意外的用户输入等)之外处理此问题。具有此类类型系统的语言,许多错误将在运行时之前被捕获,因此您不会有那么多的防御案例。
当错误处理无法避免时,支持快速失败习惯用法的语言(如 Erlang)将允许比不支持快速失败习惯用法(静态或非静态)的语言更清晰的代码,主要是因为特殊情况的代码不会与理想执行路径的代码。
Fail-fast programs aren't necessarily shorter than defensive style programs: it depends on the implementation and the measures needed to make your defensive code safe.
In the case of Erlang, the fail-fast programs are usually shorter because of the declarative style and how the VM makes sure to generate error cases for you. As an example, in the function:
Any unexpected value passed to the function will result in an error that can be caught and handled by another process (ie.: a supervisor). Such errors will also never endanger the system as a whole and don't require code to be added to the function itself -- it's all done outside of the normal execution path by predetermined behaviors.
In a dynamic language where fail-fast isn't the norm, you would have to manually check the boundaries and throw an exception yourself. Then you must catch the exception locally (top-level try ... catches included) if you don't want the whole system to go down. The error handling code usually has to be inserted throughout the normal execution path.
In a static language where fail-fast isn't the norm, then how long your code will be will highly depend on the type system you have. If the language allows to define types where the edge cases end up checked for you by the compiler, then you usually do not have to handle this inside the code, outside of nondeterministic events (files not working, unexpected user input, etc.) In languages with such type systems, many errors will be caught before runtime and so you won't have as many defensive cases.
When error handling can't be avoided, languages supporting fail-fast idioms (like Erlang) will allow for arguably clearer code than languages that don't (static or not), mainly because the code for special cases isn't mixed in with the code for the ideal execution path.
请参阅 Joe Armstrong 的 论文 的第 4.3 和 4.4 节。
See sections 4.3 and 4.4 of Joe Armstrong's thesis.
快速失败编程风格专注于更好的代码可读性和调试。用户体验是次要目标:用户可能会遇到奇怪的错误消息或程序故障,但更高的代码质量使程序员可以轻松找到错误并纠正问题。
相反,防御式编程侧重于来自用户和代码其他部分的验证输入。代码更加冗长,因为程序员必须仔细验证输入并在出现错误时优雅地失败。这会导致更多的代码(从程序员的角度来看)和更健壮的应用程序(从用户的角度来看)。
The fail-fast style of programming is focused on better code readability and debugging. The user experience is a secondary target: a user may experience strange error messages or program failures, but the greater quality of code allows programmers to easily find the bug and correct the issue.
Defensive style programming, instead, focuses on validation input from user and from other portions of code. The code is more verbose, because the programmer has to carefully verify input and fail gracefully in case of error. This lead to more code (from the programmers' point of view) and a more robust application (from the users' point of view).