3.1.1 Get the code and prepare Git repository
3.1.2 Problem 1: Test Graph <String>
3.1.3 Problem 2: Implement Graph <String>
3.1.3.1 Implement ConcreteEdgesGraph
3.1.3.2 Implement ConcreteVerticesGraph
3.1.4 Problem 3: Implement generic Graph<L>
3.1.4.1 Make the implementations generic
3.1.4.2 Implement Graph.empty()
本次实验训练抽象数据类型(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 并据此设计测试用例。
实验环境配置:大体上与Lab1相同,包括JDK11与Junit4,除此之外我还需要在IDEA中配置Code Coverage for Java,用来检查我们测试的覆盖率,社区版(我使用的是社区版)IDAE自带Code Coverage for Java插件,只能选择使用或者禁用,不能卸载,如图
请仔细对照实验手册,针对两个问题中的每一项任务,在下面各节中记录你的实验过程、阐述你的设计思路和问题求解思路,可辅之以示意图或关键源代码加以说明(但千万不要把你的源代码全部粘贴过来!)。
这个任务的目的是完善并使用一个图的模块,需要我们完善Graph接口类,实现Graph类中的方法,包括:add,set,remove,vertices,sources,targets,最后实现GraphPoet类。最后这个类是从输入的文本的两个单词之间如果存在桥接词,就将该桥接词插入,如果有多个则选取权重较大的(如果有多个并列,则随机)。
在Git Bash中使用命令git clone + URL地址,从老师那里克隆代码
Git clone https://classroom.github.com/a/NL2TjK2z
以下各部分,请按照MIT页面上相应部分的要求,逐项列出你的设计和实现思路/过程/结果。
思路:这是针对Graph<String>设计相应的测试策略,主要针对里面的每个方法进行等价类划分的测试。
过程:如图:
结果:
我将所有的方法测试放入到一个覆盖率报告中,所以没有了单个方法的覆盖率,下同,我生成了一个覆盖率的报告文档,是一个html文件,在目录test\P1\graph下,是对这个包中所有方法的测试报告,文件名为index.heml,从报告中可以看出在我这个包中的类的覆盖率达到了百分之80,方法覆盖百分之97.4,行覆盖百分之98.6,总体上看覆盖率比较高。
以下各部分,请按照MIT页面上相应部分的要求,逐项列出你的设计和实现思路/过程/结果。
- Edge中应该包括边的权重,边的起始顶点和目标顶点,防止内存泄漏,所以将其设置为private
- Edge中所实现的方法为:
Edge类 | 初始化边的起始顶点和目标顶点以及权重 |
checkRep | 检查表示不变性:边的权重大于等于0 |
getsource | 返回一个起始顶点 |
gettarget | 返回一个目标顶点 |
getweight | 返回边的权重 |
toString | 返回一条边的字符串:“起始顶点->目标顶点权重为xx” |
- AF,RI和防止内存泄漏
- 测试方法:
- 实现ConcreteEdgesGraph类
- 这个类中包括边表list和顶点表set
- 实现的方法有:
ConcreteEdgesGraph | |
checkRep | 检查表示不变性:边的长度为大于0的数且有起始顶点 |
add | 添加一个顶点到顶点集合中 |
set | 参数为source,target,weight,边存在且权重为正,则返回原来的权重;边不存在且权重为正,则返回0;权重为负数,则返回-1 |
remove | 删除一个顶点和与之相关的边,遍历Edges,运用迭代器寻找是否以这个点为起始顶点或者目标顶点 |
vertices | 返回所有顶点的集合 |
sources | 输入一个目标顶点,返回和他相连的所有的边和起始顶点构成的集合 |
targets | 输入一个起始顶点,返回和他相连的所有的边和目标顶点构成的集合 |
toString | 将图中所有的点转化为一条可以输出的字符串 |
- AF,RI,防止内存泄漏:
- 测试方法:
对toString进行测试,其余直接继承Graph测试:
测试结果:
我生成了一个覆盖率的报告文档,是一个html文件,在目录test\P1\graph下,是对这个包中所有方法的测试报告,文件名为index.heml,从报告中可以看出在我这个包中的类的覆盖率达到了百分之80,方法覆盖百分之97.4,行覆盖百分之98.6,总体上看覆盖率比较高。
- 这个类包含顶点的名字,起始顶点的集合以及目标顶点的集合
- 实现的方法:
Vertex | 用顶点的名字创建顶点表 |
checkRep | 检查表示不变性:边的权重大于0 |
getmark | 返回顶点的名字 |
getsource | 返回能到达这个顶点的所有的点和边的集合 |
gettarget | 返回这个顶点能到达的所有顶点和边的集合 |
addsource | 在起始顶点集合中加入一个起始顶点,如果权重大于0且顶点已经存在,则返回原来的权重;如果权重大于0且顶点不存在,则返回0;如果权重等于0,则移除这个顶点 |
addtarget | 在目标顶点集合中加入一个目标顶点,如果权重大于0且顶点已经存在,则返回原来的权重;如果权重大于0且顶点不存在,则返回0;如果权重等于,则移除这个顶点 |
removesource | 在起始顶点集合中删除一个起始顶点,并且返回原来的权重 |
removetarget | 在目标顶点集合中删除一个目标顶点,并且返回原来的权重 |
toString | 得到一个顶点的字符串表示 |
- AF,RI和防止内存泄漏
- 测试方法:
- ConcreteVerticesGraph类
- 顶点构成的集合
- 实现的方法:
ConcreteVerticesGraph | |
checkRep | 检查表示不变性:顶点集合中不应该有重复的顶点 |
add | 添加一个顶点到顶点集合中 |
set | 参数source,target,weight,如果边存在且权重大于0,则返回原来的权重;如果边不存在且权重大于0,则返回0;如果权重为负数,则返回-1 |
remove | 删除一个顶点和与之相关的边,使用迭代器遍历Vertex在起始顶点集合和目标顶点集合中寻找是否有重复的顶点 |
vertices | 所有顶点的集合 |
sources | 输入一个起始顶点,返回与他相连的所有边和起始顶点构成的集合 |
targets | 输入一个目标顶点,返回与他相连的所有边和目标顶点构成的集合 |
toString | 将图转换成一条可以输出的字符串 |
- AF,RI和防止内存泄露
- 测试方法:
对toString进行测试,继承Graph的测试:
将String改为泛型实现
具体实现:
测试方法:
测试结果:
我生成了一个覆盖率的报告文档,是一个html文件,在目录test\P1\graph下,是对这个包中所有方法的测试报告,文件名为index.heml,从报告中可以看出在我这个包中的类的覆盖率达到了百分之80,方法覆盖百分之97.4,行覆盖百分之98.6,总体上看覆盖率比较高。
任务要求我们实现一个类,利用之前实现的图结构,能够将语料库转化为该种图结构,并且在图中搜索,完成对输入的诗句的句子进行扩充。
测试方法:
具体实现:
测试结果:
我生成了一个覆盖率的报告文档,是一个html文件,在目录test\P1\graph下,是对这个包中所有方法的测试报告,文件名为index.heml,从报告中可以看出在我这个包中的类的覆盖率达到了百分之80,方法覆盖百分之97.4,行覆盖百分之98.6,总体上看覆盖率比较高。
- 实现方法:
GraphPoet | 按行读入文件,放在list中,每次取出相邻的元素,在图中加入新的边 |
checkRep | 检查表示不变性 |
poem | 输入需要扩充的字符串,当前单词为source,下一个单词为target,找其中权重最大的加入其之间
|
toString | 调用ConcreteEdgesGraph中toString方法,转化成字符串输出 |
利用toString进行输出:
main函数中运行结果:
请按照http://web.mit.edu/6.031/www/sp17/psets/ps2/#before_youre_done的说明,检查你的程序。
如何通过Git提交当前版本到GitHub上你的Lab2仓库。
之前传上去忘记截图了
在这里给出你的项目的目录结构树状示意图。
我后来添加了覆盖率的生成报告,所以这里的截图缺少了index.html文件,但是我会将Index.html文件一并传到gitHub上去
这次实验要求我们基于Poetic Walks中定义的Graph<L>及其两种实现(在这里我所使用的是ConcreteEdgesGraph<L>),实现Lab1中Social NetWorek中的各种功能,并且尽可能复用ConcreteEdgesGraph<L>中已经实现的方法,然后运行提供的main()和执行Lab1中的Junit测试用例,使之正常运行。
(1)将FriendshipGraph中的ConcreteEdgesGraph的L改为Person,并设置为私有
(2)FriendshipGraph中所实现的方法有:
FriendshipGraph | |
addVertex | 在一个图中增加新的人,需要调用ConcreteEdgesGraph中的add
|
addEdge | 为一个人增加一个新的朋友,a表示某个人,b表示他的朋友,需要调用ConcreteEdgesGraph中的set
|
getallPeople | 直接将这个图返回
|
getDistance | 得到两个人之间的最短距离,定义一个Person队列myqueue用来存储先广搜索的遍历结果,定义一个Map集合route用来存储先广搜索的所有元素与第一个元素之间的距离。首先将a入队,并且把a和第一个下标0放入集合,当队列非空时弹出队首元素top,并且得到top在route中的下标distance,定义一个Map为friend,执行personGraph.targets(top)得到队首元素的所有朋友的集合,定义一个Set为allfriend,对friend执行KeySet得到allfriend,只要allfriend中的元素与b不同,就将这些元素全部入队,并且把这些元素极其下标distance+1放入到集合中,只要队列非空,循环执行上述步骤,知道找到某个元素与b相同,并且返回这个元素在route中的下标,如果队列为空还未找到,则返回-1
|
main | 实现Lab1中实验指导的客户端
|
- AF,RI和防止表示泄露:
- Person中所实现的方法:
Person | 构造方法 |
Person | 将没有重复的名字加入 |
getmyname | 返回这个人的名字 |
- AF,RI和防止表示泄露:
按照实验一中的实验指导所阐述的社交网络图构建一个客户端
测试策略:与实验一中进行的测试相同
测试结果:
从测试结果来看覆盖率比较高
如何通过Git提交当前版本到GitHub上你的Lab2仓库。
在这里给出你的项目的目录结构树状示意图。