1.Invariants(不变量)

不变量:程序在任何时间总是true的性质。一旦创建,不变性对象在其整个生命周期中都应始终代表相同的值。

Immutability就是一个典型的不变量

1.1.为什么需要不变量

①当ADT保留自己的不变量时,对代码的推理就变得容易得多。可以依靠String永远不会改变的事实,则可以在调试使用String的代码时或尝试为使用String的另一个ADT建立不变量时排除这种可能性。将其与可变的字符串类型进行对比,该可变的字符串类型可以由任何有权访问它的代码进行突变。要推断出涉及可变字符串的错误或不变式,您必须检查代码中可能使用该字符串的所有位置

②如果没有这个不变量,那么在所有使用String的地方,都要检查其是否改变了。

1.2.Immutability as a type of Invariants

表示泄露:不仅影响不变量,也影响力独立性:无法在不影响客户端的情况下改变其内部表示。Abstraction Functions and Rep Invariants_抽象函数Abstraction Functions and Rep Invariants_表示不变量_02

Abstraction Functions and Rep Invariants_抽象函数_03Abstraction Functions and Rep Invariants_java_04

1.3.How to solve it ? --defensive copying (防御性拷贝)

Abstraction Functions and Rep Invariants_抽象函数_05

Abstraction Functions and Rep Invariants_抽象函数_06

①但是,当复制代价很高时,不得不这么做,由此引发的潜在的bug也很多。

②除非迫不得已,否则不要把希望寄托于客户端上,ADT 有责任保证自

己的invariants ,并避免“表示泄露”。

③最好的办法就是使用immutable

1.4.保持不变量

1.在对象的初始状态不变量为true,在对象发生变化时,不变量也要为true

2.构造器和生产器在创建对象时要确保不变量为true

3.变值器和观察器在执行时必须保持不变性。

4.在每个方法return之前,用checkRep()检查不变量是否得以保持。

2.Rep Invariant and Abstraction Function

表示值构成的空间:实现者看到和使用的值

抽象值构成的空间:client 看到和使用的值

ADT 开发者关注表示空间R ,client 关注抽象空间A

Abstraction Functions and Rep Invariants_表示独立性_07

Abstraction Function

抽象函数:R 和A 之间映射关系的函数,即如何将R 中的每一个值解释为A 中的每一个值。

AF : R → A

AF : 满射、非单射、未必双射

R 中的部分值并非合法的,在A中无映射值

Abstraction Functions and Rep Invariants_抽象函数_08

Rep Invariant: another important ADT invariants

▪ 表示不变性RI :某个具体的“表示”是否是“合法的”

▪ 也可将RI 看作:所有表示值的一个子集,包含了所有合法的表示值

▪ 也可将RI看作:一个条件,描述了什么是“合法”的表示值

Abstraction Functions and Rep Invariants_表示独立性_09

What determine AF and RI?

不同的内部表示,需要设计不同的AF和RI

选择某种特定的表示方式R,进而指定某个子集是“合法”的(RI),并为该子集中的每个值做出“解释”(AF)——即如何映射到抽象空间中的值。

①同样的表示空间R ,可以有不同的RI

Abstraction Functions and Rep Invariants_表示独立性_10

②即使是同样的R 、同样的RI ,也可能有不同的AF ,即“解释不同”。

Abstraction Functions and Rep Invariants_表示独立性_11

3.Checking the Rep Invariant 随时检查RI是否满足

在所有可能改变rep 的方法内都要检查

Observer 方法可以不用,但建议也要检查,以防止你的“万一”

Abstraction Functions and Rep Invariants_抽象函数_12

4.Documenting the AF, RI, and Safety from Rep Exposure

在代码中用注释形式记录AF和RI

要精确的记录RI:rep中的所有fields何为有效
要精确记录AF:如何解释每一个R值

给出理由,证明代码并未对外泄露其内部表示—— 自证清白

Abstraction Functions and Rep Invariants_表示不变量_13

5.What an ADT spec may talk about

1.ADT的规约里也不应谈及任何内部表示的细节,以及R空间中的任何值

2.ADT的内部表示(私有属性)对外部都应严格不可见

3.故在代码中以注释的形式写出AF和RI而不能在Javadoc文档中,防止被外部看到而破坏表示独立性/信息隐藏