哈工大软件构造lab2心得

1 实验环境配置

本次实验需要在eclipseIDE中配置EclEmma,在eclipse中的Marketplace搜索EclEmma如图:

然后按步骤安装即可。

 

2 具体过程

2.1 Poetic Walks

本次实验给出了一个图接口,要求我们建立一个边图类、一个点图类分别继承自这个图接口,并在里面实现一系列方法,并且实现抽象数据型,并用这个图的抽象数据型完成poet的工作。

(1)完善Graph接口类,并运用用泛型的思想,将String拓展为泛型L类;

(2)实现Graph类的方法:add, set, remove, vertices, sources, targets;

(3)利用实现的Graph类,实现GraphPoet类,若输入的文本的两个单词之间存在衔接的词,则插入该词;若存在多个这种词,则选取边权值较大者。

2.1.2 Problem 1: Test Graph <String>

(1)思路:为Graph<String>设计相应的测试策略,主要针对其各个方法进行等价类划分的测试。

(2)过程:

测试策略如下,按照其编写6个测试

2.1.3 Problem 2: Implement Graph <String>

实现Edge类

(1)属性

   Edge应包括边的权值、起点和终点,因此定义private类型变量如下:

  

 

(2)方法

Edge

初始化构造方法,初始化新边的两个点和边的权值

checkRep

检查表示不变性,边不为空且权值大于等于0

getsource

返回边的一个点source

gettarget

返回边的一个点target

getweight

返回边的weight

toString

返回一条边的字符串,“起点->终点权重为weight”

(3)AF, RI, Safety from rep exposure

(4)测试策略

实现ConcreteEdgesGraph

(1)属性

ConcreteEdgesGraph类中应该包括顶点set表和边权值list表,定义private类型的两个表如下:

(2)方法

ConcreteEdgesGraph

构造方法

checkRep

检查表示不变性,edges长度是大于0的实数,有起始点

add

顶点不为空时,添加一个顶点进入点表中

set

输入source,target,weight,分别为边的起点、终点和权值

若权值为负,返回-1。若权值为正且新边已经存在,则除去原边并添加新边。若权值为正且新边不存在,则直接添加新边。若权值为0且新边已经存在,则除去原边

只要改变了原边权值,都返回原边权值,没有权值则返回0

remove

除去某个点及与它相邻的所有边。只需使用迭代器,遍历edges,寻找是否有边的起点或者终点为该点并删去

vertices

返回所有的点集

sources

输入一个终点,返回与它相连的所有边和起点构成的Map

targets

输入一个起点,返回与它相连的所有边和终点构成为的Map

toString

将整个图中所有点的指向转化为一条字符串输出

(3)AF, RI, Safety from rep exposure

(4)测试策略

继承Graph的测试策略GraphInstanceTest,只需增加toString的测试:

实现Vertex

(1)属性

Vertext类中应包括点的名字,点的起点表Map,点的终点表Map,因此定义Private类型的表如下:

(2)方法

Vertex

构造方法,用点的名字创建

checkRep

检查表示不变性,每个边的权值应该大于0

getname

返回点的名字name

getsource

返回能到达该点的所有点和边权值构成的Map

gettarget

返回某个点能到达的所有点和边权值构成的Map

addsource

在起点Map中加入某起点

若weight不为0,则将其加入allsource中(若起点已存在,则更新其weight并返回原weight,不存在则直接构建新点并返回0)

若weight为0,则移除起点(不存在返回0,存在返回原weight)

 

addtarget

在终点Map中加入某终点

若weight不为0,则将其加入alltarget中(若终点已存在,则更新其weight并返回原weight,不存在则直接构建新点并返回0)

若weight为0,则移除终点(不存在返回0,存在返回原weight)

 

removesource

在起点表中删除某起点,并返回原来的边权值

removetarget

在终点表中删除某终点,并返回原来的边权值

toString

得到一个点的字符串表示

(3)AF, RI, Safety from rep exposure

(4)测试策略

实现ConcreteVerticesGraphTest类

(1)属性

ConcreteVerticesGraph只需包括Vertex构成的List点集,因此定义private类型的表如下:

 

(2)方法

ConcreteVerticesGraph

构造方法

checkRep

检查表示不变性,vertices中不能有重复点

add

顶点不为空时,添加一个顶点进入点表中

set

输入source,target,weight,分别为边的起点、终点和权值

若权值为负,返回-1。若权值为正且新边已经存在,则除去原边并添加新边。若权值为正且新边不存在,则直接添加新边。若权值为0且新边已经存在,则出去原边。只要改变了原边权值,都返回原边权值,没有权值则返回0

remove

