目录
1.什么是规约
规约包括方法的注释和方法名和参数等,不包括方法的实现体(方法块内的注释不算)。
规约就是注释,不能被编译器检测(×)
方法部分还是能被编译器静态检测出来的。
规约只讲“能做什么”,不讲“怎么实现”。
2.行为等价性
站在用户的角度看方法是否等价,而不是从实现的方式,只要同时能满足用户的需求,则等价。
3.确定的规约vs非确定的规约
3.1确定的规约
对于同一输入,返回的是确定的值。
3.2非确定的规约
对于同一输入,返回的不是确定的值。
val可能出现多次,它也没说明是从左往右找还是从右往左找,或者也可能是根据随机来选择从左或从右开始找,因此对同一输入可能会返回不同的值 。
4.声明式规约vs操作式规约
4.1声明式规约
声明性规约没有给出中间步骤的细节。相反,它们只是给出最终结果的属性,以及它与初始状态的关系。
4.2操作式规约
操作式规约(用伪代码或者笔述)给出了方法的实现大致思路,例如告诉客户这个数组是从左往右遍历的。
5.规约的组成
5.1前置条件
对客户端的约束,在使用方法时必须满足的条件。包括方法声明满足的参数条件和require中的条件。例如,方法声明中的参数输入必须是整数和数组,require要求改整数必须大于等于0,该整数必须在数组中出现且仅出现一次。
5.2后置条件
对开发端的约束,在方法结束时必须满足的条件。包括返回值的类型必须要正确和effect中的条件。例如,返回值必须是整数,effect中要求出错时要抛出异常。
5.3例子
错误的例子:
如果会对输入的参数进行改变的,那么一定要写入规约中,一般除非后置条件里声明,否则不应该改变输入的参数:
6.规约应该展示的内容
一个规约可以涉及方法的输入参数和返回值,但是不能涉及方法的局部变量或者类的私有属性或者实现细节。
7.设计规约
7.1规约的强弱
有两个规约S1、S2,如果S1的前置条件更弱且后置条件更强,则说明S1的规约比S2的规约要强(条件越弱说明越容易满足)。如下例:
以下情况不可比较:
一个规约很强意味着什么:
①更少的实现能满足它(因为规约变强了,那么实现它也越难)
②更多的客户可以使用它
7.2图画规约
下图中每一个点代表一个方法的实现,每一个椭圆代表一种规约限定的范围(圆越小,规约越强),即点若处在椭圆内,则该方法满足这个规约。
如上图,findFirst和findLast和findOneOrMore满足同一规约,程序员可以任意选择其中一个来实现,客户端无需了解具体使用了哪个实现。
更强的规约需要(相对而言)更小的面积的椭圆来表示,具有更强规约的方法除以更内层因为它可以满足的规约更多。
7.3设计一个好的规约
(1)内聚性
即设计的规约功能单一,简单,易理解。下面是反例,有两个功能,应拆分成两个方法来实现。
(2) 强壮性
即需要告知用户这个方法在一般和特殊情况时会怎么处理,参数会怎么变化,返回值会怎么变化。以下这个例子只是说明了遇到null会抛出异常,但没有说明list1和list2会如何变化。
(3)规约可以适当弱一些
(4)使用抽象数据类型
使用抽象数据类型而不是具体的数据类型。
(5)是否使用前置条件
如果使用,则方便了程序员,限制了用户;如果不使用,则为难了程序员,方便了用户。需要根据代价掂量。例如,假如一个方法需要的前置条件是输入参数是一个递增的数组,如果不写该前置条件,则在方法里进行check的代价太大了,还是写的好。
(6)明确性
方法调用的返回应该是一个明确的结果。如下例:
这个规约设计不好,原因是当返回值为NULL时,无法确定是因为存在一个键值对应NULL还是不存在而返回NULL。
7.4一般的约定
① 除非规约中有明确声明在输入参数和返回参数允许使用NULL,一般的方法和类的设计是不允许出现NULL作为输入和返回的(如果设计方法和类时允许出现NULL,则必须在规约中显式地声明)。
②除非规约中有明确声明在输入参数和返回参数补允许使用空串,一般的方法和类的设计是允许出现空串作为输入和返回的(如果设计方法和类时不允许出现空串,则必须在规约中显式地声明)。
③如果规约中不明确地声明可能会出现异常,一般是默认不会出现异常。倘若设计方法或者类时会出现异常,那么就需要在规约中以@throws的形式写出来。
今天的文章软件构造学习笔记第五章——设计规约[通俗易懂]分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:http://bianchenghao.cn/85258.html