哈工大软件构造Lab2

  1. 实验目标概述

本次实验训练抽象数据类型(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 并据此设计测试用例.

  1. 实验环境配置

简要陈述你配置本次实验所需环境的过程,必要时可以给出屏幕截图。

特别是要记录配置过程中遇到的问题和困难,以及如何解决的。

配置本次实验所需开发、测试、运行环境的过程:

第一步,JDK下载和环境配置

在官网:Java Downloads | Oracle 中国下载

环境配置:

第二步,下载IDEA,并配置环境

第三步,下载并配置JUnit

第四步,下载Git,并学习相关操作

配置过程中遇到的问题和困难:

1..配置JDK时,在17和11同时切换使用存在问题,后来调查了资料使用JAVA_HOME随时切换。

2.Git安装时的具体操作,在网上搜集资料后成功安装。

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

https://github.com/ComputerScienceHIT/HIT-Lab2-2022111787.git

  1. 实验过程

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

    1. Poetic Walks

在这里简要概述你对该任务的理解。

Java集合框架提供了许多有用的数据结构来处理对象集合:列表映射队列集合等。它不提供图形数据结构。让我们实现图形,然后使用它们来创造无与伦比的光彩的永恒艺术。

      1. Get the code and prepare Git repository

如何从GitHub获取该任务的代码、在本地创建Git仓库、使用Git管理本地开发。

对项目右键打开open Git Bash here,用git clone从远程仓库导到本地仓库

修改文件格式后上传到远程仓库

1. git init

2. git add .(文件name)

3. git commit -m "first commit"

4. git remote add origin 远程仓库地址

5. git pull origin master --allow-unrelated-histories

6. git push -u origin master

      1. Problem 1: Test Graph <String>

以下各部分,请按照MIT页面上相应部分的要求,逐项列出你的设计和实现思路/过程/结果。

这一步是测试带有String类型顶点标签的图。

  1. 对于静态方法GraphStaticTest.java,只有一个实现,只需要运行一次这些测试,已经被提供,所以可以保持原样。
  2. 在GraphInstanceTest.java中,使用emptyInstance()方法创建一个空图,并对Graph接口中每个方法使用等价类划分的方法。
  1. 将图划分为空图与非空图
  2. 根据顶点分为“已经存在于图中”,“未存在于图中”两组。
  3. 根据边分为“weight为0”和“weight为正整数”两组。
  4. 测试方法的实现调用Graph接口提供的add, set, remove, vertices, sources,  targets等方法充分覆盖对输入集的划分。

Problem 2: Implement Graph <String>

以下各部分,请按照MIT页面上相应部分的要求,逐项列出你的设计和实现思路/过程/结果。

        1. Implement ConcreteEdgesGraph

对于ConcreteEdgesGraph我们必须使用的rep是

对于AF,ConcreteEdgesGraph为一个带权有向图,其中每个顶点的标签为非空字符串且两两不等;每条有向边两个端点不等;每条有向边具有正整数权值。

AF,Ri如下图:

对于需要实现的函数如下:

  1. add函数:

如果点集中含有这个点,返回false,没有就将该点加入点集

  1. set函数:

若weight不为0,当存在(source, target)这条边时,将其边权修改为weight,返回值为之前的权值;否则当这条边不存在,加入这条边,边权为weight,返回0。若weight为0,当存在这条边时,删除这条边;否则什么也不做。

  1. remove函数:

删除点集中的该点及其对应的边

  1. set函数:

返回vertices的副本,防止泄露

  1. sources函数:

创建Map,遍历边集,将所有能到达target的点及其权值加入Map

  1. targets函数:

创建Map,遍历边集,将所有source能到达的点及其权值加入Map

  1. toString函数:

打印出图

        1. Implement ConcreteVerticesGraph

对于ConcreteEdgesGraph我们必须使用的rep是

对于AF,Ri如下图:

在Vertex类中加入label作为邻接表的表头,targets作为出边集合

对于需要实现的函数如下:

  1. add函数:

如果点集中含有这个点,返回false,没有就将该点加入点集

  1. set函数:

若weight不为0,当存在(source, target)这条边时,将其边权修改为weight,返回值为之前的权值;否则当这条边不存在,加入这条边,边权为weight,返回0。若weight为0,当存在这条边时,删除这条边;否则什么也不做。

  1. remove函数:

删除点集中的该点及其对应的边

  1. set函数:

返回vertices的副本,防止泄露

  1. sources函数:

创建Map,遍历点集,找到所有出边集合中含有target的表头,并连同weight加入map

  1. targets函数:

创建Map,遍历点集,找到与source相等的对应表头,使得map=ver.getTargets()

  1. toString函数:

打印出图

对于两个图的实现方法的测试除toString外为公共测试,在GraphInstanceTest中实现,testtoString在两个函数中分别实现

      1. Problem 3: Implement generic Graph<L>
        1. Make the implementations generic

只需要将作为图标签的String替换为<L>,.Edge和Vertex也应该替换为泛型Edge<L>和Vertex<L>

        1. Implement Graph.empty()

对empty函数进行修改:

      1. Problem 4: Poetic walks
        1. Test GraphPoet

Testing strategy如图所

        1. Implement GraphPoet

对应的AF,Ri如图

在GraphPoet中使用BufferedReader的readline方法循环读取文本,并用split函数分割用“ ”相隔开的单词,将其保存到words数组中,保存到图,并计算出weight.

在poem函数中将输入的语句用相同的办法分割,并求出weight最大的bridge.

        1. Graph poetry slam

重写的main如图:

输出结果为:

      1. 使用Eclemma/Code Coverage for Java检查测试的代码覆盖
      1. Before you’re done

请按照Problem Set 2: Poetic Walks的说明,检查你的程序。

如何通过Git提交当前版本到GitHub上你的Lab2仓库。

在这里给出你的项目的目录结构树状示意图。

    1. Re-implement the Social Network in Lab1

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

      1. FriendshipGraph

使用3.1中的两个类来建图

  1. addVertex函数:

将点加入graph中

  1. addEdge函数:

判断图中是否有两个点。若有,将边加入图,反之给出错误提示并退出

  1. getDistance函数:

使用广度优先算法

      1. Person

与实验1的设计一致

      1. 客户端main()

与实验1的设计一致

      1. 测试用例

给出你的设计和实现思路/过程/结果。

分别对addVertex,addEdge,getDistance进行测试,使用assertEquals断言来进行测试,和实验1一致。

      1. 提交至Git仓库

如何通过Git提交当前版本到GitHub上你的Lab3仓库。

在这里给出你的项目的目录结构树状示意图。

  1. 实验进度记录

使用表格方式记录你的进度情况,以超过半小时的连续编程时间为一行。

每次结束编程时,请向该表格中增加一行。不要事后胡乱填写。

不要嫌烦,该表格可帮助你汇总你在每个任务上付出的时间和精力,发现自己不擅长的任务,后续有意识的弥补。

日期

时间段

计划任务

实际完成情况

2024.4.13

20:00-20:45

简单了解实验要求,并对对应的知识点进行了充分的复习

按时完成

2024.4.14

10:00-12:00

完成3.1的Problem1及对应report

按时完成

2024.4.15

18:00-24:00

完成3.1的Problem2及对应report

按时完成

2024.4.16

18:00-22:00

完成3.1的Problem3, Problem4及对应report

按时完成

2024.4.17

18:00-24:00

完成3.2及对应report

按时完成

2024.4.18

17:30-20:00

完善report

按时完成

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

遇到的难点

解决途径

对checkRep的概念不理解

在CSDN查阅资料学会

对图的empty调用报错

发现读题理解有误,应使用emptyInstance

在ConcreteEdgesGraph中设计toString时,使用TreeSet,让其有序,但是在ConcreteVerticesGraph中未果,同时程序报错StringIndexOutOfBoundsException

查阅资料后发现对StringBuilder类型的长度length()和删除最后一个字符放在一个语句,产生歧义。

在FriendshipGraph中使用广度优先算法求最小距离时,程序出现死循环

发现是对Set类型的判断为空语句有误

  1. 实验过程中收获的经验、教训、感想
    1. 实验过程中收获的经验和教训(必答)

  学会了ADT的设计规约、测试,并使用面向对象编程(OOP)技术实现 ADT。了解到了一些编程语言技巧。

    1. 针对以下方面的感受(必答)
  1. 面向ADT的编程和直接面向应用场景编程,你体会到二者有何差异?

  面向ADT的编程:这种方法更加抽象和通用,关注于数据的结构和操作,而不是具体的应用场景。由于ADT是通用的,所以可以被多个应用或场景重用。可维护性更好

  直接面向应用场景的编程:这种方法更具体和实际,你会直接解决特定的问题或实现特定的功能。可能会导致代码紧密耦合于特定的应用场景,降低了代码的重用性和灵活性。

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

  使用泛型提高了代码的复用性,类型安全性、清晰度和可读性,同时也能帮助在编译时捕获错误。而不使用泛型可能会导致代码冗余、类型不安全、难以维护和调试等问题。

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

  规约定义了ADT的预期行为和属性,这为测试提供了明确的目标。编写测试用例可以帮助我好地设计ADT的实现。通过考虑如何测试ADT,我更清楚地了解哪些功能需要实现,以及如何实现它们。适应起来不如想象中的容易,但了解了他的好处后,我意识到应该努力适应,

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

  减少了代码的冗杂,提高了代码的重用性,降低了代码的维护成本

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

  确保ADT的正确性:规约:定义了ADT的操作和行为,为实现提供了明指导。不变式:描述了在ADT的生命周期内始终保持不变的属性或条件,帮助确保ADT的正确性。表示不变量(RI):指定了表示(rep)必须满足的条件,确保内部表示的有效性。抽象函数(AF):描述了如何从ADT的表示到其抽象值的映射,确保ADT与其抽象值之间的关系清晰明确。

  防止rep exposure:通过控制对表示的直接访问,可以避免rep exposure,从而防止不合法或不一致的状态。这有助于保护ADT的内部表示,确保它不被外部代码意外或恶意地修改。

  为了以上的有利点,我愿意在以后编程中坚持这么做。

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

  本次实验工作量适中,有些难度,我的deadline是在4.18

  1. 《软件构造》课程进展到目前,你对该课程有何收获和建议?

  本课程教我们如何规避一些不必要的麻烦,开发出高质量的软件,也让我们与其他程序员之间建立起规约,可以与其他人进行更好地交流

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值