规约的介绍:
“方法”是程序的积木,可以被独立开发、测试、复用。使用“方法”的客户端,无需了解内部的具体实现,这就是“抽象” 的思想。
一个完整的方法应包含规约和实现两大部分
代码中本身就蕴含着你的设计决策,但是远远不够
final关键字定义了设计决策“不可改变”
代码中的设计决策:给编译器读
注释中的设计决策:给自己和别人读
规约的作用:
隔离变化,无需通知客户端
规约可以提高编码效率
规约可以扮演防火墙的角色
解耦,不需要了解具体实现
行为等价性:
根据规约判断是否行为等价
eg:见ppt26页
规约的设计
前置条件(precondition):对客户端的约束,客户端使用方法时必须满足的条件,使用关键词requires表明。
后置条件(postcondition):对开发者的约束,方法结束时必须满足的条件,使用关键词effects表明。
静态类型声明是一种规约,可据此进行静态类型检查(static checking)
方法前的注释也是一种规约,但需人工判定其是否满足
契约:如果前置条件满足了,后置条件必须满足;前置条件不满足,则方法可做任何事情
规约具体设计:
参数使用@param描述,结果使用@return、@throws描述
如果可能,将前置条件写入@param中,后置条件写入@return和@throws中
除非在后置条件中声明过,否则方法内部不应该改变输入参数
尽量不设计修改输入参数的规约,减少使用可变对象
描述的功能要单一、简单、易理解
如果规约中需要提到“值”,只能使用抽象空间中的“值”
可从规约的确定性、陈述性及强度入手进行比较。
假如规约强度S2 >= S1,则有:
- 前置条件S2比S1更弱或相同
- 后置条件S2比S1更强或相同
较强的规约具有更放松的前置条件 + 更严格的后置条件
当规约被增强时:
- 可满足规约的实现方式更少
- 更多的用户端可以使用
- 实现者(开发者)的自由度更小,责任更重
- 客户端(使用者)责任更轻
某个具体实现,若满足规约,则落在其范围内,否则,在其之外
程序员可以在规约的范围内自由选择实现方式,客户端无需了解具体使用了哪个实现
规约越强,对应的区域越小
如何设计好的规约
规约不应太弱,也不能太强(权衡用户使用与实现难度)
在规约里使用抽象类型,可以给方法的实现体与客户端更大的自由度
是否使用前置条件取决于check的代价和方法的使用范围