每行代码都有潜在的Bug
作者:网络转载 发布时间:[ 2015/5/13 10:38:43 ] 推荐标签:软件测试管理
去年夏天我写了一些代码来实现从一个哈希表中获取一条消息。这条消息是将要通过另外一个线程放入哈希表中的。这里会有很小的概率发生冲突,即一开始查找消息的时候它还没有被保存进去。查找的代码如下:
while ((message = map.get(key)) == null && System.currentTimeMillis() < timeoutTime) {
wait(1000);
}
wait() 函数调用阻塞当前线程,等待负责向表存入消息的线程调用 notifyAll() 函数。这里 1000 表示 1 秒。大约 5 秒后将会超时。
上面的代码是简单而且正确的。它将会一直保持循环,直到获取得到数值或者超时。超时多延迟1秒,但在这个案例中不会有问题。(或者说,直到超时发生,你才会遇到更多严重的问题)
代码被另外两个人评审。两个人都抱怨 wait() 函数需要等待”当前”到超时之间的整个时长,而不是仅仅 1 秒。他们认为我的代码不必要地唤醒了线程五次。我的回复是只有在第一秒内是有可能读取到消息的,而且唤醒一个线程的代价并不大。我认为他们提出的代码会太复杂,而且更有可能存在bug。
他们都说,“一个减法并不复杂”,然后回到了自己的座位上将他们修改后的版本通过邮件发送给我,想要以此证明他们的办法是多么简单。两个人的代码分别都出现了一个 bug。第一个人的 bug很简单:他使用了错误的常量进行计算。但第二个人的bug却非常微妙:
while ((message = map.get(key)) == null && System.currentTimeMillis() < timeoutTime) {
wait(timeoutTime - System.currentTimeMillis());
}
这里会存在很小的可能性使得在做减法时,当前时间超过了超时的阈值,从而产生一个负值并传递给了wait(),进而会抛出一个IllegalArgumentException的异常。为了省得计算机一次罕见的线程切换,他引入了一个会偶尔发生并将不可思议地导致运算失败的bug。
(2010年3月15日更新:Ajit Mandalay指出另外一个不好的细节:减法得到0,这意味着“无穷”,循环有可能永远不会退出)
你写的每一行代码都可能会有一个潜在的bug。所以,除非是当前立刻需要的或者程序缺了不能正常运行的,请不要写任何代码。不要推测性地写例程。如果不是立刻需要,不要写抽象层。如果一个优化会增加任何的复杂性,哪怕是一个减法,也请抵制它。否则五年后,当你的代码中充满有可能是错误的而又从未真正需要的代码时,你会非常遗憾后悔的。
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11