-
2009-08-17
《程序员修炼之道》 第四章 注重实效的偏执 - [新知随笔]
版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://liuyangsl.blogbus.com/logs/44384632.html
不可能写出完美的软件,因此程序员应该针对自己的错误进行防卫性编码。
1. 按合约设计
坦率是交流过程中最好的解决办法,用合约规定双方的权力和义务。
按合约设计(DBC):
用文档记载并约定软件模块的权力与责任,确保程序的正确。
一个程序业务例程的约定包括以下方面:
<a> 前提条件:执行例程之前必须满足的条件。
<b> 后条件:例程完成后,世界的状态。
<c> 不变项:在例程执行前后,保持不变的事物。
合约中应该保持“羞怯”,尽量缩小输入和输出的数量以及范围。
对父类规定了合约之后,继承父类的子类可以有自己的合约,但至少要遵循父类的合约。
这样用户在使用子类的时候,才能感到它是父类的一种。
使用DBC的好处是,它明确了需求和约束,让程序员知道应该是什么样子,不允许是什么样子。
一些编程语言具有内置DBC支持,这样就可以用“断言”让编辑器帮助检查合约。
但是断言不能被继承,runtime系统和库的设计也不支持合约。
<a> Eiffel 和 Sather 可以自动在编译器和runtime系统中检查前提条件和后条件。
<b> C 和 C++ 可以使用Nana,用调试器在运行时监控断言。
<c> Java 可以使用 iContract ,读取注释,生成包含断言逻辑的源文件。
但是像<b><c>两种预处理实现断言的方式,可能会使项目集成变得杂乱。
断言的判断,是在调用者调用例程之后,进入例程之前,在后台进行测试的,这样就可以在出现问题之前,阻止例程的错误运行。
不变项的用法:
<a> 循环不变项:循环中经常出现计数错误,用循环不变项来确定循环的最终目标,并且每次循环都应符合这个目标。
<b> 语义不变项:定义一种在任何情况下都不可违反的需求。注意那些反复变化的政策性约定不属于语义不变项。
----------------------------------------------------------------------------------
2. 死程序不说慌
尽早地检测问题,尽早地让程序崩溃。
例如在Java中,一个runtime中的异常发生时,RuntimeExcepton如果没有被捕捉,将渗透到程序的顶部,并留下痕迹。
当程序中发现有不应发生的事情发生之后,程序应该尽早地报警崩溃,因为如果没有及时报告,这个异常的后果可能会在之后引发“不可能的错误”。
----------------------------------------------------------------------------------
3. 断言式编程
在编码的过程中,不要坚信某些事情是不可能发生的,就不去处理。应该用断言来确保这些事情不会发生。
例如在C++中,用于判断布尔的assert宏:
void writeString(char *string){
assert(string != NULL);
...
}
注意在编译时,断言可能不会被执行,因此不要把必须执行的代码写在断言中。
断言只是一种异常情况的预防,不要用断言代替异常处理代码。
应该让断言失败,抛出异常,以便在某处做资源的释放等处理。
虽然断言是在检查那些“绝不会发生”的事情,但是在软件经过了测试并发布之后,断言也应该开着。
注意不要在使用断言时,引发新的危险代码。
----------------------------------------------------------------------------------
4. 何时使用异常
引入断言的一个副作用是,当需要进行断言的事物太多,很容易让代码变得丑陋。
这就需要使用异常处理,可以对一整段内容进行异常处理,替代多个断言,使代码简洁。
----------------------------------------------------------------------------------
5. 怎样配平资源
对于资源,要有始有终。
分配资源的例程要负责结束该资源。
按照分配资源顺序相反的顺序来结束资源。
在代码的不同地方分配一组资源时,总是用相同的顺序来分配它们。
配平资源的方法在不同程序语言中有所不同。
当一个资源生成后,如果有多个途径来释放(比如可以在正常流程后释放,也可以在异常捕获后释放),可能会在维护时带来问题。
当一个子结构创建的资源从属于一个顶层结构时,在配平时有以下选择:
<a> 顶层结构负责释放包含的子结构。
<b> 只解除顶层结构的分配。
<c> 如果包含子结构,拒绝解除自身的分配。
检查配平:
为资源编写包装,用包装检查资源的状态,比如在包装里加入计数器。随机文章:
《程序员修炼之道》 第八章 注重实效的项目 2009-08-19《程序员修炼之道》 第七章 在项目开始之前 2009-08-19《程序员修炼之道》 第六章 当你编码时 2009-08-19《程序员修炼之道》 第五章 弯曲或折断 2009-08-18《程序员修炼之道》 第三章 基本工具 2009-08-14
收藏到:Del.icio.us







