本次实验训练抽象数据类型(ADT)的设计、规约、测试,并使用面向对象 编程(OOP)技术实现 ADT。具体来说
- 针对给定的应用问题,从问题描述中识别所需的 ADT;
- 设计 ADT 规约(pre-condition、post-condition)并评估规约的质量;
- 根据 ADT 的规约设计测试用例;
- ADT 的泛型化
- 根据规约设计 ADT 的多种不同的实现;针对每种实现,设计其表示 (representation)、表示不变性(rep invariant)、抽象过程(abstraction function)
- 使用 OOP 实现 ADT,并判定表示不变性是否违反、各实现是否存在表 示泄露(rep exposure);
- 测试 ADT 的实现并评估测试的覆盖度;
- 使用 ADT 及其实现,为应用问题开发程序;
- 在测试代码中,能够写出 testing strategy 并据此设计测试用例。
实验环境:
- 系统:windows10,JDK8
- ide:Eclipse IDE for Eclipse Committers 2018-12 (4.10.0)
- 版本管理:git
- 代码托管:Github
配置过程
安装在 Eclipse IDE 中安装配置 EclEmma
在这里给出你的GitHub Lab2仓库的URL地址(Lab2-学号)。
https://github.com/ComputerScienceHIT/Lab2-1170300527
请仔细对照实验手册,针对三个问题中的每一项任务,在下面各节中记录你的实验过程、阐述你的设计思路和问题求解思路,可辅之以示意图或关键源代码加以说明(但千万不要把你的源代码全部粘贴过来!)。
通过接口实现对Graph的出路,得到对文件中各单词间的关系,进而对输入的诗进行润色
使用git clone获取实验代码,同样使用git clone将github上的仓库同步到自己的电脑上
-
-
- Problem 1: Test Graph <String>
-
本问题以测试优先的原则先编写测试用例。
所有静态方法的测试都在GraphStaticTest.java中,实例方法的测试在GraphInstanceTest.java中。
GraphInstanceTest是一个抽象类,针对Graph的不同的实现类需要编写具体的测试类,都需要继承自GraphInstanceTest类。
在graph的接口的spec中,各个方法的precondition和postcondition都已给出,可以依据其编写测试用例
-
-
- Problem 2: Implement Graph <String>
-
分别按要求实现ConcreteEdgesGraph和ConcreteVerticesGraph,其反别继承了Graph类,根据spec对其反别实现,其中ConcreteEdgesGraph的Edge要求是不可变数据类型,ConcreteVerticesGraph的Vertex是可变数据类型
-
-
-
- Implement ConcreteEdgesGraph
-
-
首先是对Edge属性的定义:
private final String | source(起始点) |
private final String | target(终止点) |
private final int | weight(权值) |
对edge方法的定义
public Edge | 构造方法 |
public String getSource() | 返回起始点 |
public String getTarget() | 返回终止点 |
public int getWeight() | 返回权值 |
public String toString() | 输出string |
private void checkRep() | 检查RI |
ConcreteEdgesGraph继承了Graph的接口,根据其spec实现接口的各个方法,在每次改变数据之后要进行checkRep检查RI,并且在remove操作时不只要remove顶点集还要将含有该顶点的边一同remove掉
注意!debug了半天,在remove方法中在迭代过程中如果修改的话会抛出异常,应该调用iterator.remove()方法。。。。。。
-
-
-
- Implement ConcreteVerticesGraph
-
-
ConcreteVerticesGraph中只有一个属性vertices,故实现vertex时要使其包括顶点和边的集合
Vertex的属性:
String vertex; | 顶点 |
Map<String,Integer> | 该点的为起始点的边的map |
Vertex的方法
private void checkRep() | 检查RI |
public Vertex | 构造方法 |
public String getVertex() | 返回顶点 |
public Map<String, Integer> getMap() | 返回该点为起始点的边的map |
public void setEdge | 加入一条边 |
public void removeEdge | 删除边 |
public String toString() | 输出边的string |
其中map中的key为边的终点,value为边的权值,以类似邻接表的方式存储。
ConcreteVerticesGraph中的方法则为Graph中接口的实例,根据接口的spec立用设计的Vertex实现各个方法
-
-
- Problem 3: Implement generic Graph<L>
-
之前实现的是string类型的不具有通用性,故此问将其改为泛型
将声明改为
public class ConcreteEdgesGraph<L> implements Graph<L>
public class ConcreteVerticesGraph<L> implements Graph<L>
class Edge<L>
class Vertex<L>
将原方法中涉及到的操作都换成L
-
-
-
- Implement Graph.empty()
-
-
实现Graph中的静态方法empty方法,因为Grap是接口不能实例化所以选择实现的两个中的一个即可,我选择的是
public static <L> Graph<L> empty() {
Graph<L> graph = new ConcreteEdgesGraph<L>();
return graph;
}
使用上面建立的结构对输入的文本进行润色
-
-
-
- Test GraphPoet
-
-
根据接口的spec对GraphPoet编写测试用例
-
-
-
- Implement GraphPoet
-
-
public GraphPoet(File corpus) throws IOException:
通过输入的文本语料库立用之前实现的图建立各单词间的关系,因为要求是不区分大小写,要对输入的单词全部转化为小写
public String poem(String input) :
在上个方法中已经得到了各单词间的关系图,在此方法中根据关系图进行对输入的润色,首先因为是不区分大小写的建立一个新的字符串将其全部转化为小写便于与边关系中的匹配,对其进行分割,逐个进行比较,取其中权值最大的边将单词加入
该问题要求修改main()方法,使用不同的输入对程序进行测试,也可以自定义语料库。
请按照http://web.mit.edu/6.031/www/sp17/psets/ps2/#before_youre_done的说明,检查你的程序。
如何通过Git提交当前版本到GitHub上你的Lab2仓库。
在这里给出你的项目的目录结构树状示意图。
├── src
│ └── P1
│ ├── graph
│ │ ├── ConcreteEdgesGraph.java
│ │ ├── ConcreteVerticesGraph.java
│ │ └── Graph.java
│ └── poet
│ ├── GraphPoet.java
│ ├── Main.java
│ └── mugar-omni-theater.txt
└── test
└── P1
├── graph
│ ├── ConcreteEdgesGraphTest.java
│ ├── ConcreteVerticesGraphTest.java
│ ├── GraphInstanceTest.java
│ └── GraphStaticTest.java
└── poet
└── GraphPoetTest.java
利用上一题中完成的图结构重写Lab1中的社交网路
选取了上一问中的ConcreteEdgesGraph使FriendshipGraph继承他,其中的addVertex方法与addEdge方法可以借助ConcreteEdgesGraph中的add和set方法实现,addEdge更是可以直接调用set即可,需要注意的是,addVertex是要判断两个人名是否不同,这是之前的add方法中没有的
主要点在于getDistance方法,这是ConcreteEdgesGraph中没有的,但其与Lab1中的结构类似只需对Lab1中进行改变一部分即可,但由于lab1中的邻接表无边的位置为0而该结构无边的位置为空,若是直接复用会发生空指针问题。
与lab1中完全相同,只有属性name,只有构造方法,getName方法,并重写了equals方法
-
-
- 客户端main()
-
使用lab1中的客户端代码
使用了lab1中的测试用例
-
-
- 提交至Git仓库
-
如何通过Git提交当前版本到GitHub上你的Lab3仓库。
在这里给出你的项目的目录结构树状示意图。
├── src
│ ├── P1
│ │ ├── graph
│ │ │ ├── ConcreteEdgesGraph.java
│ │ │ ├── ConcreteVerticesGraph.java
│ │ │ └── Graph.java
│ │ └── poet
│ │ ├── GraphPoet.java
│ │ ├── Main.java
│ │ └── mugar-omni-theater.txt
│ └── P2
│ ├── FriendshipGraph.java
│ └── Person.java
└── test
├── P1
│ ├── graph
│ │ ├── ConcreteEdgesGraphTest.java
│ │ ├── ConcreteVerticesGraphTest.java
│ │ ├── GraphInstanceTest.java
│ │ └── GraphStaticTest.java
│ └── poet
│ └── GraphPoetTest.java
└── P2
└── FriendshipGraphTest.java
-
- Playing Chess
- ADT设计/实现方案
- Playing Chess
设计了哪些ADT(接口、类),各自的rep和实现,各自的mutability/ immutability说明、AF、RI、safety from rep exposure。
必要时请使用UML class diagram(请自学)描述你设计的各ADT间的关系。
Action接口:对玩家行为的抽象
Board类:棋盘,根据输入的go或chess创建棋盘,mutable
// Abstraction function:
// TODO position represent the position of board
// TODO choice represet go or chess
// Representation invariant:
// TODO psitions is mutable and choice can't be null
// TODO sharing copies, immutable,so do not need to worry
Game类:对一局游戏,包括两名玩家,棋盘,下棋步骤,实例化Action
// Abstraction function:
// TODO player1 and player2 represent two player board represent the go board or chess board
// Representation invariant:
// TODO players and board can't be null
// Safety from rep exposure
// TODO all fields are private
// TODO board so make defensive copies to avoid
// TODO sharing player immutable,so donnot need to worry
Piece类:对棋子的,包括颜色,名字 immutable
// Abstraction function:
// TODO name and color represent the piece's attribute
// Representation invariant:
// TODO name and color can't be null
// Safety from rep exposure
// TODO all fields are private
// TODO sharing name and color immutable,so donnot need to worry
Player类:对玩家的,包括玩家,所使棋子颜色 immutable
// Abstraction function:
// TODO name and color represent the player's attribute
// Representation invariant:
// TODO name and color can't be null
// Safety from rep exposure
// TODO all fields are private
// TODO sharing name and color immutable,so donnot need to worry
Position类:描述了棋盘上的一个位置包括坐标,棋子 mutable
// Abstraction function:
// TODO x,y and piece represent the position's attribute
// Representation invariant:
// TODO x,y can't be null
// Safety from rep exposure
// TODO x and y are private
// TODO piece is mutable so make defensive copies to avoid
// TODO sharing x and y immutable,so donnot need to worry
-
-
- 主程序MyChessAndGoGame设计/实现方案
-
辅之以执行过程的截图,介绍主程序的设计和实现方案,特别是如何将用户在命令行输入的指令映射到各ADT的具体方法的执行。
首先输入用户名称,然后通过输入选择棋类操作进行游戏的初始化进入不同的命令,分别对go和chess进行处理
通过swith语句判断用户输入的命令,尽可能简化用户的输入,输入的不同命令对应执行ADT不同的操作
-
-
- ADT和主程序的测试方案
-
介绍针对各ADT的各方法的测试方案和testing strategy。
介绍你如何对该应用进行测试用例的设计,以及具体的测试过程。
对于piece,player,position只有基本的构造方法,action只是接口且在game中进行了实例话所以并没有对其进行单独编写测试用例
在GameTest中对落子,移子,提子,吃子分别进行测试;台BoardTest中对setPositions,getCount进行了测试尽可能对各种情况都要测试到
对各种越界情况也要