软件构造Lab2-实验报告

本次实验涉及软件构造的多个方面,包括ADT设计、泛型化、测试用例编写和OOP实现。实验中,学生需实现Graph接口的多个版本,如ConcreteEdgesGraph和ConcreteVerticesGraph,进行泛型化改造,并实现Poetic Walks和社交网络的场景。此外,还设计了棋类游戏的ADT,包括Position、Piece、Player、Board和Action接口及其实现,以及主程序MyChessAndGoGame。
摘要由CSDN通过智能技术生成
  1. 实验目标概述

本次实验训练抽象数据类型(ADT)的设计、规约、测试,并使用面向对象编程(OOP)技术实现ADT。具体来说:

⚫ 针对给定的应用问题,从问题描述中识别所需的ADT

⚫ 设计ADT规约(pre-conditionpost-condition)并评估规约的质量;

⚫ 根据ADT的规约设计测试用例;

⚫ ADT的泛型化;

⚫ 根据规约设计ADT的多种不同的实现;针对每种实现,设计其表示(representation)、表示不变性(rep invariant)、抽象过程(abstraction function

⚫ 使用OOP实现ADT,并判定表示不变性是否违反、各实现是否存在表示泄露(rep exposure);

⚫ 测试ADT的实现并评估测试的覆盖度;

⚫ 使用ADT及其实现,为应用问题开发程序;

⚫ 在测试代码中,能够写出testing strategy并据此设计测试用例。

2.实验环境配置

延续Lab1中的实验环境,除此之外,本次实验在 Eclipse IDE中安装配置 EclEmma(一个用于统计JUnit测试用例的代码覆盖度测试用例的代码覆盖度plugin)

在这里给出你的GitHub Lab2仓库的URL地址(Lab2-学号):

https://github.com/ComputerScienceHIT/Lab2-1173710111 

3.实验过程

请仔细对照实验手册,针对三个问题中的每一项任务,在下面各节中记录你的实验过程、阐述你的设计思路和问题求解思路,可辅之以示意图或关键源代码加以说明(但千万不要把你的源代码全部粘贴过来!)

3.1Poetic Walks

  1. 对给定的接口Graph<L>,完成他的两个实例类ConcretVerticesGraph和ConcreateEgdesGraph:

(1)首先分别构造两个实例类的rep类Vertex和Edge;

(2)用String作为L的特例,分别在两个实例类中实现Graph接口中的各个方法,写对应的test文件以确保其正确性;

(3)将所有String变量替换为泛型L。

2. 对给定的文本文件,按照给定规则建立有向图,调用Graph<L>作为存储语料库的数据结构,利用该结构,对输入的字符串进行扩充。

3.1.1Get the code and prepare Git repository

 

请阅读 http://web.mit.edu/6.031/www/sp17/psets/ps2/,遵循该页面内的要求完 ,遵循该页面内的要求完成编程任务。

⚫ 在 Get the code步骤中你无法连接MIT的 Athena服务器,请从以下地址获取初始代码 :

 https://github.com/rainywang/Spring2019_HITCS_SC_Lab2/tree/master/P1

⚫ 在作业描述中若遇到 “commit and push”的要求 ,请将你的代码 push到你的 GitHub Lab2仓库中 。

⚫ 其他步骤请遵循 MIT。

自 https://github.com/rainywang/Spring2019_HITCS_SC_Lab2/tree/master/P1 获得实验代码。

git初始化:

Git init

Git remote add origin git@github.com:ComputerScienceHIT/Lab2-1173710111.git

Git pull origin master

Git add .

Git commit -m “xxx”

Git push origin master

 

3.1.2Problem 1: Test Graph <String>

静态 Graph.empty()方法的测试策略和测试都在GraphStaticTest.java,为了运行这个测试,首先要修改Graph<L> empty()为:

 public static String Graph empty() {

        Graph graph = new ConcreteEdgesGraph();

return graph;

 }

这里以ConcreteEdgesGraph作为Graph默认的实例类,也可以用ConcreteVerticesGraph,二者是等价的

3.1.3 Problem 2: Implement Graph <String>

3.1.3.1Implement ConcreteEdgesGraph

(1)实现 Edge<String>类

  1. rep:

private int weight;

边的权值

private String sourceVertex;

边的起点

private String targetVertex;

边的终点

  1. constructor:

public Edge(L source,L target,int w){

this.weight=w;

this.sourceVertex=source;

this.targetVertex=target;

}

 

  1. function:

getter

三个域的getter,因为规定Edge<L>是Immutable的所以没有setter。

public void checkRep() {

assert sourceVertex!=null;

assert targetVertex!=null;

assert weight>=0;

}

每个getter返回前检查该边的起点、终点、权值是否有空的。

@Override public String toString()

以字符串的形式直观地展示该边的起点、终点和边权,格式为:

source->target [weight]

(2)实现ConcreteEdgesGraph类

  1. rep:

private final Set<Stringvertices

保存图中的所有顶点

private final List<Edge<String>> edges

顺序存储图中的所有边

  1. function:

每个function返回前检查rep不变

private void checkRep() {

     for(int i=0;i<edges.size();i++) {

assert vertices.contains(edges.get(i).getSourceVertex()):"an edge with illegal vertex";

assert vertices.contains(edges.get(i).getTargetVertex()):"an edge with illegal vertex";

for(int j=i+1;j<edges.size();j++) {

assert !(edges.get(i).getSourceVertex().equals(edges.get(j).getSourceVertex())&&edges.get(i).getTargetVertex().equals(edges.get(j).getTargetVertex()))

:"duplicate edges";

}

assert edges.get(i)!=null;

}

for(L s:vertices) {

assert s!=null;

}

}

@Override 

public boolean add(String vertex)

(1)点存在:返回false

(2)不存在:调用list.add向vertices中添加该点

@Override public int set(String sourceString targetint weight)

遍历edges:

(1)如果已经存在从source到target的一条边,记下这条边的权值,创建一条新的边(参数为source,target,weight),调用Collections.replaceAll替换掉edges中的旧边,返回旧边权;

(2)如果不存在,新建一条边(参数为source,target,weight),将其加入edges,返回0。

@Override public boolean remove(L vertex)

调用set.contains判断图中是否存在该顶点:(1)如果不存在,返回false;

  1. 否则,遍历edges,删除起点或终点是该顶点的边,遍历结束后调用list.remove从vertices中删除该顶点。

@Override public Set<L> vertices()

copy一份vertices到新Set中,返回这个Set

@Override public Map<L, Integer> sources(L target)

建立一个空Map,遍历edges,找出以target为终点的边edge;

weight=0时表示该边不存在,跳过;

将edge.source->edge.weight加入Map,遍历结束后返回这个Map

@Override public Map<L, Integer> targets(L source)

建立一个空Map,遍历edges,找出以source为起点的边edge;

weight=0时表示该边不存在,跳过;

将edge.source->edge.weight加入Map,遍历结束后返回这个Map

@Override public String toString() 

将所有边的toString连接在一起

(3)编写测试 GraphInstanceTest.java

 public abstract Graph<String> emptyInstance();

抽象方法,创建新的空Graph<String>

@Test public void testAdd() 

分别对input未存在、已存在的情况进行测试,检查其rep是否与期待相符

@Test public void testRemove() 

@Test public void testSources() 

1. 参数vertex的source域为空;

2. 参数vertex的target域为空;

3. 对set方法传入weight=0的情况进行测试

 

方法调用后,对相关参数(边)调用source方法或target方法的返回值进行检查

@Test public void testTargets() 

@Test public void testSet()

  1. 边不存在
  2. 边存在
  3. 边权为0

 

方法调用后,对相关参数(边)调用source方法或target方法的返回值进行检查

@Test public void testVertices()

调用add和remove方法,然后对vertices方法的返回值进行检查

@Test public void testALL()

创建一个较复杂的有向图,调用到每个方法,对rep进行检查

(4)编写测试ConcreteEdgesGraphTest.java

Graph中定义的接口

GraphInstanceTest.java中实现,不必重复

创建一个新的空图 ConcreteEdgesGraph

@Override public Graph<String> emptyInstance() {

        return new ConcreteEdgesGraph<String>();

 }    

    

 public void testToString()

调用Graph中的方法构建一张有向图,测试toString的返回值是否能正确规范地表示这张图。

public void testVertex()

主要测试Edge中的toString方法,测试其返回值能否正确规范地表示这条边的信息。

 

3.1.3.2Implement ConcreteVerticesGraph

(1)实现Vertex<L>类

  1. rep:

 private L name;

当前节点的名字(标签)

private Map<L, Integer>source;

存储所有以当前点为终点的边,key表示边的起点,value表示边权

private Map<L, Integer>target;

存储所有以当前点为起点的边,key表示边的终点,value表示边权

  1. constructor:

public Vertex(L name){

this.name=name;

}

  1. function:

setter

source,target的setter

getter

name,source,target的getter

public void checkRep() {

assert source!=null;

assert target!=null;

assert name!=null

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值