除去某个点及与它相邻的所有边。只需使用迭代器,遍历vertices,寻找是否有与待删除点相同的名字的点直接删去即可,如果名字不同,则在该点的起点表和终点表中寻找删去即可

vertices

返回所有的点集

sources

输入一个终点,返回与它相连的所有边权值和起点构成的Map

targets

输入一个起点,返回与它相连的所有边权值和终点构成为的Map

toString

将整个图中所有点的指向转化为一条字符串输出

(3)AF, RI, Safety from rep exposure

(4)测试策略

继承Graph的测试策略GraphInstanceTest,只需增加toString的测试:

 

2.1.4 Problem 3: Implement generic Graph<L>

(1)首先将具体类的声明及属性改为如下图所示:

(2)类似地,再将代码中的String用L替换,可根据eclipse的报错找到位置并修改,将方法等其他部分修改完毕即可。

(3)测试代码中的也需修改,在声明对象时添加<String>,意为泛型在该测试中运用String类型。如:

 

2.1.5 Problem 4: Poetic walks

测试策略

Implement GraphPoet

(1)属性

(2)方法

GraphPoet

输入文件的路径,一行行读入,储存在List中,接着每次根据相邻的元素,在图中添加新的边

checkRep

检查不变性,必须保存从语料库文件生成的图

poem

输入需要进行扩充的字符串,由StringBuilder保存。

每读取一个词,当前词作为source,下一个词作为target,在garph中寻找source的终点表中是否有与target的起点表中相同的元素,若存在,找到权值和最大的点加入source和target之间。最后返回扩充后的字符串。

 

toString

调用ConcreteEdgesGraph中的toString方法,输出图结构

(3)AF, RI, Safety from rep exposure

 

2.2 Re-implement the Social Network in Lab1

实验要求我们基于在 3.1 节 Poetic Walks 中定义的 Graph<L>及其两种实现,尽可能复用ConcreteEdgesGraph<L>或ConcreteVerticesGraph<L>中已经实现的方法,重新实现 Lab1 中 3.3 节的 FriendshipGraph 类,通过基本操作实现FriendshipGraph中addVertex,addEdge和getDistance三个接口,要求不能修改父类rep,需再运行提供的main()和执行Lab1中的Junit测试用例,使之正常运行。

3.2.1 FriendshipGraph类

(1)属性

FriendshipGraph需要一个图,为Person构成的ConcreteEdgesGraph,定义private类型的表如下:

(2)方法

FriendshipGraph

构造方法

addVertex

在图中增加新Person,调用ConcreteEdgesGraph中的add

 

main

复制Lab1的main即可

addEdge

为某个人a增加朋友b,调用ConcreteEdgesGraph中的set

 

getallpeople

直接返回即可

 

getDistance

得到两个人之间的最短距离。与Lab1类似,稍加修改即可。先判斷person1和person2是不是同一个人,如果是,直接返回距离为0。

如果不是则继续通过BFS算法计算距离:首先将c1入队,并且把第一个元素c1和下标0入集合,当队列非空时,弹出队首元素top,并且得到top在集合waypoints中的下标distance,然后调用gethisfriend函数得到队首元素的所有朋友allfriend,只要allfriend中的元素与c2不同,就把这些元素全部入队,并且把这些元素及下标distance+1放入集合。只要队列非空,继续执行以上步骤,直到找到某个元素与c2相同并且返回这个元素在集合waypoints中的下标。如果直到队列为空还没找到c2,则返回-1。

 

(3)AF, RI, Safety from rep exposure

3.2.2 Person类

(1)属性

Person类应有两个属性,分别为String类型的名字,以及字符表以记录所有已存在的名字(可用于防止重复的人名),定义private类型变量如下:

(2)方法

Person

构造方法,如果是新名字则创建person

getmyname

返回本人名字

(3)AF, RI, Safety from rep exposure

 

实验过程中遇到的困难与解决途径

遇到的难点

解决途径

进行Problem2时,报错

发现声明ConcreteEdgesGraph类时,多加了一个<L>

进行Problem3时,转换泛型时对泛型不是很理解

复习课件,网上查询资料

ConcreteVerticesGraphTest运行测试时,报错

根据failure trace找到了错误之处,发现是在设计测试时,自己将预计输出写错了

 

4 经验感想

(1)ADT编程,使得写过的类的属性、方法可以通过继承等方法复用,与直接面向应用场景编程相比,代码的复用性更高。

(2)泛型能够适应更多变化,应用范围更广泛,可以使得代码用于更多的场景。

(3)在给出ADT的规约后就开始编写测试用例,可以更好地保证代码的正确性,及时修改错误。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十六涣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值