软件构造:3-2 Designing Specification

Designing Specification

行为等价性

站在客户端视角看行为等价性:根据规约判断行为是否等价

规约结构:前置条件和后置条件

前置条件:对客户端的约束,在使用方法时必须满足的条件;
后置条件:对开发者的约束,方法结束时必须满足的条件;
契约:如果前置条件满足了,后置条件必须满足

前置条件不满足,则方法可以做任何事情

前置条件在@param中定义 后置条件在@return 和 @throws,但是在规范中,前置条件和后置条件的部分可能在@param和@return子句之外的地方找到,因此仔细阅读非常重要。

除非在后置条件里声明过,否则方法内部不应该改变参数。
应尽量遵循此规则,尽量不设计mutating的spec,否则就容易引发bugs。

测试以及验证规约

黑盒测试:测试在不了解实现情况的方式下遵照规约进行测试,测试情况不应当遵照任何具体的实现行为;
白盒测试:

设计规约

(1) 规约的分类
spec变强 = 前置条件更弱+后置条件更强

确定的规约:给定一个满足precondition的输入,其输出是唯一的、明确的
欠定的规约:同一个输入可以有多个输出
非确定的规约:同一个输入,多次执行时得到的输出可能不同

操作式规约:例如伪代码
声明式规约:没有内部实现的描述,只有“初-终”状态
声明式规约更有价值
操作式规约存在地位置:不要放在spec中,放在代码实现体内部注释里呈现。

(2) 图表规约

软件构造:3-2 Designing Specification_第1张图片

(3)设计好的规约
(1) 规约应当是内聚的
规约描述的功能应当单一,简单,易理解
(2)调用的结果应当是信息丰富的
不能让客户端产生理解的歧义
(3)规约应当强弱得当
太弱的spec:可能会遇到很多不同的特殊情况
太强的spec:很多特殊情况难以达到
(4)规约应当使用抽象类型
在规约里使用抽象类型,可以给方法的实现体与客户端更大的自由度
(5)检测前置后置条件
客户端不喜欢太强的precondition,不满足precondition的输入会导致失败。
惯用做法是:不限定太强的precondition,而是在postcondition中抛出异常:输入不合法
是否使用前置条件取决于(1)check的代价; (2)方法的使用范围
如果只在类的内部使用该方法(private),那么可以不使用前置条件,在使用该方法的各个位置进行check——责任交给内部client;
如果在其他地方使用该方法(public),那么必须要使用前置条件,若client端不满足则方法抛出异常。

你可能感兴趣的:(软件构造)