21.按合约设计

日常中,人与人打交道存在权利与责任,以及信任的问题,这些问题会让人与人之间的交往变得困难,那么为了解决这些困扰,在人与人打交道时会用合约的方式来明确下双方的权利责任。

DBC

软件设计中为了确保软件模块的权利与责任,以确保程序的正确性,也引入了合约的概念,这就是DBC(Design By Contract)按合约设计。

什么是正确的程序?程序只做它声明中要做的事情,不多做也不少做。

DBC的方式:用文档记载并约定软件模块的权利和责任,以确保程序正确性。用文档记载这样的声明,并进行校验,是按合约设计(DBC)的核心所在。

DBC的流程:

     1.前条件:为了调用例程,必须为真的条件

     2.后条件:例程保证会做的事情

     3.类不变项:类确保从调用者的视角来看,该条件总是为真

*如果调用者满足了例程的所有前条件,例程应该保证在其完成时,所有后条件和不变项将为真。

(java中的DBC工具是iContract,书中的例子代码是以iContract写的)

对在开始之前接受的东西要严格,而允诺返回的东西要尽可能少。记住,如果你的合约表明你将接受任何东西,并允诺返回整个世界,那你就有大量代码要写了!

面向对象的继承和多态是合约发挥作用的领域之一。

实现DBC

   1.断言

    支持断言式编程的语言可以通过断言部分实现DBC。

    为什么是部分实现?因为:

      首先,断言不支持继承层次向下遗传

      其次,断言不支持“老”值。(什么是“老”值?)

      最后,runtime和库的设计不支持合约(什么意思?)

  2.语言支持

    有些语言内建对DBC的支持(Eiffel和Sather)

    C,C++的有些预处理器能处理作为特殊注释嵌入在代码中的DBC。预处理器可以把这些注释展开为断言代码(Nana)

    Java可以使用iContract

DBC与早崩溃

  谁负责检查前条件,调用者?还是被调用的例程?如果是作为语言的一部分实现的,答案是两者都不是。前条件是在调用者调用例程之后,但在进入例程之前,在幕后测试的。因而如果要对参数进行任何显式的检查,就必须由调用者来完成。因为例程永远也不会看到违反了前条件的参数。

  通过早崩溃、在问题现场找到和诊断问题要容易的多。

不变项的其他用法

  1.循环不变项

    循环不变项是对循环最终目标的描述,有时在复杂的循环上设置正确的边界条件会很成问题。循环常有的“香蕉”问题、“篱笆桩”问题、“差一个”问题。这样在循环每次执行前以及迭代时它都是有效的。

  2.语义不变项

    语义不变项描述的是一种不可违法的需求。固定的需求或不可违反的法则,和一些需求中细化出的政策是要加以区分的。细化的政策是可以动态的变化的。而需求中的一些基本定义是不变的。那么用语义不变项去清晰、简介的定义出那些政策无论怎么变化都不会改变的基本法则。

动态合约与代理

  在“自治代理”的领域中。按照自治的定义,代理有权拒绝它们不想接受的请求。“能够互相磋商合约,以实现某个目标”的组件和代理是解决软件生产率危机的方法。

原文地址:https://www.cnblogs.com/mysic/p/5766198.html