TranslateProject/published/201407/20140626 Joy of Programming--Fail Fast.md

59 lines
4.6 KiB
Markdown
Raw Normal View History

2014-07-28 17:27:11 +08:00
编程的乐趣:快速终止!
================================================================================
![](http://www.opensourceforu.com/wp-content/uploads/2011/12/fail-350x262.jpg)
2014-07-28 17:27:11 +08:00
> 当软件出现问题的时候,它应该以一种很容易引起注意的方式马上终止。这种“快速终止”的方式值得借鉴,我们会在这期专栏里谈谈这个重要的概念。
2014-07-28 17:27:11 +08:00
一开始“快速终止”看上去是一种会影响可靠性的不好的实践——为什么一个系统在还可以继续运行的时候要崩溃或者说终止对于这个我们需要理解快速终止是和Heisenbugs对于不易复现bug的一种称呼紧密联系在一起的。
2014-07-28 17:27:11 +08:00
考虑一下Bohrbugs对于能够重现的bug的一种称呼它们在一个给定输入的条件下总是会出现比如访问空指针。这类问题很容易测试、复现并修复。而如今所有有经验的程序员应该都面对过这样的情形导致崩溃的bug在重启软件后就不再出现了。不管花多少时间或努力去重现问题那个bug就是跟我们捉迷藏。这种bug被称为Heisenbugs。
2014-07-28 17:27:11 +08:00
花在寻找、修复和测试Heisenbugs上的努力比起Bohrbugs来说要高出一个数量级。一种避免Heisenbugs的策略是将它们转化为Bohrbugs。怎么做呢预测可能导致Heisenbugs的因素然后尝试将它们变成Bohrbugs。是的这并不简单而且也并不是一定可行但是让我们来看一个能产生效果的特殊例子。
2014-07-28 17:27:11 +08:00
并发编程是Heisenbugs经常出现的一个典范。我们的例子就是一个Java里和并发相关的问题。在遍历一个Java集合的时候一般要求只能通过Iterator的方法对集合进行操作比如remove()方法。而在遍历期间,如果有另一个线程尝试修改底层集合(因为编程时留下的错误),那么底层集合就可能会被破坏(例如,导致不正确的状态)。
2014-07-28 17:27:11 +08:00
类似这种不正确的状态会导致不确定的错误——假如我们幸运的话实际上这很不幸程序可以继续执行而不会崩溃但是却给出错误的结果。这种bug很难重现和修复因为这一类的程序错误都是不确定的。换句话说这是个Heisenbug。
2014-07-28 17:27:11 +08:00
幸运的是Java Iterators会尝试侦测这种并发修改并且当发现时会抛出异常`ConcurrentModificationException`而不是等到最后再出错——那样也是没有任何迹象的。换句话说Java Iterators也遵从了“快速终止”的方法。
2014-07-28 17:27:11 +08:00
如果一个`ConcurrentModificationException`异常在正式版软件中发生了呢根据在Javadoc里对这个异常的说明它“只应该被用于侦测bug”。换句话说`ConcurrentModificationException`只应该在开发阶段监听和修复,而不应该泄漏到正式代码中。
2014-07-28 17:27:11 +08:00
好吧如果正式软件确实发生了这个异常那它当然是软件中的bug应当报告给开发者并修复。至少我们能够知道曾经发生过一次针对底层数据结构的并发修改尝试而这是软件出错的原因而不是让软件产生错误的结果或是以其他现象延后出错这样就很难跟踪到根本原因
2014-07-28 17:27:11 +08:00
“防止崩溃”的途径就意味着开发健壮的代码。一个很好的编写容错代码的例子就是使用断言。很可惜的是,关于断言的使用有大量不必要的公开争论。其中主要的批评点是:它在开发版本中使用,而在发布版中却被关掉的。
2014-07-28 17:27:11 +08:00
不管怎么样这个批评是错误的从来没有说要用断言来替代应该放到发布版软件中的防御式检查代码。例如断言不应该用来检查传递给函数的参数是否为空。相应的应该用一个if语句来检查这个参数是否正确否则的话抛出一个异常或是提前返回来适合上下文。然而断言一般可以用于额外检查代码中所作出的假设这些假设应该一直为真才正常。例如用一个语句来检查在进行了入栈操作后栈应该不是空的例如对“不变量”的检查
2014-07-28 17:27:11 +08:00
所以,快速终止,随时中断,那么你就走在开发更加健壮代码的道路上了。
--------------------------------------------------------------------------------
via:http://www.opensourceforu.com/2011/12/joy-of-programming-fail-fast/
2014-07-28 17:27:11 +08:00
译者:[zpl1025](https://github.com/zpl1025) 校对:[ReiNoir](https://github.com/reinoir)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创翻译,[Linux中国](http://linux.cn/) 荣誉推出
[1]:
[2]:
[3]:
[4]:
[5]:
[6]:
[7]:
[8]:
[9]:
[10]:
[11]:
[12]:
[13]:
[14]:
[15]:
[16]:
[17]:
[18]:
[19]:
[20]: