前言
本文将介绍一些关于ADT设计中Spec、AF和RI的细节。由于内容较为细碎,为了加强理解,特将该部分知识点列出来,进行简单归纳总结。
一. Spec
刚开始接触软件构造时,关于规约Spec的概念便已经有所接触,但真正开始逐步认识还是在实验中设计规约的时候。
(一)含义
Spec是程序员在设计ADT时对自己所写方法的规约,它规定了方法应该做什么,不应该做什么。而在接下来的设计中,测试用例的编写就需要依靠Spec的描述,因为程序员所编写的代码必定是符合spec的,否则就是不合格的。同时,有了Spec的存在,客户端在使用代码时就会有所依据,好的Spec可以大大节省客户端使用自己的API时所需要的时间,并且大大降低了客户端对自己所编写的代码的误解。
(二)内容及评判标准
Spec的主要内容分为以下三部分:
1. 前置条件precondition:这是对客户端的约束,是用户在使用方法时必须满足的条件。在Java中一般使用声明@param说明每个参数的前置条件。
2. 后置条件postcondition:这是对开发者的约束,也是方法结束时设计者必须满足的内容。在Java中一般使用如下两种声明,其内容及用途如下:
@return:对后置条件的说明,一般为返回值;
@throws:说明出现异常的时候会发生什么,一般为异常处理方式。
(三)Spec强弱
若想要Spec变强,可以采用如下方式:
1. 更宽松的前置条件
2. 更严格的后置条件
如果是用椭圆在图中对不同的Spec强弱进行表示,则越小(包含的结果的点越少)的椭圆,其Spec越强,此处我们可以理解为:椭圆的大小代表了开发者的自由度。
(四)注意事项
程序员应该通过Spec让客户端轻松地知道他需要为这个方法提供什么样的参数,以及会得到什么样的结果,但不应该让用户知道方法的内部逻辑是怎么样的,以避免恶意用户对代码结构的破坏。
二. AF和RI
由于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是否被满足的。
此处附上自己在lab2中写过的AF、RI,以及Safety from rep exposure的描述:
// Abstraction function:
// AF(vertices) = 点集
// Representation invariant:
// 无重复点
// Safety from rep exposure:
// private final List<Vertex<L>> vertices
(三)注意事项
RI、AF存在如下关系:
相同的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的含义、内容、注意事项等内容。其细节部分相对琐碎,但是在实际应用中非常重要,因此应该牢记,并在日后有需求的时候活学活用。