Design by Contract (DbC) – 契约式设计

  DbC的核心思想是对软件系统中的元素之间相互合作以及“责任”与“义务”的比喻。这种比喻从商业活动中“客户”与“供应商”达成“契约”而得来。例如:

  供应商必须提供某种产品(责任),并且他有权期望客户已经付款(权利)。

  客户必须付款(责任),并且有权得到产品(权利)。

  契约双方必须履行那些对所有契约都有效的责任,如法律和规定等。

  同样的,如果在程序设计中一个模块提供了某种功能,那么它要:

  期望所有调用它的客户模块都保证一定的进入条件:这是模块的先验条件(客户的义务和供应商的权利,这样它不用去处理不满足先验条件的情况)。

  保证退出时给出特定的属性:这是模块的后验条件——(供应商的义务,显然也是客户的权利)。

  在进入时假定,并在退出时保持一些特定的属性:不变式。

  契约是这些权利和义务的正式形式。我们可以用“三个问题”来总结DbC,并且作为设计者要经常问:

  它期望的是什么?

  它要保证的是什么?

  它要保持的是什么?

  根据Bertrand Meyer氏提出的DBC概念的描述,对于类的一个方法,都有一个前提条件以及一个后续条件,前提条件说明方法接受什么样的参数数据等,只有前提条件得到满足时,这个方法才能被调用;同时后续条件用来说明这个方法完成时的状态,如果一个方法的执行会导致这个方法的后续条件不成立,那么这个方法也不应该正常返回。

  现在把前提条件以及后续条件应用到继承子类中,子类方法应该满足:

  1.前提条件不强于基类.

  2.后续条件不弱于基类.

  换句话说,通过基类的接口调用一个对象时,用户只知道基类前提条件以及后续条件。因此继承类不得要求用户提供比基类方法要求的更强的前提条件,亦即,继承类方法必须接受任何基类方法能接受的任何条件(参数)。同样,继承类必须顺从基类的所有后续条件,亦即,继承类方法的行为和输出不得违反由基类建立起来的任何约束,不能让用户对继承类方法的输出感到困惑。

  这样,我们有了基于契约的LSP,基于契约的LSP是LSP的一种强化。

  参考:http://en.wikipedia.org/wiki/Design_by_contract

  Acyclic Dependencies Principle (ADP) – 无环依赖原则

  包之间的依赖结构必须是一个直接的无环图形,也是说,在依赖结构中不允许出现环(循环依赖)。如果包的依赖形成了环状结构,怎么样打破这种循环依赖呢?有2种方法可以打破这种循环依赖关系:第一种方法是创建新的包,如果A、B、C形成环路依赖,那么把这些共同类抽出来放在一个新的包D里。这样把C依赖A变成了C依赖D以及A依赖D,从而打破了循环依赖关系。第二种方法是使用DIP(依赖倒置原则)和ISP(接口分隔原则)设计原则。

  无环依赖原则(ADP)为我们解决包之间的关系耦合问题。在设计模块时,不能有循环依赖。