李卫公的长安城

过上一万年,那城就会变成黑色,永远不倒……

  DonewsBlog  |  Donews首页  |  Donews社区  |  Donews邮箱  |  我的首页  |  联系作者  |  聚合   |  登录
  373篇文章 :: 38篇收藏:: 393篇评论:: 5个Trackbacks

公告




版权声明:本 blog 上所有原创文章、图片,未有特别声明者,均遵守 Common Public License。所有翻译、转载文章和图片,版权归属原作者所有,遵守原作者声明。

warning


给我写信

文章

收藏

相册

Focus

Friend's blog

Miscellaneous

My Favourite Blogs

存档


正在读取评论……


朋友问这样的问题:
写了一个函数,从网页源代码中抽取一个结点的文本,函数本身没有问题,但同事在code review时指出,如果提取不成功,应该返回None,而不是空字符串""。

提问的朋友跟我说:你之前说过,从数据库里取出一批数据,如果不存在,要返回一个空的Collection,而不是None(这样才能正确表示“需要的数据不存在”),那么这里,是否应该听取同事的意见呢?
当时我的回答是,因为从这个函数接受数据的代码期望获得的是一个字符串,所以,如果提取不成功,应该返回""。
但是,这样,就无法区分下面两种情况了:存在这个结点,但是一个空结点;不存在这个结点。

这几天晚上一直在思考这个问题,并与Patrick讨论,最后的结论是:
之所以会出现这个问题,原因在于函数的定义是不明确的——虽然函数名看来很清楚,但它的意义是不确定的。
按照契约式设计(Design by Contract)的原则,每个模块都应该有前驱条件(pre-condition)和后继条件(post-condition)。正是因为两位开发人员对这一点的认识存在分歧,问题才会出现:
  • 如果这个函数的前驱条件是,必须提供一段包含此结点的源代码(也就是说,这个结点必须存在),就不能返回None,返回"",就表示这个结点内容为空,如果提供的源代码不包含这个结点,应抛出异常;
  • 如果前驱条件是,提供的源代码不必包含这个结点,那么,这个函数其实就履行了两项职责——检查是否存在结点,以及提取结点的文本,必须与调用方有一个约定,来表示这两重含义(此时可以用None表示“不存在结点”的情况,用""表示结点内容为空的情况,当然我不推荐这么做)。
同样,按照契约式设计的原则,数据验证的职责在调用方,也就是说,约定了这个函数的前驱和后继条件之后,调用方在调用之前,必须保证前驱条件:如果函数要求源代码必须包含这个结点,那么验证是否存在的职责就应该由调用方来承担。

Trackback: http://tb.donews.net/TrackBack.aspx?PostId=1201383


[点击此处收藏本文]  发表于2007年08月21日 4:42 PM




正在读取评论……

发表评论

大名:
网址:
验证码
评论