2022年春季学期
计算学部《软件构造》课程
Lab 2实验报告
姓名 | |
学号 | |
班号 | |
电子邮件 | |
手机号码 |
本次实验训练抽象数据类型(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 并据此设计测试用例。
2.实验环境配置
本次实验基于Windows64位,JDK11、IDEA
还需要插件Code Coverage for Java
在这里给出你的GitHub Lab2仓库的URL地址(Lab2-学号)。
请仔细对照实验手册,针对两个问题中的每一项任务,在下面各节中记录你的实验过程、阐述你的设计思路和问题求解思路,可辅之以示意图或关键源代码加以说明(但千万不要把你的源代码全部粘贴过来!)。
这个实验的主要目的是测试 ADT 的规约设计和 ADT 的多种不同的实现,并练习测试优先的编程,在后面练习 ADT 的泛型化。
-
-
- Get the code and prepare Git repository
-
从实验指导PPT中给的网址找到任务代码
获取到实验代码后,在IDEA中为Lab2创建git,之后先将源代码进行提交
-
-
- Problem 1: Test Graph <String>
-
在 GraphInstanceTest.java 中为所有实例方法编写测试策略和测试。
依次对Graph.java中的方法设计测试,尽可能多的覆盖到之后有可能实现的代码,测试策略如下:
-
-
- Problem 2: Implement Graph <String>
-
以下各部分,请按照MIT页面上相应部分的要求,逐项列出你的设计和实现思路/过程/结果。
-
-
-
- Implement ConcreteEdgesGraph
-
-
Edge类的设计,成员变量如下:
在EDGE中需要实现的方法如下图所示:
Edge | 初始化构造方法,初始化新边的两个点和边的权值 |
checkRep | 检查起止点不为空,边长权值非负 |
source | 返回边的源点 |
target | 返回边的目标点 |
weight | 返回边的权重 |
toString | 返回一条边的字符串,形式为“起点--权重->终点” |
changeweight | 改变一条边的权重。 |
AF,RI,Safety from rep exposure:
Testing strategy for Edge
对Edge类的每个方法进行测试,分别测试Edge,source,target,changeweight,weight,toString.
部分代码如下:
ConcreteEdgesGraph类的设计
成员变量和成员函数如图所示:
函数均为Graph.java中要求完成的方法,此处不再赘述
AF,RI,Safety from rep exposure:
实现ConcreteEdgesGraph类和它的测试
部分的代码如下:
运行测试:
覆盖率测试:
-
-
-
- Implement ConcreteVerticesGraph
-
-
Edge类的设计,成员变量如下:
Vertex类的成员函数包括:
Vertex | 含参构造函数,public Vertex(final String name) |
checkRep | 检查权值非负,点名字不为空,起止点不能相同 |
getName | 获取顶点名称 |
getSources | 获取以顶点为目标点对应的源点和边权重组成的map |
setSources | 设置以顶点为目标点对应的边 |
setTargets | 设置以顶点为源点对应的边 |
totargetString | 按指定格式打印targets的map |
toString | 按指定格式打印 |
getTargets | 获取以顶点为源点对应的目标点和边权重组成的map |
类的UML图如下图所示:
AF,RI,Safety from rep exposure:
Testing strategy for Vertex:
实现Vertex类和它的测试,部分代码如图所示:
ConcreteVerticesGraph类的设计
UML图如下:
AF,RI,Safety from rep exposure:
实现ConcreteVerticesGraph类和它的测试,部分代码截图如下:
运行测试:
测试覆盖:
将ConcreteEdgesGraph和ConcreteVerticesGraph都用泛型实现,依照IEDA的报错一步一步进行修改,将其全部改为泛型。之后重新跑测试
-
-
-
- Implement Graph.empty()
-
-
调用一个具体的实现:
任务要求我们实现一个类,利用之前实现的图结构,用给的语料生成图,相邻的单词间用一条有向边连接,之后给定一个输入字符串,通过在图中判断它们之间是否有bridge来对字符串进行扩充。
-
-
-
- Test GraphPoet
-
-
Testing strategy:
-
-
-
- Implement GraphPoet
-
-
成员变量如下:
成员函数如下:
GraphPoet | 输入文件的路径,一行一行读入,按空格进行切割,然后每次取相邻的元素,在图中添加新的点,添加新的边。 |
checkRep | 保证图中的顶点名字不为空格,同样也不为大写字母 |
poem | 寻两点间的bridge,当有多个符合要求的节点时,要选择权值大的。返回扩充后的字符串 |
toString | 调用ConcreteVertexGraph中的toString方法,将整个图中所有点的指向转化为一条字符串输出 |
AF,RI,Safety from rep exposure:
部分代码截图如下:
测试结果:
测试覆盖:
语料库为一首小诗:
Rain is falling all around
It falls on field and tree
It rains on the umbrella here
And on the ships at sea
输入为:
Rain falling around It on and tree
输出为:
Rain is falling all around It falls on field and tree
请按照http://web.mit.edu/6.031/www/sp17/psets/ps2/#before_youre_done的说明,检查你的程序。
如何通过Git提交当前版本到GitHub上你的Lab2仓库。
在这里给出你的项目的目录结构树状示意图。
这个任务主要是重新实现 Lab1 中的 Social Network,利用在P1中已经写好的接口来实现,尽量重用已有的函数。
-
-
- FriendshipGraph类
-
FriendshipGraph类的设计,成员变量如下:
FriendshipGraph类的成员函数包括:
addVertex | 向图中加边 |
addEdge | 向图中加点 |
getDistence | 计算两点间的最短距离 |
getGraph | 将图返回 |
类的UML图如下图所示:
部分代码如下:
-
-
- Person类
-
Person类的设计,成员变量如下:
FriendshipGraph类的成员函数包括:
一个构造函数,输入一个Sting 名字
一个getPerson返回该person的名字。
类的UML图如下图所示:
部分代码如下:
-
-
- 客户端main()
-
利用 Lab1 中已有的 main 客户端
测试策略主要是根据 FriendshipGraph 中的图的类型进行测试,为其中所有方法进行测试。
覆盖率测试如下图所示:
-
-
- 提交至Git仓库
-
如何通过Git提交当前版本到GitHub上你的Lab2仓库。
在这里给出你的项目的目录结构树状示意图。
请使用表格方式记录你的进度情况,以超过半小时的连续编程时间为一行。
每次结束编程时,请向该表格中增加一行。不要事后胡乱填写。
不要嫌烦,该表格可帮助你汇总你在每个任务上付出的时间和精力,发现自己不擅长的任务,后续有意识的弥补。
日期 | 时间段 | 计划任务 | 实际完成情况 |
5/20 | 16:00-20:00 | 完成测试的编写 | 按时完成 |
5/21 | 18:00-21:00 | 完成ConcreteVerticesGraph和ConcreteEdgeGraph的编写 | 按时完成 |
5/22 | 19:00-21:00 | 完成poet | 延迟一小时完成 |
20:00-21:30 | 完成P2 | 按时完成 |
- 实验过程中遇到的困难与解决途径
遇到的难点 | 解决途径 |
题目包含大量英文,阅读有一定困难 | 通过翻译软件和实验课讲的东西一点一点了解实验要求 |
对Java的泛型和接口概念有一定的遗忘 | 查看网课和在csdn上自学 |
对Map类型了解不多 | 在csdn上查询学习 |
写代码时碰到问题要查资料,查资料有所得就写博客。这样的话理解能深刻不少。
在编写程序的时候,可以先编写测试,在编写源代码
- 面向ADT的编程和直接面向应用场景编程,你体会到二者有何差异?
在面向 ADT 编程的时候需要考虑代码的可复用性,需要使整个的编程更加具有普适性;而面向应用场景编程,更加直接和方便,但是适用的范围小。
- 使用泛型和不使用泛型的编程,对你来说有何差异?
使用泛型的话,程序对不同情况的适应性更好,但是由于是第一次写泛型,写起来比较麻烦,不太习惯。
- 在给出ADT的规约后就开始编写测试用例,优势是什么?你是否能够适应这种测试方式?
方便测试,先写测试用例再编程能明确需求。我不太适应这种方法,觉得没有基础代码的话,测试写起来很困难。
- P1设计的ADT在多个应用场景下使用,这种复用带来什么好处?
应用场景中的代码更加简洁,减少无用劳动,提高编程效率。
- 为ADT撰写specification, invariants, RI, AF,时刻注意ADT是否有rep exposure,这些工作的意义是什么?你是否愿意在以后编程中坚持这么做?
提醒自己注意数据外泄,明确类型的要求,提前注意可能的错误,方便自己日后阅读。
愿意。
- 关于本实验的工作量、难度、deadline。
工作量适中,但由于与其他课程的实验、考试重叠,时间比较紧张。
难度也适中,但是搞清楚实验要求需要阅读大段英文,耗费时间较长。
- 《软件构造》课程进展到目前,你对该课程有何体会和建议?
本课训练我们对大型程序的编写的基本素质,了解编写程序不仅有代码的实现,还有注释,git等辅助完成任务,可以方便他人阅读,同时方便自己对版本进行控制。希望以后的课可以学到更多关于软件构造的相关知识与技巧。