软件构造学习笔记第五章——设计规约

目录

1.什么是规约

2.行为等价性

3.确定的规约vs非确定的规约

3.1确定的规约

3.2非确定的规约

4.声明式规约vs操作式规约

4.1声明式规约

4.2操作式规约

5.规约的组成

5.1前置条件

5.2后置条件

5.3例子

6.规约应该展示的内容

7.设计规约

7.1规约的强弱

7.2图画规约

7.3设计一个好的规约

7.4一般的约定


1.什么是规约

规约包括方法的注释和方法名和参数等,不包括方法的实现体(方法块内的注释不算)

规约就是注释,不能被编译器检测(×)

方法部分还是能被编译器静态检测出来的。

规约只讲“能做什么”,不讲“怎么实现”。

2.行为等价性

站在用户的角度看方法是否等价,而不是从实现的方式,只要同时能满足用户的需求,则等价。

3.确定的规约vs非确定的规约

3.1确定的规约

对于同一输入,返回的是确定的值。

3.2非确定的规约

对于同一输入,返回的不是确定的值。

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图画规约

下图中每一个点代表一个方法的实现,每一个椭圆代表一种规约限定的范围(圆越小,规约越强),即点若处在椭圆内,则该方法满足这个规约。

更强的规约需要(相对而言)更小的面积的椭圆来表示,具有更强规约的方法除以更内层因为它可以满足的规约更多。

7.3设计一个好的规约

(1)内聚性

即设计的规约功能单一,简单,易理解。下面是反例,有两个功能,应拆分成两个方法来实现。

(2) 强壮性

即需要告知用户这个方法在一般和特殊情况时会怎么处理,参数会怎么变化,返回值会怎么变化。以下这个例子只是说明了遇到null会抛出异常,但没有说明list1和list2会如何变化。

(3)规约可以适当弱一些

(4)使用抽象数据类型

使用抽象数据类型而不是具体的数据类型。

(5)是否使用前置条件

如果使用,则方便了程序员,限制了用户;如果不使用,则为难了程序员,方便了用户。需要根据代价掂量。例如,假如一个方法需要的前置条件是输入参数是一个递增的数组,如果不写该前置条件,则在方法里进行check的代价太大了,还是写的好。

(6)明确性

方法调用的返回应该是一个明确的结果。如下例:

这个规约设计不好,原因是当返回值为NULL时,无法确定是因为存在一个键值对应NULL还是不存在而返回NULL。

7.4一般的约定

① 除非规约中有明确声明在输入参数和返回参数允许使用NULL,一般的方法和类的设计是不允许出现NULL作为输入和返回的(如果设计方法和类时允许出现NULL,则必须在规约中显式地声明)。

②除非规约中有明确声明在输入参数和返回参数补允许使用空串,一般的方法和类的设计是允许出现空串作为输入和返回的(如果设计方法和类时不允许出现空串,则必须在规约中显式地声明)。

③如果规约中不明确地声明可能会出现异常,一般是默认不会出现异常。倘若设计方法或者类时会出现异常,那么就需要在规约中以@throws的形式写出来。

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2022年5月7日
下一篇 2022年5月7日

相关推荐