ers truly don’t know what they want in a program until they use it.
事实一:
“今天(2010-10-01)上午我们的某版本系统在某省出现了故障,该版本在这个省上线恰好将近6个月^_^,系统上线以来一直运行良好,直到这次故障。故障现象为"挂死":所有进程都挂死在某一把锁的lock上。以前出现这种情况多为某个进程加锁后,在锁内异常退出,未能释放锁而导致其他进程挂死。这种"挂死"多是代码中访问非法内存地址 导致的,一般都会有core文件dump出来。不过这次出现挂死后,我们并未找到core文件的影子。查看系统运行日志也无果。通过脚本将所有该应用的子进程的运行栈快照收集到一个文件中,然后对这个数据庞大的文件进行分析,以试图找到一些蛛丝马迹。
分析发现绝大多数子进程都挂起了,其运行栈栈顶多为:
lwp_mutex_timedlock (f1444c28, 0)
不过只有一个进程与众不同,它的栈顶 是一个我们自己实现的函数,这里暂且称这个函数为foo_func吧。迅速查看foo_func的源码实现,发现一个while循环,第一时间想到:是不是foo_func进入while死循环了?在故障应用主机上用top查看一下
系统运行状态,发现确有一个进程占用cpu很高,而且持续很高。pstack一下这个进程,栈顶端果真就是foo_func,“死循环”的推论是正确的。 即使这个进程死循环了,怎么会连累其他进程也停止工作了呢?原因就在于这个死循环是在这个子进程获得锁之后发生的,因为死循环了,导致无法释放这把锁,其他子进程干着急也无可奈何!
foo_func为何能进入死循环?仔细斟酌一下foo_func的代码也不难得出:代码中混用了int和unsigned char,导致数组下标值变为负数,数组访问溢出,读取到的值是随机值,所以死循环也是随机发生的(之前几个月运行都良好也是因为这个原因)。”
..
.
Java开发最容易犯的21种错误
url:dev.yesky/87/8128587.shtml
1.Duplicated Code
代码重复几乎是最常见的异味了。他也是Refactoring的主要目标之一。代码重复往往来自于copy-and-paste的编程风格。与他相对应OAOO是一个好系统的重要标志。
2.Long method
它是传统结构化的“遗毒”。一个方法应当具有自我独立的意图,不要把几个意图放在一起。
3.Large Class
大类就是你把太多的责任交给了一个类。这里的规则是One Class One Responsibility.
4.Divergent Change
一个类里面的内容变化率不同。某些状态一个小时变一次,某些则几个月一年才变一次;某些状态因为这方面的原因发生变化,而另一些则因为其他方面的原因变一次。面向对象的抽象就是把相对不变的和相对变化相隔离。把问题变化的一方面和另一方面相隔离。这使得这些相对不变的可以重用。问题变化的每个方面都可以单独重用。这种相异变化的共存使得重用非常困难。
5.Shotgun Surgery
这正好和上面相反。对系统一个地方的改变涉及到其他许多地方的相关改变。这些变化率和变化内容相似的状态和行为通常应当放在同一个类中。
6.Feature Envy
对象的目的就是封装状态以及与这些状态紧密相关的行为。如果一个类的方法频繁用get 方法存取其他类的状态进行计算,那么你要考虑把行为移到涉及状态数目最多的那个类。
7.Data Clumps
某些数据通常像孩子一样成群玩耍:一起出现在很多类的成员变量中,一起出现在许多方法的参数中,这些数据或许应该自己独立形成对象。
8.Primitive Obsession
面向对象的新手通常习惯使用几个原始类型的数据来表示一个概念。譬如对于范围,他们会使用两个数字。对于Money,他们会用一个浮点数来表示。因为你没有使用对象来表达
问题中存在的概念,这使得代码变的难以理解,解决问题的难度大大增加。好的习惯是扩充语言所能提供原始类型,用小对象来