哈工大软件构造复习二

Abstraction and User-Defined Types

除了编程语言所提供的基本数据类型和对象数据类型,程序员可定义自己的数据类型

Data Abstraction(数据抽象)

由一组操作所刻画的数据类型
传统的类型定义:关注数据的具体表示
抽象类型:强调“作用于数据上的操作”,程序员和client无需关心数据如何具体存储的,只需设计/使用操作即可。

Classifying Types and Operations

Mutable and immutable types

可变类型的对象:提供了可改变其内部数据的值的操作
不变数据类型: 其操作不改变内部值,而是构造新的对象

Classifying the operations of an abstract type

  • Creators(构造器): create new objects of the type.
  • Producers(生产器): create new objects from old objects of the type.
  • Observers(观察器): take objects of the abstract type and return objects of a different type.
  • Mutators(变值器): change objects. 改变对象属性的方法

Abstract Data Type Examples

  • int: immutable, so it has no mutators.
    • creators: the numeric literals 0 , 1 , 2 , …
    • producers: arithmetic operators + , - , * , /
    • observers: comparison operators == , != , < , >
    • mutators: none (it’s immutable)
  • String: Java’s string type. String is immutable.
    • creators: String constructors
    • producers: concat , substring , toUpperCase
    • observers: length , charAt
    • mutators: none
  • List: Java’s list type and is mutable.
    • creators: ArrayList and LinkedList constructors, Collections.singletonList
    • producers: Collections.unmodifiableList
    • observers: size , get
    • mutators: add , remove , addAll , Collections.sort

Designing an Abstract Type

Designing an abstract type involves choosing good operations and determining how they should behave. 设计好的ADT,靠“经验法则”,提供一组操作,设计其行为规约 spec

  • 设计简洁、一致的操作
  • 要足以支持client对数据所做的所有操作需要,且用操作满足client需要的难度要低
  • 要么抽象、要么具体,不要混合 — 要么针对抽象设计,要么针对具体应用的设计

Representation Independence (RI)

表示独立性:client使用ADT时无需考虑其内部如何实现,ADT内部表示的变化不应影响外部spec和客户端。
除非ADT的操作指明了具体的pre-condition和post-condition,否则不能改变ADT的内部表示——spec规定了client和implementer之间的契约。
在这里插入图片描述

Testing an ADT

  • 测试creators, producers, and mutators:调用observers来观察这些
    operations的结果是否满足spec;
  • 测试observers:调用creators, producers, and mutators等方法产生或
    改变对象,来看结果是否正确。
  • 风险:如果被依赖的其他方法有错误,可能导致被测试方法的测试结
    果失效。

Invariants

The most important property of a good abstract data type is that it preserves its own invariants. (保持不变量)
不变量:在任何时候总是true,例如:immutability就是一个典型的“不变量”
由ADT来负责其不变量,与client端的任何行为无关
为什么需要不变量:保持程序的“正确性”,容易发现错误
总是要假设client有“恶意”破坏ADT的不变量—defensive programming

Rep Invariant and Abstraction Function

Abstraction Function

一般情况下ADT的表示比较简单,有些时候需要复杂表示
抽象值构成的空间:client看到和使用的值
在这里插入图片描述

  • ADT开发者关注表示空间R,client关注抽象空间A
  • Every abstract value is mapped to by some rep value (surjective, 满射).
  • Some abstract values are mapped to by more than one rep value (not injective, 未必单射).

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

Rep Invariant: another important ADT invariants

  • 表示不变性RI:某个具体的“表示”是否是“合法的”
  • 也可将RI看作:所有表示值的一个子集,包含了所有合法的表示值
  • 也可将RI看作:一个条件,描述了什么是“合法”的表示值

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

设计ADT:

  1. 选择R和A;
  2. RI — 合法的表示值;
  3. 如何解释合法的表示值 —映射AF
  4. 做出具体的解释:每个rep value如何映射到abstract value,而且要把这种选择和解释明确写到代码当中

Checking the Rep Invariant 随时检查RI是否满足
在这里插入图片描述

Beneficent mutation

  • 对immutable的ADT来说,它在A空间的abstract value应是不变的。
  • 但其内部表示的R空间中的取值则可以是变化的。
  • 这种mutation只是改变了R值,并未改变A值,对client来说是immutable的 →“AF并非单射”,从一个R值变成了另一个R值
  • 但这并不代表在immutable的类中就可以随意出现mutator!
  • 通过牺牲immutability的部分原则来换取“效率”和“性能”
    • Caching:例如通过cache暂存某些频繁计算的结果
    • Data structure rebalancing:例如对tree数据结构进行插入或删除节点之后
    • Lazy computation:上例中在toString()的时候才进行约分计算

Documenting the AF, RI, and Safety from Rep Exposure

  • 在代码中用注释形式记录AF和RI
  • 要精确的记录RI:rep中的所有fields何为有效
  • 要精确记录AF:如何解释每一个R值
  • 表示泄漏的安全声明(Safety from Rep Exposure):给出理由,证明代码并未对外泄露其内部表示——自证清白
  • ADT的规约里只能使用client可见的内容来撰写,包括参数、返回值、异常等。
  • 如果规约里需要提及“值”,只能使用A空间中的“值”。
  • ADT的规约里也不应谈及任何内部表示的细节,以及R空间中的任何值
  • ADT的内部表示(私有属性)对外部都应严格不可见,故在代码中以注释的形式写出AF和RI而不能在Javadoc文档中,防止被外部看到而破坏表示独立性/信息隐藏

ADT invariants replace preconditions

用ADT不变量取代复杂的Precondition,相当于将复杂的precondition封装到了ADT内部。
在这里插入图片描述

  • 更加安全
  • 更加易于理解
  • 更加准备好迎接变化
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值