第三单元总结
第三单元作业目的在于培养JML规格思想,通过JML而不是模棱两可的自然语言对需求进行描述,让项目规格化,方便了需求方和实现方.
对于此次作业直观的感受就是__轻松了许多__,函数需要实现的功能以及要求都写明在了JML中,换句话说顶层设计已经给出,只需要按照要求进行开发即可.
一、实现策略分析
本单元三次作业的实现流程基本相同,包括以下几步:
通读规格
规格既然已经在JML中写明,第一步自然是需要通读JML的要求,对项目以及迭代新增的功能有个整体的了解;在阅读JML的过程中同时可以构思实现的框架,例如要求的储存容器的选择,功能函数的实现思路等.
实现功能
阅读完规格要求之后即着手基于上一步对各个函数的理解和编写类和方法具体实现;通过第一步可以了解到各个异常类以及Person等元素类更多是作为容器,需要实现的方法基本都是获取内部信息,也就是getXXX(),或者是异常类的print()等.实现时我选择从这些细枝末节开始,然后再实现Network中的功能方法.
在实现过程中对于部分复杂函数给予更多关注和思考.
测试完善
完成代码整体框架之后针对方法功能构造数据进行测试,并针对个别性能瓶颈方法进行优化.
测试策略
由于笔者缺乏自动测试相关的经验,也学无余力进行相关的学习,故主要方法还是手动构造数据进行测试.
样例构建
程序有几个层次需要进行测试:正常工作,工作正确,性能满足需求.
第一点即是程序运行不能够出错,主要是各种疏忽导致的NullPointerException.笔者构造样例时不够全面,在第三次作业中没有对EmojiList进行删改,没有发现使用Iterator时若需要删除元素时需要使用Iterator.remove()方法进行删除而不能直接在元Map/Set上进行删除,否则会抛出异常的bug;
第二点即是字面义,在构造验证正确性样例时需要对JML规格有足够的理解,不然构造的样例只能是程序工作正常的再验证以及自己对规格的错误理解的相互证明.在构造正确性验证样例时需要在第一步理解规格时下足够功夫.
第三点其实没有特别构造样例必要,解决这一点更需要下边的方法.
阅读代码
在使用样例一件测试以外就需要直接阅读代码分析方法实现是否符合功能,而且复杂函数的性能也只能阅读代码分析其复杂度进行优化。
容器选择和使用
通读JML可以发现基本所有的元素都有唯一id与之对应,故作业实现中主要采用hashmap进行元素的储存管理,采用hashmap也可以方便地根据输入的id判断是否需要抛出异常,而不需要遍历所有元素了。
同时对于获取名字排名的函数采用了treemap进行管理,利用treemap的自动排序的特性减轻了自行实现排序的负担;同时这一部分为了实现对重名的支持,采用了treemap套hashset的方式储存。
性能问题分析
本次作业性能问题主要集中于个别函数。
第一次作业
第一次作业中仅有一个复杂函数iscircle,这个函数需要返回给定的两个person是否连通。分析可以知道如果每次查询都重新计算一遍会带来很大的性能负担,故此处采取了一定措施进行处理,具体为每个person内部维护一个hashset,内部保存自身能够连通的所有person。每次添加relation时说明两人能够连通的person需要合并,故进行addall操作即可。调用iscircle方法进行查询时只需查询指定person是否在两者的连通集中即可。
第二次作业
由于时间安排不当未能及时完成,故全部在第三次作业中进行说明
第三次作业
第三次作业复杂函数有两个,分别是queryblocksum以及sendindirectmessage。对于前者采用了和第一次作业中类似的实现方式,也就是每次向组中增删人员时更新组中维护的一个blocksum值。这一个实现有一个坑,也就是在组中两个person之间添加relation时需要更新对应的组的blocksum。
对于sendindirectmessage则是一个传统的寻找最短路算法,这里采用的是Dijkstra算法,具体实现时构建了一个hashset markedperson,一个hashmap idtoperson以及一个treemap unmarkedperson。由于笔者不熟悉优先队列的实现故采用这种实现方式,利用treemap仿照有限队列,通过firstvalue来模拟pop操作等。
单元感想
本次单元主要目的是了解并熟悉JML语法,并掌握规格化的项目管理交付模式。说实话这次作业难度确实不高,实现起来比较轻松。
在完成作业的过程中对规格化的工程管理的优越性有了深刻体会,具体来说就是前两个单元那般反复研读指导书以及大班群中激烈探讨的现象不存在了。出现正确性bug时读回JML描述就能发现确实是自己阅读不够仔细导致的理解偏差。这样的规格化描述不仅对实现有了指导,同时也给测试带来了启发,构造测试数据时就可以根据JML描述中的ensure进行构造,提升了测试效率。