今天终于看完了《零缺陷程序设计》,这可能是我看的计算机书中,按时间/页来算
时间最长的一本了.薄薄200页看了一个半月.期间主要是因为放假了就懒得翻书了.
不过更长的时间间隔可以让我有充足的时间去体会净室工程的实质.
"净室软件工程",作为程序员应该都听说过这个名字吧,但真正了解他的却真的不多
(有点像我喜欢的python).不了解同时还带来了偏见,这个随笔的最后我打算就
别人的一些见解发表一下自己的看法.
净室工程的核心思想是在软件生产的过程中制造出几乎没有缺陷的程序.
对改进软件质量这种方法是非常有效的,通常每千行错误不超过10个,
已有的项目一般做1个左右,甚至还有0.5的.
实现这点用的核心方法就是"验证":证明代码是正确的,而不是通过测试去debug.
要使软件可验证,就要将代码一定程度(注意不要过度)得形式化.
在所有论述之前先要建立这个观点:代码(也是程序)是对输入状态进行变换得到输出状态的一个函数.
程序设计基于预期函数,程序必须"匹配"对应的预期函数.
对大的预期函数可以分解为几个简单的部分分别验证(就是自顶向下的分解),
随后根据替换原则在验证大的预期函数(自底向上得归约).
具个小例子:(P32)
[code]
[y>x -> x,y := y,x
|true-> I]
if (y > x)
[x,y := y,x]
{
int temp;
temp = x;
x = y;
y = temp;
}
[/code]
在验证的时候跟踪表是一个很重要的公正,它让你轻松应对比较复杂的情况.
关于被验证的程序和预期函数的关系,应该叫"匹配",
被验证的程序的处理能力不一定要完全和预期函数相同.
通常如果预期函数是F(),程序所作的变换是F*()
那么:通常是D(F)是D(F*)的子集,程序的处理能力大于预期函数,
要验证的函数在预期函数的定义域内和预期函数相等,形式得表示:
F*|D(F)=F.
验证中最麻烦的应该是迭代(还有递归)的验证,不过好在所有的迭代都可以转为递归,
而递归函数的验证有一套数学方法了.书中讲了一大堆,实质就是数学归纳法.
1. 验证带头性(我们讲高等代数的老师喜欢这么叫,就是归纳的时候第一个元素的验证,
一般是不证自明的,比如在0时的情况)
2. 验证在假设成立的时候,原来的命题成立.
说得有点模糊,不过知道归纳法的人都明白我在讲什么.
书上对程序的验证也就是分这两步的.
关于归纳法,我再提一点,数学归纳法分两种分别叫一型和二型(好ugly的名字),
高中时学的归纳法都属于一型,第二步时假设N-1时情况成立,证明一下N的情况也成立.
而二型归纳法,第二步时假设m我不能确定大学数学是否讲到过二型归纳法.
另外归纳法的根基是自然数集的性质.所以也不是万能的,好在几乎所有迭代都不会超出这个范围.
如果真的碰到那么复杂的,我想就不要死盯着那里了.这种复杂情况基本上来自于某个复杂的算法.
它的正确性,或者算法存在的时候已经有证明了,
或者还是未决问题就留给数学家做吧.
关于写程序的过程,我建议先写预期函数,在写和预期函数匹配的代码,而不是倒过来.
当然对已有的代码采用净室方法的情况另当别论.
说到这里净室工程的核心好像讲完了,我看书的时候也这么以为,不过其实书的一半都没看完.
净室工程的方法是要贯穿整个软件制造过程的,编码只是第一步.
验证过程的回顾,要求一段代码要几个人一起验证他的正确性,这断代码被验证后,
他的质量就由这几个人共同负责,而不只是写代码的人,
点像代码走读.多人一起验证错误更少拉,而一个人往往会在验证时犯和编码时同样的错误.
所以这是保证代码质量至关重要的一步.(也是作者建议此书是最好和同伴一起学习的原因,:(可惜偶没找到.)
此后这本书又讨论了定迭代,抽象数据类型面向对象,递归和函数语言等的验证,有了前面的基础这部分很容易理解.
本以为这本书会以这种平淡的方式结束,第10章 "测试" 却令我有了惊奇的发现.
测试的角色:净室中的测试起到对净室过程进行评价的作用,如果测试过程中每千行bug大于10个,
那么这个净室过程肯定没有被很好的执行了.
基于使用的测试:它不是结构化的测试,不是覆盖程序的执行流程,
而是以和实际执行情况类似的概率对可能的输入进行抽样,加以测试.
按作者的观点这最有利于提高MTTF(mean time to failure 平均故障时间),
还给评价软件质量提供了可靠的依据.
的确是不错的方法,因为F*只要在D(F)上等于F就行了,定向测试是否有很多是多余的呢?
当然有改进软件质量的方法还是可以一用的,作者也认为,他一向反对在净室中使用的单元测试,必要的时候也可以动用.
另外里面关于测试数据生成器的描述很有意思,有空我要实现一下.
接着的增量开发也不错,不过和净室关系不大.
最后的展望讲到形式化方法,净室是形式化方法之一,而且是不太形式化的形式化方法.
还是那句话要适度应用方法,没有"银弹".
软件设计是没有最佳方法的,净室也有缺陷,但是通过我们综合运用各种方法,不断积累经验,
一切都在慢慢得改善.
另外我发现Python中可以应用净室工程是比较容易的,很大语句可以直接和预期函数对应,
这样代码中只要插入少数预期函数就可以清楚得表达意思了.
PS:写得重点不明,乱七八糟,所有只能算是读书笔记,参考价值不大.我的下一本净室工程的书是《从规范出发的程序设计》不知道有没有人和我一起学习?
下面搜了一些csdn上的朋友对净室的看法:
lizhli(小三) 信誉:100 2003-03-21 12:05:44Z 得分:5
静室软件工程,对每个地方都要用数学证明是正确的肯定很慢,它是用在高可靠性方面的.
问题是,如何保证你的证明是正确的,做数学题也会出错啊,如果不能保证证明过程是正确的又怎么能保证证明出来的结果,也就是程序是正确的?一直没想明白.
当然,证明的东西,现在人工智能已经能做一定程度了,用电脑证明应该可以比较正确,赫赫.
这位大哥的观点很典型.
"静室软件工程,对每个地方都要用数学证明是正确的肯定很慢"
要注意软件开发的时间(和成本)很大程度上是依赖于测试时间的,而净室虽然在编码时可能不快,但可以大大缩短测试时间.
净室软件工程比其它方法快多数,这不能肯定,有快1.5~5倍的,加速程度不够稳定.但有一点可以肯定他不会比其它方法慢.
"问题是,如何保证你的证明是正确的,做数学题也会出错啊"
至少用数学方法比不用数学方法准确得多吧,而且只要真正理解数学题一般是不会做错的.
(偶深有体会阿,偶们班怎么那么多人数学都考95分以上阿?)
"当然,证明的东西,现在人工智能已经能做一定程度了,用电脑证明应该可以比较正确,赫赫."
据我所知机器证明还没强到这种程度,数学家是找出各种证明来维持生计的,如果计算机真这么强,饭碗就保不住了(偶可不希望偶将来的饭碗没了.)
3gcdma ( ) 信誉:99 2003-03-21 13:00:03Z 得分:0
静室方法对实施人员的要求太高,不现实
净室方法的确需要培训人员,但绝对不会比学任何一门新技术更麻烦,我的感觉净室比UML简单多了(当然两者是完全不同范畴的东西).
gelenbertang 信誉:100 2003-03-21 17:32:41Z 得分:5
用自已现有的技术手段可以实现的去设计每一个可进的方案步聚,都设计完了,
检查一下工程图纸没有什么缺的,就照图施工这是不是静室软件呢?
我想是的话可以有这样的的结论,
静室工程对人的要求是把所有的可能的问题事先都想透了再动手,
技术是非关键因素,没有高级的技术一样可以做出好的软件来,
那怕只是用汇编,我个人认为多数人在工作一两年后就可以去做一些静室软件工程了,
当然是很小的工程而且是自已有经验的工程。
净室软件工程很省成本,但设计文档到谁手里能看懂是个问题,UML好像不是每个人都可以很清楚的。
如果产业化来个编程专业,设计专业,软件的分工更清楚,来之能战,战之能胜,倒是个不错的产业结构,
只可惜这行业变得太快了,不稳定的结构才合适现状,也苦了新人类了。唉~~~
"只可惜这行业变得太快了,不稳定的结构才合适现状,也苦了新人类了。唉~~~"
中国 软件 业的问题吧,好的东西永远都不会变,净室本来就不是什么新东西.
回复人: klbt(快乐白兔) ( ) 信誉:100 2003-11-09 01:53:52Z 得分:0
需要用到很多数学知识。
"需要用到很多数学知识。"
只要你有高中数学的水平就足以应付日常的验证了.
看看正面的评论:
quicmous(快鼠) ( ) 信誉:100 2003-03-22 22:31:03Z 得分:0
to GProgramer:净室的方法基于数学模型,保证了该方法的正确性。使用它并不需要程序员用数学方法进行论证。
to saucerman(外星人):呵呵,实用性沃也得验证一下才有发言权...。最近写的小控件如果不用这个方法可能早就写完了(可能包含不可预料的错误),嗬嗬,学习新东西总的有代价吧。
to lizhli(小三):我目前的理解是静室方法的数学模型保障了设计方案的完备性、一致性和正确性,不需要我们逐一论证。由于实际操作场景不可穷举,因此,设计方案只能建立在对输入场景合理抽象的基础上。而对程序的验证则靠数理统计在一定置信度内给予保障。
zhf_karen(zhf)可能是做ERP的,我也作此行。我觉得越来越需要在软件工程技术理论学些有使用价值的理论,不然的话真的会让工程给累死。
总之刚看几天书,体会有一点点,希望有经验的同行多指点。
说到我心里去了:)
smilemac() ( ) 信誉:100 2003-03-28 00:13:10Z 得分:0
其实比较普遍的看法是cr有价值的是它的盒子规约、控制迭带和统计测试的方法,很多人甚至认为只可以使用它的思想。它虽然诞生已有近20年,但使用即使在国外也很有限。实际我曾经在一个项目中吸取了它的基于使用模型的测试方法,取得了较为不错的效果。其实太简单的软件或可靠性要求不高的软件都不适合使用cr.试验恐怕得不到什么有意义的经验。而至于复用性要求,与cr没什么关系。而灵活性角度讲,cr是比较差的,比不上rup,因为纯粹的cr是不允许做refactoring的,它的规约是一级一级严格进行的。rup的设计开发过程是可以迭代的,而cr的迭代事实上是不同项目之间的迭代。是同一软件高版本对低版本的迭代(我在目前的项目中正吸取此思想以降低风险)。cr最困难的在第一个迭代中,而以后就好办了。