Designing Specification
设计规约
Objective of this lecture
§ Understand preconditions and postconditions in method specifications, and be able to write correct specifications (方法的规约)
§ What preconditions and postconditions are, and what they mean for the implementor and the client of a method (前置/后置条件)
§ Understand underdetermined specs, and be able to identify and assess nondeterminism (欠定规约、非确定规约)
§ Understand declarative vs. operational specs, and be able to write declarative specs (陈述式、操作式规约)
§ Understand strength of preconditions, postconditions, and specs;and be able to compare spec strength (规约的强度及其比较)
§ Be able to write coherent, useful specifications of appropriatestrength (如何写出好的规约)
1.Functions & methods in programming languages
·参数类型是否匹配,在静态类型检查阶段完成
·返回值类型是否匹配,也在静态类型检查阶段完成
·“方法”是程序的“积木”,可以被独立开发、测试、复用;使用“方法”的客户端,无需了解方法内部具体如何工作—“抽象”
·示例:
2.Specification: Programming for communication
(1) Documenting in programming
变量的数据类型定义
final关键字定义了设计决策:“不可改变”
代码中蕴含的“设计决策”:给编译器读
注释形式的“设计决策”:给自己和别人读
(2) Specification and Contract (of a method)
没规约,没法写程序;即使写出来也不知道对错
规约使程序与客户端之间达成一致
Spec给“供需双方”都确定了责任,在调用的时候双方都要遵守
An example of specification:
输入输出的数据类型;功能和正确性;性能
(3) Behavioral equivalence行为等价性
要站在客户端的视角看行为等价性
可以根据规约判断是否行为等价
Exercise:
解答:是行为等价的。用户只关心存在i使val在数组中有数对应,或者是返回一个与数组下标无效的数字j。明显函数都能满足,不用关心返回-1或是a.length。这里要注意,题干中说明了val只在数组中出现一次,若是出现多次结果又应该不同了。
总结:单纯看代码,不足以判定不同的实现是否是行为等价的---需要根据代码的spec来判定行为等价性---在编写代码之前,需要弄清楚spec如何协商形成、如何撰写
(4) Specification structure: pre-condition and post-condition前置和后置条件
前置条件用requires表示;后置条件用effects表示
前置条件:对客户端的约束,在使用方法时必须满足的条件
后置条件:对开发者的约束,方法结束时必须满足的条件
契约:如果前置条件满足了,后置条件必须满足
静态类型声明是一种规约,可据此进行静态类型检查
方法前的注释也是一种规约,但需人工判定其是否满足
Parameters are described by @param clauses and results are described by @return and @throws clauses.
Put the preconditions into @param where possible, and postconditions into @return and @throws.
除非在后置条件里申明过,否则方法内部不应该改变输入参数
尽量不涉及mutating的spec,否则就容易引发bugs
程序员直接应达成的默契:除非spec必须如此,否则不应该改变输入参数
尽量避免使用Mutable的对象
3.Designing specifications
(1) Classifying specifications
如何比较两个规约,以判断是否可以用一个规约替换另一个?
规约的强度S2>=S1当且仅当:
S2的前置条件更弱
S2的后置条件更强
spec变强:更放松的前置条件+更严格的后置条件
(2) Diagramming specifications
空间中的每个点表示一个方法的实现。
某个具体实现,若满足规约,则落在其范围内;否则,在其之外。
更强的规约,表达为更小的区域
更强的后置条件意味着实现的自由度更低了-》在图中的面积更小
更弱的前置条件意味着实现时要处理更多的可能输入,实现的自由度低了-》面积更小
(3) Designing good specifications
在规约里使用抽象类型,可以给方法的实现体与客户端更大的自由度
在Java中,这通常意味着使用接口类型,如Map或Reader,而不是特定的实现类型,如HashMap或FileReader。