[OO 第三单元] 单元总结

[OO 第三单元] 单元总结

概述

OO 第三单元围绕实现一个给出 JML 规格的社交网络展开,主要包含了 JML 规格的阅读与理解、OKTest 的编写以及图论相关算法的学习。现对这一个月的 OO 第三单元做一个总结,为 JML 的学习画上一个句号。

整体架构

这次作业实现的社交网络主要结构如下图所示。

在这里插入图片描述
NetWork类表示社交网络,其中包含了网络中的人、信息和组,控制着信息的发送和对人与群组的各种操作;Person类表示社交网络中的人,其存储了自己的“熟人”;Group类是群组;Message类为网络中的信息,其在最后一次作业中有三个子类,NoticeMessageEmojiMessageRedEnvelopeMessage,不同种的信息需要添加一些额外的处理,比如在RedEnvelopeMessage需要添加Money属性。

在本单元的作业中,具体的架构实际上课程组已经通过接口等方式搭建好了,我们只需要实现这些接口然后按照给出的 JML 实现定义好的方法就能通过本单元作业的正确性测试(但是大概率通不过性能测试)。

作业实现

第九次作业

本次作业中的实现难点在于:

  • isCircle:该方法是查询在社交网络中两个人之间的是否存在一条熟人路径使得他们连通。最简单的 floyd 算法和 bfs 复杂度较高,可能会在强测压力测试中 TLE。因此我使用了并查集进行处理,让网络中的所有人都有一个对应的根节点,也是一个人,具体实现是通过 HashMap 的方式。在调用 isCircle的时候直接查询两个人的根节点是否一致,如果一致就返回 true
  • qbm:该方法是查询社交网络中存在的最大连通子图的数量。因为 JML 规格给出的方法是使用两层 for 遍历所有的人然后找到不同连通子图的数量。但是如果按照 JML 直接翻译会在强测 T 掉 40% 的点。因此在这次作业中我使用了动态维护的方法,在使用并查集的基础上,只在加边和加人的时候增加或者减少 qbm 属性的值。
  • qtm:该方法是查询社交网络中存在的三角边的数量。和qbm一样,如果直接按照 JML 翻译会 T,也是使用了动态维护的方式,只在加边的时候遍历一次和熟人找到需追加的 qtm 数量,然后修改对应的属性。

bug 修复:

本次作业中由于低估了对性能的要求,所以只是草草运用了一个并查集,没有使用动态维护的方式导致强测错了 40% 的点。修复方式就是和上面所述一样修改了qbmqtm方法,使用动态维护避免了 t 的测试点。

第十次作业

本次作业中的实现难点在于:

  • modifyRelation:该方法是对于网络中存在的边进行修改,难点在于涉及到了删边的操作。我还是在第九次实现的并查集的基础上进行功能实现的,在遇到删边操作的时候,我从被删边的某一个节点出发,找它的根节点,然后遍历在删边后还和根节点相连通的点,以此为新集合,再通过新旧集合之差找出是否存在因此分开的连通子图。
  • Group类的各种查询:这次新增的组类具有许多查询功能,可以查询组内所有人的总年龄、平均年龄等,对性能影响比较大的就是查询群组内的所有人之间关系之和,如果每次查询都遍历时间复杂度较高,可能会无法通过评测。所以我也是采用动态维护的方式,在修改边关系、加边、加人入组等操作时进行维护,查询时只需要返回一个具体数值即可。

bug 修复:

本地测试不够充分,oktest 和 qgvs 出现了明显bug都没发现,不过没有出现性能问题,只是对两处的逻辑进行了修正。

第十一次作业

本次作业中的实现难点在于:

  • qlm:该方法是获取该社交网络中的过定点最小环,如果不考虑性能的话,可以通过删边+dijstra算法的方式实现。但是在思考了复杂度以及时间限制之后发现这么做一定会在强测被卡,所以我使用了评论区中同学的算法,通过在 dijstra 的更新过程中维护目前次短路的长度,最后遍历所有节点得到环的最小值。

bug 修复:

这次作业没有出现bug,性能也没有问题。

规格与实现

通过这三次的作业迭代开发以及两次研讨课与同学们的讨论之后,我认为,规格是架构师搭好项目框架之后,为每一个类、每一个方法设计了规格,通过规格告诉这些类、方法得具体实现者需要做到什么,但是他并不关心具体是如何实现的,因为框架不会变,而实现者则是不用考虑架构的问题,只需要针对每一个方法、每一个类中的规格找到最合适的实现方法就行。比如在本单元作业中那些对性能有要求的方法,比如 qbs,JML 规格说明了方法需要得到的是什么,而我们作为实现者则是需要考虑如何优化得到结果的过程。我认为这就是规格与实现的分离。

测试

  • 黑箱测试:黑箱测试是指在测试过程中,测试人员并不知道软件的内部结构和实现方式,只关注软件的输入和输出。我们所使用的评测机对拍就是黑箱测试。
  • 白箱测试:白箱测试是指在测试过程中,测试人员了解软件的内部结构和实现方式,可以直接访问并验证代码实现是否符合规格和预期。我认为我们所实现的 oktest 就是一种白箱测试,这并不是从我们所实现的作业整体出发的测试,而是对于单一模块的正确性测试。
  • 单元测试:单元测试是指对程序中的各个基本模块进行测试,一般用于检测各个方法的逻辑是否符合规格,比如 oktest 就是对某一个方法得测试,属于白箱测试。
  • 功能测试:功能测试是指测试软件的功能是否满足需求,不关心具体实现,是黑箱测试。
  • 集成测试:集成测试是指测试不同模块之间相互协作时的正确性的测试,比如测试几个方法之间的协同或者是接口的调用。
  • 压力测试:压力测试是指模拟负载极高的情况下软件运行的情况,是否能保证其正确性和稳定性。通常是在极短时间内有大量输入或者请求。
  • 回归测试:回归测试是指在软件更新或修改后,对已有的功能进行重新测试,以确保更新或修改不会影响原有的功能。实际上我们的后两次迭代开发之后,都应该对前面的功能进行测试,以保证之前的功能没有被改变,这就是回归测试。
  • 测试工具:我主要是使用了同学分享的评测机对自身代码进行了评测和对拍。
  • 数据构造:我先是对每一个功能进行了基本测试,保证在普通情况下的逻辑符合规格,对于大规模数据(性能测试)的构造我并没有实现,只是通过同学的评测机的大规模数据生成器进行测试。
  • OkTest:OkTest 实际上就是检测实现是否符合规格的测试,需要对所有规格中提及的后置条件以及异常情况进行测试。改进建议则是最好说明一下这个测试的使用对象,在第九次作业时不太理解 OkTest 的意义在哪。

学习体会

本单元重点学习了 JML,但是在具体实现的时候,大部分时间不是在理解和学习 JML 而是在想怎么去通过性能评测,也复习了很多图论的相关知识并且运用到了本单元的作业中。不过刚开始认为后面两个单元相较于前两个单元应该是难度大减所以放松了警惕,在本地测试的时候稍微投了下懒,导致很多bug都没能在本地发现,值得反思。希望能在接下来的四周加强测试,让自己的 OO 学习有一个较为满意的结果!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值