【软件构造】设计规约
代码文档
编码提供的文档记录程序的设计决策,大体可以分为两类,一种是独立于代码的自然语言文档,一种是规范编码本身起到的文档作用。
自然语言文档
自然语言文档一般是在代码间的注释或独立于代码的文档。以一个Java使用的API为例,文档一般以类为单位,每个类的页面要包含类所属的包、类实现的接口和继承的类、类的简介、类的构造方法、类的属性和方法的详细介绍、类在不同版本的变更等。
API文档是给API的使用者看的,目的是让使用者在不用关心API具体实现地情况下尽可能快地掌握API的使用方法,因此一个优秀的API文档应当清晰易懂,甚至包含用例示范等内容。
下面是一个很好的样例:


规范编码
有句话说,好的代码不需要注释,代码本身就是自己的注释。规范清晰的编码本身就能起到文档的作用,传达编码的设计决策
例如在某个类中有一个用final修饰的成员变量,如果你在完成编码后将这个fianl去掉也不会影响程序的运行,但是保留final可以提醒使用者这个成员变量不能被修改,这起到了文档的作用。
方法规约
一个程序需要用大量的方法构建,每个方法都可以被独立开发、测试、复用。
一个完整的方法由方法的规约spec和实现体构成。前者包含方法的javadoc注释和签名,后者则是方法最外层大括号内的所有内容。
/**
* Add a vertex to this graph.
*
* @param vertex label for the new vertex
* @return true if this graph did not already include a vertex with the
* given label; otherwise false (and this graph is not modified)
* @throws NullPointerException if vertex is null
*/
@Override public boolean add(L vertex) {
//————此处为实现体和spec的分界线————
if(vertex==null)
{
throw new NullPointerException("尝试添加空顶点,请检查操作!");
}
if(vertices.contains(vertex))
{
return false;
}
vertices.add(vertex);
checkRep();
return true;
}
方法的规约spec用自然语言描述了使用方法遵守的规则和使用方法产生的作用,方法的调用者不需要阅读实现体的代码,而是只看Spec来判断需要使用什么方法,怎样使用方法;而开发者也只需要严格按照方法spec的描述来实现方法。因此规约spec可以称作是实现者和使用者之间的契约,只有两方都严格遵守才能让方法正确发挥作用。
在理想情况下,规约可以直接节省使用者和开发者对于这个方法所有沟通。即便开发者要修改方法的具体实现,只要规约足够精确且开发者依然严格按照规约要求修改,开发者甚至不需要通知使用者方法被修改的事情。
如何写规约
方法规约应该在编码前就确定,由开发者和使用者共同商议得出结论。
只讲“能做什么”,不讲“怎么实现”。一个好的规约应该只包含“初-终”状态。
规约应包含前置条件和后置条件。前置条件是对于使用者使用的约束,而后置条件是对于开发者提供输出的约束;如果使用者按照前置条件使用方法,那么开发者必须保证方法能够提供满足后置条件的输出。
而如果使用者没有遵守前置条件,则开发者提供的方法可以以任意形式来处理这种情况。不过一个好的规约应当也包含对于各种违反前置条件的输出的限制,这样可以帮助使用者更好的发现错误。
另外,除非spec要求必须如此,方法不应该改变传入的可变类型对象,方法的返回值也不应该是可变类型的类的成员变量。这两种情况对于可变类型对象的修改都可能导致意外的Bug,而且这种Bug往往及其难以发现,因为使用者一般不会关心调用方法的具体实验。如果方法确实有让一些不应发生变化的对象陷入被修改的风险,我们不能简单在规约里警告使用者,因为使用这种方法不遵守前置条件影响的不只是返回值,只依靠使用者的“道德”可能会发生很多意外的Bug。因此我们最好还是使用防御性拷贝,让使用者放心修改返回值。
规约的优劣
对于一个方法,规约并非是唯一的,不同的人对于一个方法可能会写出不同的规约。我们要掌握如何判断归约的优劣,编写、挑选处更优的规约。
- 规约的强度
一个规约的前置条件越弱、后置条件越强,则其规约强度越大。规约的强度越大,则质量越好。因为编写一个方法是为了让使用者更好的复用,应当让使用者能更轻松的获得更明确的返回值。 - 规约的可读性
规约应当简洁易懂,没有歧义。以让使用者只看spec能尽可能快的掌握方法的正确用法为佳。 - 抽象性
使用抽象类型,给予使用者更大的自由度

浙公网安备 33010602011771号