软件构造规约设计知识点总结
已经开始做软件构造实验二了,但做了几天还是感觉不太对,有种无从下手的感觉,我还是来复习一下本次实验所要用到的知识点吧,至于前面的知识呢,先别急,虽然也用的上,但在本次实验不是重点,之后再进行复习。
知识点概要:
规约设计
测试用例
ADT的泛化型
ADT的抽象函数(AF)、表示不变性(RI)
OOP实现ADT,并且检测表示泄露(RE)
在本次将进行规约设计的知识点回顾
规约设计
一、规约的简要介绍
“方法”是程序的“积木”,可以被独立开发、测试、复用使用“方法”的客户端,无需了解方法内部具体如何工作—“抽象”,这是方法的主要思想。而用例规约则是在这一基础上延伸出来的,是一个方法前面的说明性注释,会解释方法的功能、参数、返回值等。
规约的好处是十分明显的,首先作为开发者,先写下规约可以清晰地明确该方法要实现的功能与限制,并且在之后的开发中不会忘记该方法的作用;而对于客户端,好处则更加明显:无需阅读调用函数的代码,只需理解spec即可,相当便捷高效。
下图是一个规约的具体例子,首先描述了方法的作用,@param解释了方法中参数的意义及限制,@return解释了方法的返回值。
一句话概括规约:只讲“能做什么”,不讲“如何实现”!

二、行为等价性
行为等价性,是用来判断两个函数是否等价(对客户端来说)。
具体到如何判断两个函数是否行为等价,单纯的看实现代码,并不足以派判定不同的implmentation是否是行为等价的,需要用规约来判断,若两个函数都符合同一个规约,则他们俩行为等价。
三、规范结构:前置条件和后置条件
  前置条件(precondition):对客户端的约束,在使用方法是必须满足的条件,使用关键词requires表明。
  后置条件(postcondition):对开发者的约束,方法结束是必须满足的条件,使用关键词effects表明。
契约:如果前置条件满足了,后置条件必须满足;前置条件不满足,则方法可做任何事情,“你违约在先,我自然不遵守承诺”。
规约具体设计规则:
- 参数使用@param描述,结果使用@return、@throws描述
- 如果可能,将前置条件写入@param中,后置条件写入@return和@throws中
- 除非在后置条件中声明过,否则方法内部不应该改变输入参数
- 尽量不设计修改输入参数的规约,减少使用可变对象
- 描述的功能要单一、简单、易理解
下图是一个具体的规约及函数实现(条件可能出现在@param和@return之外的其他地方,因此一定要仔细读用例规约!!)

注意:在规约中一定不能包含方法中的局部变量与私有字段,要使方法中的具体实现对用户invisible。
四、规约的分类
规约的分类一般分为四种分类方法,分别通过正确性、陈述性和强度进行分类。
按强度进行分类
用来判断是否可用用一个规约来替换另一个,一般是运用强度对两个规约进行判断。
假如规约强度S2 >= S1,则有:
- 前置条件S2比S1更弱或相同
- 后置条件S2比S1更强或相同
较强的规约具有更放松的前置条件 + 更严格的后置条件
下图展示了三个规约强度的比较

而下图两个规约的强度则无法比较,相较于第一个规约,第二个的前置条件更弱了;但在满足第一个规约的前置条件的情况下,第二个规约相较于第一个其后置条件也弱化了(没有返回最低索引值)。

总的来说,当规约被增强时:
- 可满足规约的实现方式更少
- 更多的用户端可以使用
- 实现者(开发者)的自由度更小,责任更重
- 客户端(使用者)责任更轻
按确定性进行分类
确定性规约(Deterministic):给定前置条件,其输出是唯一的、明确的。
欠定的规约(Underdetermined):同一个输入可以有多个输出,但是一旦使用具体的方法实现了这个规约,那么这个返回值也将会被确定。
非确定的规约(Not deterministic):同一个输入,多次执行可能得到多个结果,比如涉及到随机数的方法。
按陈述性分类
操作式规约:有具体的实现细节,如伪代码
声明式规约:没有内部实现的描述,只有对输入输出的规定
声明式规约更有价值,更能应对变化。但是操作式规约能够方便开发。
五、规约画图

已该图为例,规约画图有以下几点性质:
- 某个具体实现,若满足规约,则落在其范围内,否则,在其之外
- 程序员可以在规约的范围内自由选择实现方式,客户端无需了解具体使用了哪个实现
- 规约越强,对应的区域越小
而两个规约无法比较时,则会出现部分重合和不相交的情况,如下图

六、如何设计好的规约
- 规约描述的功能应该单一、简单、易理解,并且不能产生歧义
- 规约不应太弱,也不能太强(权衡用户使用与实现难度)
- 在规约里使用抽象类型,可以给方法的实现体与客户端更大的自由度
- 是否使用前置条件取决于check的代价和方法的使用范围
七、总结
- 规约可以减少bug,并使查找bug变得更容易
- 规约比实现函数本身更易理解,对客户端来说能直接使用方法
- 规约会使方法代码修改变得简单与安全(只要继续满足契约的要求)
 
                    
                 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号