规约Specs

规约——使方法可以“交流”

我们知道,Java中的一切操作几乎都需要通过方法来实现,因此其在整个基于Java的软件开发过程中占有举足轻重的地位。程序员一般会对方法进行编写、测试、复用等一系列操作,这些操作为了考虑软件的向能往往比较复杂。而软件是面向客户的一种产品,用户需要在较短的时间内得知软件中的不同方法的功能和使用方法。

不仅如此,程序员自己团队的其他成员在使用这个方法时也希望能以最快的速度知道这个方法的要求和作用,甚至程序员自己未来的某一天重新回看这个方法的时候也有可能忘记这个方法的细节(事实上,对同一个名称的方法,不同人,在不同时间的理解可能不同,而很多的bug往往来源于这些“不同的理解”)。这个时候,规约就起到了人和代码间“交流”的作用。一个具体的规约实例如下图所示:


而Java中规约的书写一般使用Javadoc的格式,其生成的样式一般如下图所示:我们可以前往Oracle的Java Platform中看到更多的方法的规约。


行为等价性(Behavioral Equivalence)

如果在用户的观察角度下,两个方法可以替换,则称这两个方法具有行为等价性。

下面,我们以下图的两个函数为例详细地讲述行为等价性。


当给定参数val缺失时,findFirst()函数返回数组的长度,而findLast()函数返回-1;

当给定参数val在数组中出现超过两次时,findFirst()函数返回val最早出现的位置,而findLast()函数返回val最后出现的索引。

但是我们可以发现,当给定参数val在数组中出现且仅出现一次时,这两个方法的返回值相同,因此,在这种情况下,findFirst()函数和findLast()函数对用户是一样的。

规约结构

一个方法的规约主要由以下几部分组成:

1.    前置条件(Precondition):由关键字require表示,为方法对客户的要求,即客户在使用此方法时必须满足的条件

2.    后置条件(Postcondition):由关键字effects表示,对开发者的要求,即方法本身需要满足的要求。

3.    契约(Exceptional Behavior):在前置条件被违反的情况下方法的行为

规约的确定性

1.    确定的规约:确定的规约是指给定一个满足前置条件的输入,方法的输出应该是唯一且明确的

2.    欠定的规约:欠定的规约是指对于一个给定的、确定的输入,方法会有多个输出

3.    非确定的规约:非确定的规约是指对于一个给定的输入,多次执行这个方法可能得到不同的结果

规约的强度

对于实现相似功能的方法,我们一般可以通过比较其规约强度来判断这两个方法是否可以用其中的一个去替换另一个。一般地,我们可以用一个规约强度更高的方法去替换一个规约强度更低的方法去实现相似的功能。那么,下面我们来介绍比较两个方法规约强度的方法。

对于两个规约S1、S2,若S2的前置条件比S1的前置条件更弱且S2的后置条件比S1的后置条件更强,则称规约S2比规约S1的强度更强。即规约变强=更放松的前置条件+更严格的后置条件。规约的强度越强,意味着方法的自由度越低,责任越重,而方法的责任越重会直接减轻用户的责任。所以说,程序员应该尽可能做到少写,甚至不写前置条件,所有可能出现的问题都应该尽量在代码的内部进行检查。如果检查的代价确实太大,就在规约中加入前置条件,把责任交给客户。当然,对于客户来说,一定是不喜欢过强的前置条件的,因为不满足前置条件的输入会直接导致程序运行失败。

对于这种原则,一般的做法是:不限制太强的前置条件,当出现不符合方法逻辑的输入时,通过抛出异常的方式进行提示,并且尽可能避免错误的扩散。













猜你喜欢

转载自blog.csdn.net/LeoYu1998/article/details/80857169