`
zuzong
  • 浏览: 115201 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

软件设计原则——Design by Contract(契约式设计)

阅读更多
个人心得,权作讨论,切勿当真 

Design by Contract(契约式设计),以下简称DbC,字面意义来看,包含两个内容“责任”与“义务”,是对交易或互动中,两方之间关系的约束。换用软件行话来说,表示调用方与被调用方的,参数和返回值的Assert处理。

Assert有三个,前提条件、后续条件、和不变式,前两个针对方法,而最后一个针对整个类,“前提条件”指完成function需要的参数必须为真,“后续条件”指function的结果必须为真,“不变式”指class必须为真。那在代码中如何体现呢。。。

1、前提条件,谁来做“真”验证?调用方还是被调用方?有个很简单的例子,在超时买完东西付费,你总得给钱吧,所以调用方需要做非空验证。至于给多给少那是收银员需要判断的事了,所以具体的逻辑验证自然由被调用方来处理。很多新人都习惯于在action中做“前提条件”的处理,且不论后方的service方法可能变化,就action的来源来说,如果有PC浏览器请求,手机浏览器请求,手机客户端Http请求,远程调用方请求,那该如何处理,都cp一份“前提条件”处理代码吗?要是这时service方法变了。。。嘿嘿,杯具了。
当然,到了service内部,logic和operation之间就不需要验了,因为这里已经远离输入端,且有“后续条件”的保证。

2、后续条件,保证执行结果是调用方所期望的,那错误的结果如何处理呢?如果是在service内部,则抛异常就是了。而在action和service之间,比较好的做法是看这个错误能否被请求方(用户)处理,若可以(如输入错误),则返回一个错误信息,由action发下去;若不可(如sql错误、通信通道错误),则捕获这个异常,编写异常信息,再包装成运行时异常继续往上抛,交由系统的统一异常处理方法,到时处理方法可以是错误页面展现,也可以是给一个约定的格式下去

3、不变式,个人理解,就是看这个类的hashcode。

若涉及到了继承,子类和父类,则需要遵守一个原则,即子类方法的前提条件不强于基类,后续条件不弱于基类。此处实际是遵守了LSP 里氏替换原则(Liskov substitution principle)


相关书籍
《UML Distilled: A Brief Guide to the Standard Object Modeling Language (3rd Edition) 》此书有中文版
《Design by Contract by Example》(Design by Contract原则与实践)
作者列出了DbC的六条原则和六条准则:
六原则:
1、区分命令和查询
    查询返回一个结果,但不改变对象的可见性质。命令改变对象的状态,但不返回结果。

2、将基本查询同派生查询区分开
    派生查询可以用基本查询来定义。

3、针对每个派生查询,设定一个后验条件,使用一个或多个基本查询的结果来定义它
    这样一来,只要我们知道基本查询的值,也就能知道派生查询的值。

4、对于每个命令都撰写一个后验条件,以规定每个基本查询的值
    结合“用基本查询定义派生查询”的原则(原则3),我们现在已经能够知道每个命令的全部可视效果。

5、对于每个查询和命令,采用一个合适的先验条件
    先验条件限定了客户调用查询和命令的时机。

6、撰写不变式来定义对象的恒定特性
    类是某种抽象的体现,应当将注意力集中在最重要的属性上,以建立关于类抽象的正确概念模型。

六准则:
1、在适当的地方添加物理限制
    尤其是那些需要限制变量不应该为void的地方。

2、先验条件中尽可能使用高效的查询
    如果有必要,可以增加高效的派生查询,并在其后验条件中确保其与较低效的基本查询之间的等价关系。

3、用不变式限定属性
    如果一个派生查询被实现为一个属性,则应通过类中不变式的断言保证它与其他查询保持一致。在一个类的开发过程中,通常应该先把断言检测的级别设为最高级,使先验条件、后验条件和不变式都得到检测;一旦通过了检测和测试,一般就可以降低断言检测的级别,只检测先验条件,以提过代码的运行效率。

4、为了支持特性的重定义,用相应的先验条件确保每个后验条件
    这样就允许在子类开发过程中进行各种不可预见的重定义。

5、将预期发生的变化和框定规则这两种不同的限制分别放置在不同的类中
    这使开发者在扩展已有类时享有更多的自由。

6、若有保密性要求,则违背保密性的查询只能被设为私有熟悉在契约中使用
    这里的“设为私有”,是对“在契约中使用了该查询的类”之下的层次而言,至于类之上的层次,这个查询当然是可以使用的。
1
7
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics