本次实验我学习了ADT的设计、规约、测试,并使用OOP技术实现 ADT。
首先按照给定的需求,从中根据名词找到对应需要设计的ADT,然后确定ADT内所需要的方法,设计方法的spec,做到测试优先编程,在写完接口以后就开始编写对应的测试用例。为了增强ADT的能力,还可以使用泛型技术。每个ADT都是immutable或mutable,确定ADT的具体实现所需要的rep,并写出表示不变性(rep invariant)、抽象过程(abstraction function)。 利用checkRep()保证始终不违反RI。
lab2让我学会了创立一个ADT的整个过程和面向对象技术,Java对基本语法概念的掌握和编程能力有所提高。理解了怎么做到测试优先编程。教训是对Java的一些基础语法和面向对象技术不是特别熟悉,需要多加练习。做到测试优先编程也有难度,刚刚拿到类的方法的specification没能快速掌握这些方法都是干什么的和如何使用,因此编写测试的详细代码时有些难以下手。对自己设计类里面的函数的specification理解不是很清楚,一开始没弄明白我自己设计的specification应该多严格才好。
3.1.2 Problem 1: Test Graph < String>
测试优先编程,测试Graph
-
测试Graph.empty()静态方法(只有一个实现),对于提供给我的测试代码可以保留原样。
-
为所有的实例方法编写测试策略和测试GraphInstanceTest.java,使用emptyInstance()方法得到空图,而不是Graph.empty()。
(1)test add method:
3.1.3 Graph < String>
3.1.3.1ConcreteEdgesGraph
测试优先编程(先完成测试再具体实现):继承Graph的测试策略,补充对于Edge类和ConcreteEdgesGraph的toString方法的测试。
一、*实现Edge类(immutable)*
Edge is immutable
\1. representation:
*2.RI、AF、Safety from rep exposure:*
// Abstraction function:
//AF(source,target,weight)=an edge from start to end with a positive weight
// Representation invariant:
//start and end not null not empty,weight>0
// Safety from rep exposure:
//start and end is private final,weight is int type, L is immutable.
//the getStart(),getEnd(),getWeight() return a immutable value.
*3.检查表示不变性:*
二、*实现ConcreteEdgesGraph类*
*1.实现Graph接口,representation:*
*2.RI(表示不变量)、AF、Safety from rep exposure*
(1)*Abstraction function:*
AF(vertices,edges)=weighted graph with directed edges,AF(vertices)=vertex in the graph,AF(edges)=edges in the graph and edges are the edges of the graph.
(2)*Representation invariant:* vertices don't contain same label,the edges' start and end label contains in vertices.The edge (from one vertex to another) no more than one,weight of the edge>0.vertices and edges don't contain null.
(3)*Safety from rep exposure:* vertices and edges field are private final,Edge is immutable,vertices and edges is mutable so vertices method need defensive copy.
3.检查表示不变性checkRep:
(2)set方法:
如果weight是负值,扔出RunTimeException异常,快速显示错误。
如果weight是正值,先在图中查找是否有从source到target的有向边。如果没有,创建这么一条边,权重是weight,向顶点集vertices中加入source和target,向边集edges加入这条边,return 0;如果有,对这条边调用getWeight()方法得到边的权值用于return,在edges中remove这条边,然后new Edge(source,target,weight)向edges中加入这个新对象。不能直接修改这条边的weight的原因是要求Edge是immutable,所以不可以改变Edge对象的值(和不能改变String对象一样),只能在edges中删除旧的边加入新的Edge对象。
如果weight是0,在edges中查找从source到target的边。如果存在,移出这条边并返回这条边的weight;如果不存在,直接return 0.
(3)remove方法:从点集vertices中删掉参数对应的点及点所连接的边。若不存在对应点,则返回false,否则返回true。
(4)vertices方法:返回顶点集合vertices。为防止representation泄露,需要进行defensive copy。
在调用每个方法返回前调用checkRep()检查是否维护了表示不变性。
(5)三个get方法:getLabel和getTargets和getAdjacency
public String getLabel(){
return label;//String is immutable so don't need defensive copy
}
public Map<String,Integer> getTargets(){
Map<String,Integer> ans=new HashMap<>();
return new HashMap<>(ans);//defensive copy
}
public Map<Vertex
return new HashMap<>(adjacency);//defensive copy
}
(6)Vertex类的toString方法:重载该类的toString方法。
![img](file:///D:\Temp\ksohtml32740\wps75.jpg)
*二、实现ConcreteVerticesGraph类*
\1. representation:
private final List<Vertex
\2. RI、AF、Safety from rep exposure :
Abstraction function:AF(vertices)=the graph which contains vertices as set of vertex and edges from vertices to.
Representation invariant: vertices contains all the vertex in the Vertex's adjacency field's key and vertices don't contain same element
Safety from rep exposure: vertices is private final and get Method make defensive copy
- 检查表示不变性:
3.1.4 *Problem 3: Implement generic* *Graph*
3.1.4.1 *Make the implementations generic*
使用泛型技术,使类不依赖于具体的String类,而能适用于任意类型L。将原来代码中的String类型替换为泛型的标识符L,并将Edge修改为Edge
3.1.5 *Problem 4: Poetic walks*
根据corpus生成一个GraphPoet图,图的每个顶点是语料中的一个单词,边代表前一个单词紧接着后一个单词,边的权重为前一个单词紧接着后一个单词的次数,单词不区分大小写,单词中没有空格和换行符。
For example, given this corpus: Hello, HELLO, hello, goodbye!
the graph would contain two edges:("hello,") -> ("hello,") with weight 2,("hello,") -> ("goodbye!") with weight 1。where the vertices represent case-insensitive "hello," and "goodbye!".
根据corpus建立图后,根据输入的句子,把相邻的单词对在图中进行检索,若句子的前后两单词w1→w2在单词图中隔着一个顶点b,则将b加入句子中,得到w1→b→w2。
w1与w2间只能间隔一个顶点,如果从w1到w2同时有两条路径w1→a→w2与w1→b→w2,则选择权重最高路径上的单词加入w1与w2之间。
输出的句子中原单词的大小写保持不变,加入的单词全用小写。
3.1.5.1 *Test* *GraphPoet*
测试策略:
2. RI、AF、Safety from rep exposure:
Abstraction function: AF(graph)=a PoetGraph made of the given corpus,graph's vertex is ths word of the corpus,and the edge of the graph represent from a word to another word
Representation invariant : vertices' label are non-empty non-null lowercase String of non-space non-newline characters
Safety from rep exposure: graph is private final and String is immutable so could return without defensive copy
\3. 检查表示不变性
3.2 Re-implement the Social Network in Lab1
本任务要求我们基于3.1的Graph
我选择ConcreteEdgesGraph用于实现FriendShip类。
3.2.1 FriendshipGraph类
测试优先编程:先设计FriendShip的测试用例。
按照FriendshipGraph方法的specification补充完善之前Lab1的测试