BUAA2024春-OOUnit3总结

oo第三单元总结

​ 第三单元的主题是规格化设计,按照JML描述的规格实现类,管理数据和方法。第三单元的背景是实现简单的社交网络,hw9实现了社交网络图的基础架构以及一些计算和查询;hw10加入了Tag层次,管理Person节点的“簇”;hw11加入了几类Message,并实现了发送消息的方法。

测试过程

黑箱测试与白箱测试
  • 黑箱测试是指测试时不考虑内部代码的逻辑和结构,只给出输入数据和预期的输出数据,将程序产生的输出数据与预期输出进行比对,检查程序功能是否满足预期。
  • 白箱测试指测试者完全知道程序的结构和处理算法,按照程序的内部结构设计测试用例,检测每条执行分支是否能按照预期工作。白箱测试基于对程序结构的深刻了解,一般由开发者进行,需要考虑测试用例对程序中语句、条件等的覆盖程度。
单元测试、功能测试、集成测试、压力测试与回归测试
  • 单元测试顾名思义,是针对程序中某一模块单元开展的测试,不考虑它与其他模块的相互作用,而只检查该单元能否正常完成功能。单元测试针对程序中的最小可测试单元(如一个方法)进行测试,这种测试粒度更细,便于定位问题。
  • 功能测试指验证程序能否正确完成预期功能,属于黑箱测试。给定一系列输入数据和对应的期望输出,只要程序在有限时间内执行完毕并且输出数据与期望输出相同,就认为通过了功能测试。
  • 集成测试指将各模块组装在一起进行测试,可以测试模块之间是否正确协作。应当尽量避免一次性的集成,而采用增量集成的方式。
  • 压力测试指让软件在极其沉重的负载条件下运行,如高并发访问、大数据量处理等极端情况,测试软件的健壮性和错误处理能力,确保软件在极端情况下仍能正确工作,或者至少不会崩溃。
  • 回归测试指迭代开发不能对软件已有的功能造成影响,需要在更改代码时测试软件已有功能的正确性。
数据构造策略

​ 在作业中构造数据测试时,主要通过随机生成数据的方式,注意覆盖各种情况(如稠密图、稀疏图,覆盖各种信息的每种操作等)。

架构设计

本单元作业的最终主要架构如下。

在这里插入图片描述

​ 本单元的架构比较简单,并且主要架构已在官方包JML中给出,需要自己设计的成分并不多。在我的设计中,除了异常处理相关的类之外,只自己创建了Graph类,用于构建图模型。

​ 图模型的维护和构建均通过Graph类完成,通过将Network中的Person抽象为结点(id)、Relation抽象为(不带权)边,实现相关的计算和查询;Network中只需要调用Graph类对象提供的接口获得结果即可,而无需带着Person对象进行沉重繁复的计算。

​ 在Graph类中进行计算也非常方便,涉及到的算法主要有两方面:并查集和BFS求最短路径。

​ 有关图的连通性的数据和方法利用并查集维护,储存并动态维护连通分支的总数blockSum。在删边时直接对并查集重建,这种方式在面对全部是删边操作的极端数据时性能较差(勉强通过了强测),一种比较好的优化方式是设置脏位并延迟重建,直到下次查询时,如果脏位被设置,再进行重建。

​ 利用讨论区同学分享的双向BFS求图中两结点间的最短路径。这部分的实现没有什么大的坑点。

​ 图中还需要储存并动态维护三元环的个数tripleSum,在增删边时对相关的结点进行遍历,判断tripleSum是否需要更改;如果完全按照JML的写法,每次查询都对整张图进行一次三重循环遍历,可想而知性能表现会是灾难性的。

性能问题

​ 本单元在hw10的强测中暴露了一次性能问题,问题出现在queryTagValueSum方法的实现上。在原本的实现中,我完全按照JML中的表述,每次查询都对本tag中管理的所有person进行二重循环遍历。这种实现性能非常糟糕,因为一个tag中可能有很多person,但只有相比之下很少一部分是有关系的,这样就导致了大量的无效遍历。进行修复时,我一方面修改遍历逻辑,外层遍历所有person,内层遍历该person的所有acquaintance,另一方面在tag中维护valueSum的值并设置脏位,在增删边、向tag中增减person时将涉及到的tag的脏位设为true,避免了每次查询都重新计算。这样一来效率就大大提升了。

规格与实现分离

​ 规格只从宏观上对数据、方法的功能进行约束限制,只保证功能的正确性而不关注具体实现。而在实现规格时,设计的正确性已经由规格保证,需要着重关注对规格的正确“翻译”,以及考虑程序运行时的性能。

Junit测试

​ 本单元的三次作业中均要求根据规格针对某个方法进行Junit测试。可以说,规格明显降低了构建Junit测试时的思维负担,不需要考虑对方法中各种逻辑的覆盖,而只需要忠实地把规格的前置条件、后置条件、不变式按照一定的模式(对\forall、\exists的验证代码都有特定模式,不管嵌套几层都可以一层一层写出来)翻译成代码,测试本身的有效性就能够得到保证。至于构造什么样的数据进行测试就是另外一个问题了,需要考虑覆盖各种边界情况。

学习体会

​ 本单元的思维负担比前两个单元降低了不少,一些图算法写起来也蛮有趣的。只是私以为本单元并没有很好地体现出JML在严谨方面的优越性,大部分方法并不需要繁复不堪的JML来保证“严谨”,反而用自然语言几句话就能表述清楚,从而导致本单元的侧重显得有些偏差,从理解体会“规格化设计”偏移到了针对各种算法的优化上。当然,并不是说不应该注重程序性能的优化,更不是否认规格化设计的重要性,只是或许可以考虑改变一下单元作业的背景,在一些不得不使用JML来保证严谨、用自然语言就极有可能留下隐患并造成难以预料的后果的场景下,让学生体会规格化设计的优越性。

  • 25
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值