3.2 Designing Specification设计规约
1. Function / method in programming language编程语言中的函数/方法
2. Specification: Programming for communication spec:交流
Why specification is needed 为什么需要spec
Behavioral equivalence 行为等价性
Specification structure: pre-condition and post-condition spec的前置条件和后置条件
Testing and verifying specifications 测试与确认spec
3. Designing specifications
Classifying specifications spec的分类
Diagramming specifications spec的图
Quality of a specification spec的质量
1 Functions & methods in programming languages
方法体:内部表述
参数类型,返回值类型(在静态类型检查中确认是否匹配)
变量的作用域
2 Spec: Programming for communication用spec来交流
(1) Documenting in programming 编程中的文档
如:JAVA API 包含:
类的等级;直接的子类;类的描述;构造总结;方法总结;方法和构造器的详细描述
为什么要写出“假设”?第一:自己记不住;第二:别人不懂。
代码中蕴含的“设计决策”:给编译器读
注释形式的“设计决策”:给自己和别人读
测试优先,随时记录代码中的设计决策。
(2) Specification and Contract(of a method)
没规约,没法写程序;即使写出来,也不知道对错
程序与客户端之间达成的一致,Spec 给“供需双方”都确定了责任
利于划分责任,便于客户端理解
扮演防火墙,用户不用知道怎么实现
Spec之讲能做什么,不讲怎么实现。
(3) Behavioral equivalence行为等价性
是否可相互替换,站在客户端视角看行为等价性
根据规约判断是否行为等价,这两个函数符合这个规约,故它们等价。
(4) Specification structure: pre-condition and post-condition前置条件和后置条件
前置条件:对客户端的约束,在使用方法时必须满足的条件
后置条件:对开发者的约束,方法结束时必须满足的条件
契约:如果前置条件满足了,后置条件必须满足
前置条件满足,则后置条件必须满足。
前置条件不满足则方法可以做任何事情
假如前置条件被违反了,我们最好快速失败(failing fast),即使我们没义务这样做
静态类型声明是一种规约,可据此进行静态类型检查 static checking 。
方法前的注释也是一种规约,但需人工判定其是否满足
前置条件在@param中声明 后置条件在@return和@throws中声明
除非在后置条件里声明过,否则方法内部不应该改变输入参数
应尽量遵循此规则,尽量不设计mutating 的 spec ,否则就容易引发 bugs 。
程序中可能有很多变量指向同一个可变对象(别名)
无法强迫类的实现体和客户端不保存可变变量的“别名”
避免使用全局对象,不过有时候为了性能不得不用,这破坏了安全性
3 Designing specifications
(1) Classifying specifications
规约的确定性 规约的陈述性 规约的强度
如何比较两个规约,以判断是否可以用一个规约替换另一个?
spec 变强:更放松的前置条件 + 更严格的后置条件
如果出现其他情况则无法比较(如前置和后置条件都更弱了)
越强的规约,意味着 implementor 的自由度和责任越重,而 client 的责任越轻。
规约的确定性:
(Deterministic)确定的规约:给定一个满足 precondition 的输入,其输出是唯一的、明确的
(underdetermined)欠定的规约:欠定的规约:同一个输入可以有多个输出
(Nondeterministic)非确定的规约:同一个输入,多次执行时得到的输出可能不同
避免混乱,欠定的规约不等于非确定的规约
操作式规约,例如:伪代码
声明式规约:没有内部实现的描述,只有“初 - 终”状态
(2) Diagramming specifications spec的图像
某个具体实现,若满足规约,则落在其范围内;否则,在其之外。
程序员可以在规约的范围内自由选择实现方式
更强的规约,表达为更小的区域
更弱的前置,说明处理更多情况,实现自由度低,面积变小;更强的后置说明实现自由度减小,面积更小。
(3) Designing good specifications
Spec 描述的功能应单一、简单、易理解(最好只在规约里做一件事)
Spec应该信息丰富,不能让客户产生歧义
Spec应该足够强(用户用的放心),也足够弱(开发者更自由)
在规约里使用抽象类型,可以给方法的实现体与客户端更大的自由度