happyhippy

这个世界的问题在于聪明人充满疑惑,而傻子们坚信不疑。--罗素



1.
契约(Contract)就是规范和审核,就是在程序中包含断言,运行时核查这些断言。开发时,如果不希望因检测这些断言而使程序运行变慢,则可以打开或关闭契约检查,比如只在某些类中启用契约检测,而在其他的类禁用契约检查;或只检测先验条件(require),而不是包括先验条件、后验条件(ensure)和不变式(invariant)在内的全部检测。

 

2. 调用者有义务满足先验条件,并有权利要求被调用者保证后验条件为真。

 

3.契约式设计与继承:

3.1 重新定义契约:
 如果正在设计一个子类,并且要从某个父类继承一个特性,则可以在子类中重新定义继承自父类的特性:
(1) 作为重定义的一部分,可以修改被继承的特性的契约。
(2) 可以使用require else弱化先验条件。
(3) 可以使用ensure then强化后验条件。 

3.2 不变式与继承:
(1) 子类继承它的父类的不变式。
(2) 子类可以在不变式中增加子句,新增的子句and被继承的子句,从而强化了被继承的不变式。

  

4Design by Contract的几个优点:

4.1 获得更优秀的设计:

(1) 更系统的设计:契约式设计鼓励程序员思考诸如“例程的先验条件是什么”这样的问题,这样可以使概念更加明晰。

(2) 更清楚的设计:使用方和提供方之间的权利和义务得到了共享,同时获得了清晰的描述。

(3) 更简单的设计:程序的先验条件清楚地描述了使用该程序的限制,而且非法调用的结果也很清楚,所以DbC鼓励程序员不要开发过于通用的程序,而要设计小巧的、目标专一的程序。

(4) 控制对继承的使用:当要用到多态和动态绑定时,检查契约可以确保被重定义的程序的先验条件在子类中没有被加强;另外,契约和继承之间的密切关系能够使类设计者切实地认识到应该设计出能够为子类设计者所复用的类。

(5) 系统地应用异常:当程序被非法使用(不满足先验条件)或者程序没有遵循契约的规定(不满足后验条件或不变式)时,就会发生异常。因此,异常的使命就清晰了:它是代码中错误的信号和标志,而不是一种因人而异、随心所欲的控制转移机制。

 

4.2 改进可靠性:

(1) 理解更清楚,代码更可靠:如果按照两种不同的方式表达同一件事情,就能更好地理解它。编写契约时,我们必须用先验条件和后验条件来说明每个程序的任务;还必须通过程序体内的代码说明它是如何完成任务的。由于不得不按照两种方法思考程序,我们就能够更清楚地理解这个程序的任务和完成任务的方法。

(2) 测试更到位,代码更可靠:断言在运行时进行检测,从而确保程序符合它们既定的契约;契约可以随时关闭或启用,因此可以方便地重复测试程序中的各个部分。

 

4.3 得到更出色的文档:

(1) 更清晰的文档:契约是类特性的公开视图(或称为客户视图)中的固有成分。

(2) 更可靠的文档:运行时要检查断言,以便保证制定的契约与实际运行情况一致。

(3) 明确的测试指导:断言定义了测试的预期结果,并且又代码进行维护。

(4) 支持精确规范:契约提供了一种方法,既能够获得精确规法所带来的益处,同时还使得我们继续以我们所熟悉的方式来工作。

 

4.4 简化调试:

(1) 开发期间的支持:由于断言判断为假而在运行时展现出来的错误将被精确得定位。

(2) 维护期间的支持:如果发布程序时打开了断言检查,客户就可以为开发人员提供更确切的错误信息。

 

4.5 支持复用:

(1) 库使用者手中的优秀文档:契约清楚地解释了程序库中的各个类、各个例程的任务,以及使用中的限制条件,从而减轻了“此功能尚未实现”综合症的危害车程度。

(2) 对库使用者的帮助:运行时的契约检查为那些学习使用别人的类的人们提供了反馈。精心编写的契约,尤其是精心编写的先验条件,为客户程序员提供了出错位置的精确分析。

  

 

5.契约的一些开销和限制:

        设计具有良好契约的程序需要一定的开销:撰写契约需要时间,开发者需要时间去学习撰写良好契约所应该掌握的思想和技术,况且,并不是每个软件都需要那么高的质量。目前的主流开发语言中,只有EiffelJavaC++支持契约,而且仅仅支持顺序时程序(Sequential program)的契约。

 


posted on 2006-12-18 07:12  Silent Void  阅读(749)  评论(0编辑  收藏  举报