契约思想的一个反面案例

原创 2003年01月17日 12:56:00

刚刚发表了《什么是契约》一文,突然发现自己通篇都在写理论,没有实例来证明。所以赶快补充一个反面案例——C++ IOStream。说是反面,不是因为IOStream库设计得不精彩(恰恰相反,你很难找到比IOStream设计更为精彩的C++库了),而是想展示一下,在没有契约概念的思想体系里,组件设计将为权责不清的错误处理付出多大的代价。

大家知道,C++ IOStream库非常经典,最先起源于Bjarne Stroustrup的Stream库,之后经过Jerry Schwartz、Martin Carroll、Andy Koenig等人的改进,成为IOStream库,并被并入Bell实验室发行的USD C++库中,广为传播。后来USD库逐渐消亡了,而IOStream由于获得广泛应用,得以幸免,并以新的形式被置于标准库中。

对于错误处理,当IOStream库诞生的时候(大约1985-1987),C++还没有异常机制。因此,Jerry Schwartz发明了这样一套错误处理机制:

例1:经典的IOStream错误处理:

  ifstream ifs("filename.txt", ios::in);
  if (!ifs) {  // 这里实施了向void*转型的操作
    // 文件打开失败,实施错误处理
  }

先测试文件是否打开,再实施具体操作,这是经典IOStream库的一个惯用法(idiom)。

我们现在设想用户没有很好地执行这个idiom:

  int val;
  ifstream ifs("filename.txt", ios::in);
  ifs >> val; 

如果filename.txt打开失败,会发生什么情况?

如果哪位还有当年的Borland C++ 3.1,可以试着测试一下。我估计是什么也不发生,或者说,程序处于极端危险的“undefined behavior”状态。

这种情况对C++库开发者来说是不能接受的。因此,尽管问题的出现是由于用户的错误(他们没有正确地测试流状态),但是由于非契约思想体系下的权责不清,IOStream库的开发者开始追求足以应对用户错误的组件开发技术。由此,IOStream开始在一个方向上被拖入了复杂性的泥潭之中。

我们看看标准库中的对付这种情况采用什么办法。标准IOStream有一个成员函数叫做exceptions(),专门用来帮助程序员切换异常模式。缺省情况下,异常触发并没有打开,所以情形跟经典IOStream库相同。如果你在操作IOStream之前如下调用:

strm.exceptions(std::ios::eofbit | std::ios::failbit |
                std::ios::badbit);
则当流不处于good状态时,执行类似 strm >> val;这样的操作时,将会抛出异常。

这样做看起来不错,是吗?

我觉得不是。请恕我C++标准的异议,这是我第一次正式对C++标准中的设计提出异议。

这种设计带来的缺点,首先是复杂。在Nicolai Josuttis的The C++ Standard Library中,对这个机制整整用了5页纸来解释,还意犹未尽。复杂的设计必然带来复杂的使用规则,而面对复杂的使用规则,用户是可以投票的,那就是你做你的,我不用!读这篇帖子的人,谁在实际项目中使用过exceptions()?事实上,我个人是害怕exception甚于害怕undefined behavior。

而对于用户来说,你可以不用,却不得不为对它付出运行性能和空间的代价。诸位有兴趣,不妨追踪一个IOStream功能的实现,看看为了支持这个异常,IOStream库的设计这耗费了多大的心力,而你的CPU又为此耗费了多少clock。

缺点之二,是异常本身的问题——即使你抓到了异常,又当如何?程序可能已经完全离开了发生异常时的执行环境,也许你连异常为什么发生都搞不清楚,谈何处理?也无非就是通知用户一声:“我完了,因为一个异常发生在XXXXXXXX处,你要报告的话给我发Email吧。” 是啊,你还能做什么呢?

我们试着用契约观点来分析这一状况,如果说“先测试,再使用”在传统上是一个idiom,那么在contract思想里上升为一个契约。对于C++来说,应该将“流处于good状态”作为一个契约,在每一个成员函数里进行检查。甚至你还可以设置一个调试期标志,专门用来核查用户是否检查过流状态。在必要的操作进行之前,你可以先用断言检查用户是否检查过流状态,满足了契约。这样一来,在契约之下,用户将被迫以正确的方式使用组件,从而大幅度简化组件开发的复杂度。

