Posted on 2006-03-02 00:55
shaofan 阅读(2053)
评论(4) 编辑 收藏 所属分类:
软件工程 、
Java
Design by Contract (DbC)的概念已经出现很长时间了,最先是在Eiffel的一个特色,通过DbC来提高软件质量,目前很多语言也都有相应的实现,但是在GOOGLE上搜索中文网页,得到的资源并不是很多.直觉上来说,DbC确实是一个很好的想法,本着拓宽眼界的原则,就简单了解一下吧.
简单的说,DbC通过指定每个方法的前置条件,后置条件来保证代码质量.也就是说,它的假设前提是:"任何一个方法,给予其满足条件的输入,应当得到一定的输出".对于一个方法来说,如果"参数"可看作其输入,返回值可看作输出.那么调用这个方法的人有责任保证给予正确的参数,而当正确的参数给予后,该方法本身有责任给出正确的输出.如果出现错误,那么是调用者的问题,还是被调用者的问题,可以根据前面所说的方法来确认.
在实际使用中,DbC可以用来更方便的找出错误,确定责任.
拿DbC的一个实现, iContract作例子.比如说,有一方法 foo(int a, int b).它要求输入的a,b都要大于零.如果提供的参数满足这个条件,那么它应保证输出大于0.用iContract来表示,是这样的:
1 /**
2 *@pre a>0
3 *@pre b>0
4 *@post @return>0
5 */
6 int foo( int a, int b ){
7 //其他代码
8 }
另一个方法调用foo:
1 public void run(){
2 int result = foo( 0, -1 ); //注意-1不满足条件@pre b>0
3 }
没有DbC的情况下,-1的输入可能导致foo内部产生异常,比如说NullPointerException之类的.当我们看到这样的异常时,一般来说无法确定是foo方法本身的bug还是其他原因造成的,可能需要跟踪进去看看才知道.
如果我们用DbC,将这段代码用一个iContract编译工具(这里也就是iContract)编译后(ant提供支持),可以像一般的程序一样执行.当运行到run方法中时,由于调用时给予的参数不满足前置条件,也会产生一个运行时异常,但是区别是,异常产生于方法刚被调用前,因此阻止了错误的继续,并指明了错误是"调用程序run违反了add方法的前置条件",对程序员来说更加直观.显然用这种方式,确定责任更加迅速明确.使用DbC的原因就是,责任明晰,到底是给予的参数有问题,还是程序本身有问题,更容易查找了.契约式设计的精神就体现在于此.
DbC在java上的实现中,iContract比较有名,但是其开发公司似乎人间蒸发了?ant从1.4后也提供对它的支持,但似乎很难找到它的下载,更不用说后续开发和支持了.javaworld上有对其介绍的
文章.如果你想了解DbC,这篇文章也是很好的入门材料.
不过后来在
wikipedia上找到了DbC的另一种实现:
JML,全称Java Modeling Language,名字挺吓人的样子.主要由一些大学联合开发,很热闹,资源也相当丰富.其主页是
这里.JML不只实现了DbC,还有其他的一些东西,还没仔细看.
这篇pdf是一个很好的介绍JML的材料.
此外还有一些书,都可以在Google上找到.总体来说,DbC的学习语法相对简单,学习成本还是比较低的.有兴趣的话不妨一式.