规约的好处
记录自己的设计决策,供自已或他人阅读。
团队协作中,如果没有规约就无法分派任务,无法写程序;即使写出来,也无法验证对错。
规约作为一种客户端与程序之间的“契约”,可以明确双方的责任。
规约可以隔离变化,无需通知客户端,即不管具体实现如何修改,只要符合规约,客户端就没必要知道修改的具体内容。
达到解耦的目标。
可以利用规约来判定方法的行为等价性。
测试用例可以根据规约来编写。
(方法的)规范和合同
规格(或称为合同)
▪ 规范是团队合作的关键。没有规范就不可能委派实现方法的责任。
▪ 规范充当一个契约,实现者负责满足契约,而使用该方法的客户机可以依赖该契约。
–说明方法和调用方的职责
–定义实现正确的含义
▪ 规范对双方都有要求:当规范有前提时,客户也有责任。
为什么需要规格?
▪ 现实:程序中许多最糟糕的错误都是由于对两段代码之间的接口行为的误解而产生的。
–虽然每个程序员都有自己的规范,但并不是所有的程序员都把它们写下来。因此,团队中的不同程序员有不同的规范。
–当程序失败时,很难确定错误在哪里。
▪ 优点:代码中的精确规范可以让您将责任分摊到代码片段上,并且可以让您免去为修复应该去哪里而费解的痛苦。
–规范对于方法的客户端来说很好,因为它们省去了读取代码的任务。
规范(合同)
▪ 该契约充当客户端和实现者之间的防火墙。
–它保护客户不受该单元工作细节的影响。
–它保护实现者不受单元使用细节的影响。
–此防火墙令客户端和程序不耦合,只要更改符合规范,允许独立更改单元代码和客户端代码。
行为等价性
为了确定行为等价性,问题是我们是否可以用一个实现代替另一个实现
规范结构:前置条件和后置条件
规格结构
▪ 方法的规范由几个子句组成:
–Precondition,由关键字requires指示
–Postcondition,由关键字effects指示
–Exceptional behavior:如果违反了Precondition,它会做什么
▪ 先决条件是客户的义务(即方法的调用方)。它是调用方法的状态的条件。
▪ 后置条件是方法实现者的义务。
▪ 如果调用状态的前提条件成立,则该方法有义务通过返回适当的值、抛出指定的异常、修改或不修改对象等方式遵守后条件。
规格结构
▪ 整体结构是一个逻辑含义:如果在调用方法时前置条件保满足了,则在方法完成时后置条件必须满足。▪ 如果在调用方法时前置条件不成立,则实现不受后置条件的约束。–它可以做任何事情,包括不终止、抛出异常、返回任意结果、进行任意修改等。
按照强弱分类
规约A强度>B规约强度意味着下面两点:
A的前置条件更弱
A的后置条件更强
前置条件和后置条件的强弱由条件的严格程度决定,即如果条件越放松,那么这个条件越弱。反之亦然。
如果要增强一个规约的强度,那么就意味着更松的前置条件+更严格的后置条件。
按照确定性分类
确定性规约(Deterministic):给定前置条件,其输出是唯一的、明确的。
欠定的规约(Underdetermined):同一个输入可以有多个输出,但是一旦使用具体的方法实现了这个规约,那么这个返回值也将会被确定。
非确定的规约(Not deterministic):同一个输入,多次执行可能得到多个结果,比如涉及到随机数的方法。
按照陈述性分类
操作式规约:有具体的实现细节,如伪代码
声明式规约:没有内部实现的描述,只有对输入输出的规定
声明式规约更有价值,更能应对变化。但是操作式规约能够方便开发。
抽象数据类型与表示独立性:
能够分离程序中数据结构的形式和对其使用的方式
ADT的特性:不变量、表示泄漏、抽象函数AF、表示不变量RI
基于数学的形式对ADT的这些核心特征进行描述并应用于设计中。
大纲:
1.抽象和用户定义类型
2.ADT 中的操作分类
3.抽象数据类型示例
4.ADT的设计原则
5.代表独立性 (RI)
6.用Java实现ADT概念
7.测试ADT
8.不变量
9. Rep不变和抽象函数
10.良性突变
11.记录 AF、RI 和 Rep接触的安全性
12.ADT 不变量替换前提条件
AF: 满射、非单射、 未必双射
➔ R中的部分值并非合法的,在A中无映射值
▪ 表示不变性RI:某个具体的“表示”是否是“合法的”
▪ 也可将RI看作:所有表示值的一个子集,包含了所有合法的表示值
▪ 也可将RI看作:一个条件,描述了什么是“合法”的表示值
ADT操作的四种类型:
1.Creators 构造器:
用于创建一个新的对象,主要表现为构造函数。典型的有Integer.valueOf()。
2.Producers生产器:
通过接受同类型的对象以创建新的对象。典型的有String.contact()。(连接两个字符串,产生一个新的字符串)
3.Observers观察器
获取ADT内部的某个信息,而不改变ADT的现有状态。典型的有List.size()。(返回int,不同于原类型)
4.Mutators变值器(改变对象属性的方法)
改变对象内部的信息。典型的有List.add()。
通常为void,如果为void,则必然意味着它改变了某些对象的内部状态,也有可能返回非空类型(如容器类的put、add方法)