2022年春季学期
计算学部《软件构造》课程
Lab 2实验报告
姓名 | 赵誉泽 |
学号 | 120L020310 |
班号 | 2003003 |
电子邮件 | 2839366160@qq.com |
手机号码 | 18317069040 |
1 实验目标概述······································································ 1
2 实验环境配置······································································ 1
3 实验过程················································································ 1
3.1 Poetic Walks·································································· 1
3.1.1 Get the code and prepare Git repository······ 1
3.1.2 Problem 1: Test Graph <String>············ 1
3.1.3 Problem 2: Implement Graph <String> 1
3.1.3.1 Implement ConcreteEdgesGraph······························ 2
3.1.3.2 Implement ConcreteVerticesGraph······················· 2
3.1.4 Problem 3: Implement generic Graph<L>· 2
3.1.4.2 Implement Graph.empty()········ 2
3.1.5 Problem 4: Poetic walks···································· 2
3.1.5.1 Test GraphPoet······························ 2
3.1.5.2 Implement GraphPoet·················· 2
3.1.5.3 Graph poetry slam··························· 2
3.1.6 Before you’re done············································· 2
3.2 Re-implement the Social Network in Lab1········· 2
3.2.1 FriendshipGraph类···································· 2
3.2.2 Person类···························································· 3
3.2.3 客户端main()·················································· 3
3.2.4 测试用例······························································· 3
3.2.5 提交至Git仓库················································· 3
4 实验进度记录······································································ 3
5 实验过程中遇到的困难与解决途径·························· 3
6 实验过程中收获的经验、教训、感想····················· 4
6.1 实验过程中收获的经验和教训··························· 4
6.2 针对以下方面的感受··············································· 4
本次实验训练抽象数据类型(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并据此设计测试用例。
使用idea,右上角自带覆盖率测试。
GitHub Lab2仓库的URL地址:https://github.com/ComputerScienceHIT/HIT-Lab2-120L020310
请仔细对照实验手册,针对两个问题中的每一项任务,在下面各节中记录你的实验过程、阐述你的设计思路和问题求解思路,可辅之以示意图或关键源代码加以说明(但千万不要把你的源代码全部粘贴过来!)。
该任务主要是实验一个图的类的创建,并应用于poet。
- 完成Graph接口类,将String拓展为泛型L类,实现vertices,edges,ConcreteEdgesGraph,ConcreteVerticesGraph四个类的各种方法和属性;
- 利用实现的Graph类,应用图的思想,实现GraphPoet类,如果输入的文本的两个单词之间存在桥接词,则插入该桥接词;若存在多个单一桥接词,则选取边权重较大者。
进入如下网址:https://github.com/rainywang/Spring2021_HITCS_SC_Lab2/tree/master/P1,下载zip文件即可。
-
-
- Problem 1: Test Graph <String>
-
首先,测试静态方法生成String类型的Graph。
-
-
- Problem 2: Implement Graph <String>
-
以下各部分,请按照MIT页面上相应部分的要求,逐项列出你的设计和实现思路/过程/结果。
-
-
-
- Implement ConcreteEdgesGraph
-
-
首先实现edge类。Edge的功能主要为存储边的3个信息,即发出边的顶点source,边指向的顶点target,以及边的权值。其中,权值需要大于0。
分别设计了chechkRep,add,set,remove方法进行生产graph操作,此外,设计了vertices,source,target方法得到顶点,边的集合。
测试截图
-
-
-
- Implement ConcreteVerticesGraph
-
-
测试截图
选择“String”并更改所有匹配项,即可实现泛化类型。
-
-
-
- Implement Graph.empty()
-
-
使Graph.empty()能返回一个新的空instance。代码如下:
public static Graph<String> empty() {
return new ConcreteEdgesGraph();
}
我们需要根据corpus中的文本,生成一个图来存放单词,然后给定一个输入,在图中搜索词之间的关系,自动补全语句中可能可以完善的部分。
-
-
-
- Test GraphPoet
-
-
在基于预设的测试用例基础上,增加等价类划分的多种情况,即两个单词之间不存在连接词,两个单词之间只有一个连接词,两个单词之间有多个连接词时的不同情况。
-
-
-
- Implement GraphPoet
-
-
首先我们需要确保所有的点都不为空。
接下来我们构造函数。首先用文件读取来输入单词,split()切片函数分割为数组,通过String.toLowerCase()全部小写。
然后创建图,即相邻的单词加边。首先要在加边前通过Graph.add()加点,同时加边时要判断是否存在。
使用自带的样例“This is a test of the Mugar Omni Theater sound system.”进行测试,测试成功。
测试通过
请按照Problem Set 2: Poetic Walks的说明,检查你的程序。
如何通过Git提交当前版本到GitHub上你的Lab2仓库。
在这里给出你的项目的目录结构树状示意图。
在这里简要概述你对该任务的理解。
首先我们可以直接调用Graph.empty()静态方法生成一个空的图,构建方法int addVertex()来调用添加点,构建方法int getDistance()来得到两点之间最短距离。
getDistance方法首先判断起止点是否相等。若不相等,则新建Map<Person, Integer> dis表示从起始点开始到该Person的距离,以及List<Person> viited表示该Person是否访问过。初始化后,把起点标记为已经访问。然后开始BFS搜索,找到终点为止。
-
-
- Person类
-
该类使得每一个人的个体对应到一个Person对象,其对象存储名字的信息。为了安全性考虑,String Name设置为私有且不可变的。并且设计了构造函数,在构造函数中将Name初始化。
-
-
- 客户端main()
-
设计代码如下:
public class FriendshipGraphTest {
/**
* Basic Network Test
*/
@Test
public void Test1() {
final FriendshipGraph graph = new FriendshipGraph();
final Person rachel = new Person("Rachel");
final Person ross = new Person("Ross");
final Person ben = new Person("Ben");
final Person kramer = new Person("Kramer");
assertEquals(true, graph.addVertex(rachel));
assertEquals(true, graph.addVertex(ross));
assertEquals(true, graph.addVertex(ben));
assertEquals(true, graph.addVertex(kramer));
assertEquals(0, graph.addEdge(rachel, ross));
assertEquals(1, graph.addEdge(ross, rachel));
assertEquals(0, graph.addEdge(ross, ben));
assertEquals(1, graph.addEdge(ben, ross));
assertEquals(1, graph.getDistance(rachel, ross));
assertEquals(2, graph.getDistance(rachel, ben));
assertEquals(0, graph.getDistance(rachel, rachel));
assertEquals(-1, graph.getDistance(rachel, kramer));
}
/**
* Further Test
*/
@Test
public void Test2() {
final FriendshipGraph graph = new FriendshipGraph();
final Person a = new Person("A");
final Person b = new Person("B");
final Person c = new Person("C");
final Person d = new Person("D");
assertEquals(true, graph.addVertex(a));
assertEquals(true, graph.addVertex(b));
assertEquals(true, graph.addVertex(c));
assertEquals(true, graph.addVertex(d));
assertEquals(0, graph.addEdge(a, b));
assertEquals(0, graph.addEdge(a, d));
assertEquals(0, graph.addEdge(b, d));
assertEquals(0, graph.addEdge(c, d));
assertEquals(1, graph.getDistance(a, d));
assertEquals(2, graph.getDistance(c, b));
}
}
根据lab1中给出的社交网络示例
分别测试:
- Rachel和Ross距离是1,Rachel和Ben距离是2
- Rachel和Rachel距离是0
Rachel和Kramer距离是-1
-
-
- 提交至Git仓库
-
用idea自带的VES工具提交到github库。
请使用表格方式记录你的进度情况,以超过半小时的连续编程时间为一行。
每次结束编程时,请向该表格中增加一行。不要事后胡乱填写。
不要嫌烦,该表格可帮助你汇总你在每个任务上付出的时间和精力,发现自己不擅长的任务,后续有意识的弥补。
日期 | 时间段 | 计划任务 | 实际完成情况 |
2022-05-22 | 15:30-17:30 | 总览代码,修改参数完成静态检测 | 完成 |
2022-05-22 | 19:30-20:30 | 设计ConcreteEdgsGraph类 | 未按计划完成 |
2022-05-23 | 8:00-11:40 | 设计ConcreteEdgsGraph类 | 按计划完成 |
14:00-17:00 | 为ConcreteEdgsGraph类设计测试类 | 按计划完成 | |
2022-05-24 | 18:30-22:30 | 设计ConcreteVerticesGraph类 | 未按计划完成 |
2022-05-25 | 8:00-11:00 | 设计ConcreteVerticesGraph类 | 按计划完成 |
2022-05-25 | 15:00-17:00 | 为ConcreteVerticesGraph类设计测试类 | 未按计划完成 |
2022-05-25 | 19:00-21:00 | 为ConcreteVerticesGraph类设计测试类 | 按计划完成 |
2022-05-26 | 8:00-11:00 | 设计GraphInstanceTest类 | 未按计划完成 |
2022-05-26 | 18:00-22:00 | 设计GraphInstanceTest类 | 按计划完成 |
2022-05-26 | 8:00-11:00 | 设计GraphPoet类 | 按计划完成 |
2022-05-26 | 18:00-23:00 | 设计Person和FriendshipGraph类 | 按计划完成 |
- 实验过程中遇到的困难与解决途径
遇到的难点 | 解决途径 |
题目要求在英文原网页下没太看懂,没能理解实验目的 | 查阅资料,询问同学 |
ConcreteEdgsGraph类和ConcreteVerticesGraph类设计过程,对数据结构图的使用生疏 | 借鉴过去数据结构中c语言的图的创建与修改方法,在java语言中重新实现。 |
For循环下map的直接remove方法不能真正删除键值对 | 用迭代器Iterator的remove方法来删除map中不需要的信息。 |
- 面向ADT的编程和直接面向应用场景编程,你体会到二者有何差异?
面向ADT需要更多的整体设计思想,构建整体框架,相较于直接面向应用场景编程需要更多的时间与精力,但应用性更强。
- 使用泛型和不使用泛型的编程,对你来说有何差异?
使用泛型能更好地兼容不同类型的数据。
- 在给出ADT的规约后就开始编写测试用例,优势是什么?你是否能够适应这种测试方式?
优势是可以直接面向规约建立测试用例,更体系化,能适应。
- P1设计的ADT在多个应用场景下使用,这种复用带来什么好处?
可移植性,可拓展性。
- 为ADT撰写specification, invariants, RI, AF,时刻注意ADT是否有rep exposure,这些工作的意义是什么?你是否愿意在以后编程中坚持这么做?
保证数据结构的安全性,防止出现意料之外的错误或受到恶意攻击。愿意坚持。
- 关于本实验的工作量、难度、deadline。
工作量较大,难得适中,但是deadline和考试重合,时间十分紧张。
- 《软件构造》课程进展到目前,你对该课程有何体会和建议?
感觉到了软件设计的复杂过程以及精细化程度。