再来考虑异常。如果真正发生了异常,在Eiffel中提供了retry机制。Bjarne Stroustrup说过,retry可以做到,但是往往没有意义。为什么没有意义呢?因为C++中没有契约的思想,异常的产生可能根本就是程序员的bug。在这种情况下,无论retry多少次,结果都是一样的糟。可是在Eiffel里情形不同。如果各方面对于契约都做到很好的遵循,那么真正发生异常的时候,我们大可以比较有把握的说,这可能是一个很偶然的事件导致的。比如说网络环境下,另一个用户在那一瞬间突然对文件实施了一个操作,或者硬件的一次偶然异常。对于这种情况,“再试一次”成了合情合理的选择。我们很可能将异常扼杀在摇篮之中,从而不给上层模块带来任何影响。

谁说契约思想不伟大呢?

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

WCF契约之---服务契约 、数据契约、 消息契约

服务契约 描述了暴露给外部的类型(接口或类)、服务所支持的操作、使用的消息交换模式和消息的格式。每个WCF服务必须实现至少一个服务契约。使用服务契约必须要引用命名空间System.ServiceMod...
  • Percy__Lee
  • Percy__Lee
  • 2015年09月17日 13:59
  • 1396

【分享】肉体契约書 汉化硬盘版+汉化1.1补丁,日语1.0和1.1补丁(带镜像版)

游戏名称:肉体契约书 开发商:FULLTIME 发售日期:2011-12-22 TAG:ADV 3D 调教 过激。 汉化硬盘版加上反和谐补丁和日语原版1.0和1.1补丁。. 游戏介绍 就业形势...
  • wangzi867258173
  • wangzi867258173
  • 2014年07月07日 18:35
  • 11570

WebService——通过契约优先开发webservice

一、基本概念 有代码优先和契约优先两种开发webService的方式,本例介绍契约优先的webService。 编写WSDL有三种方式:基于document的Wrapper方式,基于document的...
  • woshixuye
  • woshixuye
  • 2013年11月04日 07:18
  • 3248

推荐系统之反面案例

原文发表在 http://phunters.lofter.com/post/86d56_8afcd0 推荐系统是近几年来机器学习和大数据在商业化上的重要应用。依靠展示“买了这个东西的用户还喜欢买...
  • wyg7839303
  • wyg7839303
  • 2015年03月21日 19:00
  • 302

关于《Java编程思想》注解篇的一个案例所遇到的疑惑-apt参数的问题

案例为提取接口的案例,里面有一条命令 apt -factory
  • lixin84915
  • lixin84915
  • 2014年09月26日 16:38
  • 645

分享成功程序员的多了,我写个反面的教材---一个高龄菜鸟程序员的工作经历

首先,解释一下我高龄菜鸟的定义,我呢做软件开发已经六年多七年头了,目前来说在就业市场上依然还没有什么竞争力,为什么会这样呢,自己总结一下吧。     我专业是计算机科学与技术,因为我是从一个乡镇出来...
  • cargod
  • cargod
  • 2012年05月27日 00:32
  • 13776

一个ZFC的新的模型并论及GCH的反面

一个ZFC的新的模型并论及GCH的反面     杨安洲(北京工业大学数学系,E-mail :yanganzhou1938@sina.cn)                ...
  • zzwu
  • zzwu
  • 2015年10月20日 08:39
  • 533

wcf之二(接口契约式编程思想)

wcf接口契约式编程思想
  • jielizhao
  • jielizhao
  • 2015年01月26日 10:37
  • 737

新手必看WCF集合契约等价案例分析

这里就WCF集合契约等价的几个规定做出了详细的介绍,相同类型的列表集合被认为具有相同的数据契约(协定)  关于WCF集合契约等价,在WCF中应用了CollectionDataContractAttri...
  • ysf871104
  • ysf871104
  • 2011年01月20日 17:33
  • 505

杀手的契约: 我的故事(一个曾经的士兵)

1995年,16岁,被老爸强行应征入伍(当时还真没想过去当兵)就这样,到了云南,做了一名小小的士兵,新兵生涯很辛苦,想家,想妈妈,最受不了就是部队的伙食,而且还受老兵的欺负,慢慢的,新兵变成老兵,开始...
  • q93161
  • q93161
  • 2012年10月11日 15:59
  • 15457
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:契约思想的一个反面案例
举报原因:
原因补充:

(最多只允许输入30个字)