一、概念
规约是一种文字说明,用来解释方法(函数)的参数要求以及返回值要求
它是开发者与用户之间的一种约定,即只要用户按照规约的要求输入参数,开发者便会按照规约的要求输出结果
二、组成
①前置条件(Preconditions):方法对输入的规定,是一种对软件用户的约束;
②后置条件(Postconditions):方法对输出的规定,是一种对开发者的约束;
③异常行为(Exceptional Behavior):方法对用户异常输入所做出的处理方式;
三、属性
①确定性:规约描述的输出是否确定;
②陈述性:只描述了输出?还是描述了如何计算输出;
③强度:判断规约的好坏、可否替换、等价性;
四、书写方式
我们以find方法为例:
/**
*Find a value in an arr
*@param arr array to search, requires that val occurs exactly once in arr
*@param val value to search for
*@return index i if arr[i] = val
*@throws nothing
*/
static int find(int[] arr, int val)
或者写为:
static int find(int[] arr, int val)
requires: val occurs exactly once in arr[]
effects: return i such that arr[i] = val
该方法的作用为输入一个内部值互异的整型数组和一个整型值,如果数组中含有该整型值,则返回该整型值在数组中出现位置的索引值
五、规约的强度判断
设有规约S1 和 S2,且S1强于S2,则需满足:
①前置条件:S1弱于S2 (表明方法对用户输入的限制更少,用户更自由)
②后置条件:S1强于S2 (表明方法对开发者设计方法的输出要求更高,方法功能更强)
简单来说:“更少的要求,更多的承诺”
我们以find方法为例:
第一种:
static boolean find(int[] arr, int val)
requires: val occurs exactly once in arr
effects: returns index i such that arr[i] = val
第二种:
static boolean find(int[] arr, int val)
requires: val occurs at least once in arr
effects: returns index i such that arr[i] = val
第三种:
static boolean find(int[] arr, int val)
requires: val occurs at least once in arr
effects: returns lowest index i such that arr[i] = val
其中,第一种到第三种的规约强度是递增的:
与相比不再限制用户提供的初始数组中val只出现一次,前置条件更弱;
与相比明确表明会返回val第一次出现的位置,失去了“返回某一个出现位置”的随意性,功能更加具体,后置条件更强
六、规约书写的要求
①内聚的:规约的描述应该简单、专一(方法过于复杂时应该将方法功能拆分成多个方法依次实现,再为每个方法写个规约);
②信息丰富的:规约应该包含方法实现了的所有信息(方法所实现类的功能都应该在规约中体现,“既然付出了努力就理应说出来得到褒奖”);
③根据具体情况,规约应该足够强(功能丰富,用户满意),并且足够弱(不给开发者添麻烦);
④写明前置条件和后置条件;
⑤运用抽象数据类型