按合约设计与依赖巧合编程

任何程序库都有自己的一套使用方法,你只有严格遵守程序库设计者定义的规范下,才能‘随意’的使用他。

比如在STL中,除了Vector之外的大多数容器的Iterator都不能被存储,因为针对容器的很多操作都会导致Iterator失效,只有在每次使用Iterator时都从容器中重新获得才可以保证安全,否则“行为未定义”。(当然Iterator的使用也不至于如此死板,但这样的使用一定是最简单最合法的,如果法律规定写反革命文章要砍头,我不知道什么是反革命,可我知道什么是写文章,为了不被砍头于是我不写文章,前提是我并不是个作家)

又如在Java中,java.util.Vector类的add方法,add方法有一个两个参数的重载版本

    add(int index, E element);

可用来在容器的指定位置插入element,但是index的值必须在0到size()之间。

这就是一个规则,如果你打破规则,对于STL来说会发生“未定义的行为”,对Java来说会给你一个ArrayIndexOutOfBoundsExecption,如果你没有很好的处理,那么这依然是个未定义的行为。

所谓学习一个程序库的过程就是学会这个程序库所规定的规则。你学会的东西包括:
1. 按一定的顺序调用库中的某些函数。eg. SDL 中你必须 SDL_Init 先,最后还要 SDL_Destory.
2. 你调用函数时所传给的每个参数的意义及限制。eg. 上面java.util.Vector.add的index.
3. 调用函数所能产生的结果。

所有上面这些东西都不能通过程序(指接口)本身说明,只有文档(包括注释)可以。

任何一个程序库都必有自己的规则,或者说合约,一个库设计者和库使用者签订的合约。

不存在没有规则的程序库,或者说不存在没有合约的程序。

所以永远不要试图把你的程序库/类/函数/或者随便什么东西,设计成全能的,Vector的add方法就是不能接受index=-1,不必要非要让他接受。

对于Snow中的setActiveDocument方法,按合约设计时是这样的:

/**

 * @pre containsDocument(doc) == true

 * @post getActiveDocument() == doc

 */

void setActiveDocument(Document doc) {

    activeDocument_ = doc;

}


但是在实现时为了避免/提醒用户不要依赖巧合编程。我们应该实现成这样:

void setActiveDocument(Document doc) {

    assert(containsDocument(doc)) : "active document must in the document list";

    activeDocument_ = doc;

}


上面两者并不冲突,第一种程序是设计时存在于脑中的 Design Code,而第二种程序是编码时的 Implement Code.

除此之外还存在一种按合约编程,可以利用某种工具帮助我们直接将 Design Code 转变为 Implement Code,在这样的工具下我们只需要将 Design Code 写出即可。
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值