一、Spec
spec全称为specification(规约)。specification不仅给我们程序确定了责任(我们需要编写怎样的程序),也同样给客户端确定了责任(他们需要遵守怎样的输入原则,输入怎么样的数据等等)。
specification需要明确输入、输出的数据类型,需要讲清楚method的功能以及它的正确性,以及它的Performance expectations(性能)。
1.Specification structure : pre-condition and post-condition(前置条件和后置条件)
前置条件通过“requires”描述,前置条件是对客户端的约束,在使用方法是必须满足的条件。
后置条件通过“effects”描述,后置条件是对开发者的约束,方法结束时必须满足的条件。
1、如果前置条件满足,则后置条件必须满足。
2、如果前置条件不满足,则方法可做任何事情
所以客户端只有在满足前置条件的情况下输入正确的数据,才能得到他们想要的结果,有了spec可以减轻开发者的负担,排出一些非法的情况。
除非在后置条件中声明过,否则内部方法不应该改变输入参数。开发者应该尽量遵循这个规则。尽量避免使用可变的数据类型。
2.Document(注释)
1、方法的目的,是用来做什么的
2、@param:输入的参数
3、@return:方法的返回值
4、@throws:这个方法中可能抛出的异常(checked and unchecked)
5、thread safety issues:线程安全的策略。
3、Specification的强弱判断
如何比较两个规约?在前置条件相同的情况,后置条件强的规约更强。在后置条件相同的情况下,前置条件更弱的规约更强。
所以spec变强:更放松的前置条件+更严格的后置条件。
规约越强说明对开发者的要求越高,对客户端的约束越小。
3.怎么写规约
我们通过例子来看。比如我们碰到以下代码让我们对他写spec
public List<String> getSomeLines(int start,int end){
List<String> some = new ArrayList<>();
for(int i = start; i < end ; i++){
some.add(lines.get(i));
return some;
}
}
方法getSomeLines()返回文本的第start行到第end行,我们需要针对该方法设计spec,充分考虑健壮性。
/**
*@Param start start需要大于等于0并且小于总行数
*@Param end end需要大于start并且小于等于总行数
*@return 返回从start行到end行之间的行列表
*@throws Nolines 没有行抛出异常
*@throws BoundException start和end不符合规范
*/