【Blog 4】软件构造Lab2

虽说是第二次实验,但近期的确事情有点多,Java的学习进度也有些搁置,所以这次实验依旧困难重重。

1、实验目标概述

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

根据描述识别对应ADT;

设计ADT规约并评估质量;

根据规约设计测试用例;

ADT的泛型化;

根据规约设计ADT的不同实现,针对每种实现设计其表示、表示不变性、抽象过程;

使用OOP实现ADT,并判定不变性是否违反、各实现是否存在表示泄漏;

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

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

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

2、实验环境配置

3、实验过程

3.1 Poetic Walks

实现抽象数据类型Graph,在此基础上实现GraphPoet,一个通过单词亲和图生成诗歌的类。

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

Edge类:

//fields

private int weight;//边的权重

private L source;//起点

private L target;//终点

//constructor

public Edge(L source, L target, int weight):增加一个edge

//methods

public void setweight(int weight):改变weight

public L source():返回source

public L target():返回target

public int weight():返回weight

//toString()

public String toString():返回字符串表示的edge,自动生成的就行

ConcreteEdgesGraph类:

//fields

protected final Set<L> vertices = new HashSet<>();//存储所有顶点

private final List<Edge<L>> edges = new ArrayList<>();//存储所有边

//methods

public boolean add(L vertex):增加一个顶点

public int findedge(L source, L target):找到边在list中的位置,返回一个index

public int set(L source, L target, int weight):增加一条有向边

public boolean remove(L vertex):移除一个顶点

public Set<L> vertices():返回包含所有顶点的集合

public Map<L, Integer> sources(L target):返回某个顶点为终点的所有边

public Map<L, Integer> targets(L source):返回某个顶点为起点的所有边

 3.1.3.2 Implement ConcreteVerticesGraph

Vertex类:

//fields

private L name;//顶点的名字

private Map<L, Integer> allsource = new HashMap<>();//返回该顶点为起点的所有边

private Map<L, Integer> alltarget = new HashMap<>();//返回该顶点为终点的所有边

//constructor

public Vertex(L name):增加一个vertex

//methods

public L name():返回顶点名字

public Map<L, Integer> getsource():返回allsource

public Map<L, Integer> gettarget():返回alltarget

public void setsource(L source, int weight):在allsource中增加一个映射

public void settarget(L target, int weight):在alltarget中增加一个映射

//toString()

public String toString():自动生成

ConcreteVerticesGraph类:

//fields

private final List<Vertex<L>> vertices = new ArrayList<>();//储存所有顶点

//methods

public L name():返回顶点名字

public Map<L, Integer> getsource():返回allsource

public Map<L, Integer> gettarget():返回alltarget

public void setsource(L source, int weight):在allsource中增加一个映射

public void settarget(L target, int weight):在alltarget中增加一个映射

3.1.4 Problem 3: Implement generic Graph<L>

3.1.4.1 Make the implementations generic

将所有string改为L

3.1.4.2 Implement Graph.empty()

3.1.5 Problem 4: Poetic walks

3.1.5.1 Test GraphPoet

 

3.1.5.2 Implement GraphPoet

//fields

private final Graph<String> graph = Graph.empty();

//methods

public GraphPoet(File corpus) throws IOException():从corpus中读取原文,处理后存在graph中。

public String poem(String input): public String poem(String input):基于graph将input改为诗歌并返回。

3.1.5.3 Graph poetry slam

3.1.6 使用Eclemma检查测试的代码覆盖度

 

3.1.7  Before you’re done

将文件放在本地仓库,然后输入指令

Git add .

Git commit

Git push

我的项目的目录结构树状示意图:

3.2 ​​​​​​​Re-implement the Social Network in Lab1

利用Lab1中已经实现的Social Network来重新编写。

基于我在 3.1 节 Poetic Walks 中定义的 Graph<L>及其两种实现,重新实现 Lab1 中 3.3 节的 FriendshipGraph 类。

3.2.1 FriendshipGraph类

//fields

private final Graph<Person> graph = Graph.empty();

//methods

public boolean addVertex(Person person):增加一个人到关系网中

public boolean addEdge(Person source, Person target, int weight):在关系网中增加一个关系

public int getDistance(Person a, Person b):获取关系网中两个人的距离,使用BFS

3.2.2 Person类

//fields

private  String name;//人的名字

public  int distance;//方便BFS而设置的距离

//constructor

public Person(String name):增加一个人

//methods

public String name():返回name

public int distance():返回distance

3.2.3 客户端main()

沿用之前的main函数即可,仅仅对addEdge多了一个参数。

3.2.4 测试用例 

3.2.5 提交至git仓库 

提交方法同3.1.7。

我的项目的目录结构树状示意图:

4、遇到的困难及解决方法 

遇到的难点

解决途径

Test中的test文件无法正常运行

将test文件夹重新建立build path

P1的VertexGraph中remove ()方法无法正确实现

将List的remove()方法使用index删除,即可顺利删除了,

而之前使用object删除未成功

5、实验中的收获、教训、感受

5.1 收获与教训

必须要继续学习java,不然往后越来越难,很难靠自己完整编程。

5.2 感受

1面向ADT的编程和直接面向应用场景编程,你体会到二者有何差异?

后者感觉对用户更友好。

2使用泛型和不使用泛型的编程,对你来说有何差异?

暂时没有感受到,还需对泛型进行进一步的学习和体会。

3在给出ADT的规约后就开始编写测试用例,优势是什么?你是否能够适应这种测试方式?

优势是面向测试的编程,有点逆推法的感觉,需要慢慢适应。

4P1设计的ADT在多个应用场景下使用,这种复用带来什么好处?

减少内存使用,也能减少程序员代码编写时间。

5P3要求你从0开始设计ADT并使用它们完成一个具体应用,你是否已适应从具体应用场景到ADT的“抽象映射”?相比起P1给出了ADT非常明确的rep和方法、ADT之间的逻辑关系,P3要求你自主设计这些内容,你的感受如何?

不太适应,这次还是依靠了一部分Lab1的代码知识。

6为ADT撰写specification, invariants, RI, AF,时刻注意ADT是否有rep exposure,这些工作的意义是什么?你是否愿意在以后编程中坚持这么做?

能对编码有个清晰的认识,以后我可能不会写出来,但会在脑子里过一下。

7关于本实验的工作量、难度、deadline。

工作量对于我这个java小白来说真的很多,难度很大,deadline因为和计算机系统的期末考试撞了,所以很难受。

8《软件构造》课程进展到目前,你对该课程有何体会和建议?

刚刚步入软件构造的课堂,还算是个软构小白。到现在我已经聆听了几堂课,愈发觉得软件构造是一个庞大的工程,它让我跳出了基本的programming和coding,从一个更高的角度来俯视整个软件构造的过程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值