Spec规约
spec,即规约(specification),其规约的是使用者(client)【用扳手的人】和实现者(implementor)【造扳手的人】之间约定的契约——在使用时和实现时都必须要遵循该要求
每一个类前面
每一个方法前面
spec从由简要描述+前置条件precondition+后置条件postcondition等组成
- 前置条件precondition:这是对客户端的约束,是用户在使用方法时必须满足的条件。在Java中一般使用声明@param说明每个参数的前置条件
@parameter 参数及其说明 - 后置条件postcondition:这是对开发者的约束,也是方法结束时设计者必须满足的内容。在Java中一般使用如下两种声明,其内容及用途如下:
@return:对后置条件的说明,一般为返回值;
@throws:说明出现异常的时候会发生什么,一般为异常处理方式。
spec中需要涵盖对于前置条件和后置条件的说明,包括函数/类的基本使用方法、参数是否可变(immutable/mutable)、使用过程中可能出现问题的情况即抛出的Exception描述
Spec越强
-
更宽松的前置条件
-
更严格的后置条件
如果是用椭圆在图中对不同的Spec强弱进行表示,则越小(包含的结果的点越少)的椭圆,其Spec越强,此处我们可以理解为:椭圆的大小代表了开发者的自由度
程序员应该通过Spec让客户端轻松地知道他需要为这个方法提供什么样的参数,以及会得到什么样的结果,但不应该让用户知道方法的内部逻辑是怎么样的,以避免恶意用户对代码结构的破坏。
AF和RI
RI:Rep Invariant。其中Invariant是不变量的意思,是ADT的功能中任何时候都应该满足的一些条件
AF:Abstraction Function。代表抽象函数
AF和RI中的A和R分别代表两个空间:R是内部表示的空间,是开发者关注的内容;而A是ADT能表示的存在于实际的对象,一般是由客户所关注的。
AF就是从R空间到A空间的一个映射,作为解释函数,对A空间的每一个对象,在R空间中都至少由一种属性或类型与之对应,因此该映射是一个满射。
RI是一个集合,是R空间中所有值的子集,包含了所有合法的表示值。checkRep()方法就是用来随时检查RI是否被满足的。
一定是满射,未必单射,未必双射
相同的R可能存在不同的RI;
即使是同样的R、 RI,也可以根据解释不同,而获得不同的AF;
两个ADT有相同的rep和相同的AF,但其R也不—定相同
不应该给client看的内容有AF、RI、Rep exposure safety argument、testing strategy、Rep、Implementation和Test cases等等,留给client的只有Spec。
本文主要解释了一些ADT设计中关于Spec、AF和RI的含义、内容、注意事项等内容。其细节部分相对琐碎,但是在实际应用中非常重要,因此应该牢记,并在日后有需求的时候活学活用