规约的类型:方法的规约
接下来我们将介绍如下内容:
1.Understand preconditions and postconditions in method specifications, and be able to write correct specifications方法的规约2.What preconditions and postconditions are, and what they mean for the implementor and the client of a method (前置/后置条件3.Understand underdetermined specs, and be able to identify and assess nondeterminism (欠定规约、非确定规约) 4.Understand declarative vs. operational specs, and be able to write declarative specs (陈述式、操作式规约)5.Understand strength of preconditions, postconditions, and specs; and be able to compare spec strength (规约的强度及其比 较6.Be able to write coherent, useful specifications of appropriate strength (如何写出好的规约)
这一节我们转向方法/函数/操作如何定义,编程的动词,规约。
一 Functions & methods in programming languages 函数和方法在程序编程语言中。
参数方面:要点:Attention: parameter type mismatch when calling a method – static checking 参数类型是否匹配,在静态类型检查阶段完成
返回值方面:要点:看返回值的类型是否匹配,在静态检查中完成。
变量的作用域:考虑变量作用域的范围,其能影响什么范围的参数。
方法是编程中的块,方法”是程序的“积木”,可以被独立开发、测试、复用 使用“方法”的客户端,无需了解方法内部具体如何工作—“抽象”
二 spec
规约
1 文档形式:规约
规约就是将假设写入,如:变量的数据类型定义、final
关键字。
代码本身就蕴含着设计决策,但远远不够。
Java API
文档 就是通过 Java
标准库源码中的规格说明注释生成的. 同样的,Eclipse
也可以根据你的规格说明产生对应的文档),或者产生和 Java API
一个格式的 HTML
文档 。
为什么要写出规约? 第一 自己记不住 第二 :别人可能不懂
代码中蕴含的设计决策给编译器读
而注释形式的设计决策给自己和别人读。
2 规约和契约
没规约,没法写程序;即使写出来,也不知道对错
Spec给“供需双方”都确定了责任,在调用的时候双方都要遵守
为什么我们需要规约呢? 现实因素 很多bug来自于双方之间的误 解 不写下来,那么不同开发者的理 解就可能不同 没有规约 ,难以定位错误
写规约的优点和好处:精确的规约,有助于区分责任 客户端无需阅读调用函数的代码,只需理解spec即可。
规约可以隔离“变化”,无需通知客户端。
规约:扮演“防火墙”角色
只讲“能做什么”,不 讲“怎么实现”。
3.行为等价性:Behavioral equivalence
站在客户端视角看行为等价性,根据规约 判断是否行为等价。
简单总结一下: 单纯的看实现代码,并 不足以判定不同的 implmentation是否是“ 行为等价的”。
需要根据代码的spec (开发者与client之间 形成的contract)判定 行为等价性 。
在编写代码之前,需要 弄清楚spec如何协商形 成、如何撰写
三 规约结构:前置条件后置条件,Specification structure: pre-condition and post-condition
前置条件:对客户端的约束,在使用方法时必须满足的条件。
后置条件:对开发者的约束,方法结束时必须满足的条件。
契约:如果前置条件满足了,后置条件必须满足。
若前置条件不满足,则方法可做任何事情。 – “你违约在先,我自然不遵守承诺”
静态类型声明是 一种规约,可据此进行静态类型检查static checking。
方法前的注释也是一种规约,但需人工判定其是否满足。除 非在后置条件里声明过,否则方法内部不应该改变输入参数。s. 应尽量遵循此规则,尽量 不设计mutating的spec,否则就容易引发bugs
四:设计规约 Designing specification
1) Classifying specifications 评判规约 哪一个规约更好呢?
spec变强:更放松的前置条件+更严格的后置条件
2)确定的规约:给定一个满足precondition的输入,其输出是唯一的、明确的。
欠定的规约:同一个输入可以有多个输出
非确定的规约:同一个输入, 多次执行时得到的输出可能不同
3)操作式规约,例 如:伪代码
声明式规约:没有内部实现的描述,只有 “初-终”状态,内部实现的细节不在规约里呈现,放在 代码实现体内部注释里呈现
4)将规约图形化 Diagramming specifications
某个具体实现,若满足 规约,则落在其范围内;否则,在其之外。
程序员可以在规 约的范围内自由选择实现方式,客户端无需了 解具体使用了哪个实现
五 如何写出一个好的规约 Designing good specifications
一个好的“方法”设计,并不是你的代码写的多么好,而是你对该方 法的spec设计得如何。 – 一方面:client用着舒服 – 另一方面:开发者编着舒
1) The specification should be coherent (内聚的)
2) The results of a call should be informative(信息丰富的)
3)The specification should be strong enough太弱的spec,client不放心、不敢用 (因为没有给出足够的承诺)。 开发者应尽可能考虑各种特殊情况,在post-condition给出处理措施。
4)The specification should be weak enough.太强的spec,在很多特殊情况下难以达到,给开发者增加了实现的难 度(client当然非常高兴)
5)The specification should use abstract types. 在规约里使用抽 象类型,可以给方法的实现体与客户端更大的自由度
(6) Precondition or postcondition?
是否应该使用前置条件?在方法正式执行之前,是否要 检查前置条件已被满足?
满足以上几个要素,我们才能写出高质量的规约。