2019_BUAAOO_第三单元总结
一、JML理论基础及应用工具链情况梳理
JML基础语法
1.requires:定义方法的前置条件,即该方法执行前需要满足的条件;
2.assignable:副作用范围限定,列出这个方法可以修改的类成员属性,assignable \nothing表示这个方法不对任何成员属性进行修改。
3.ensures:定义了后置条件,即方法执行后需要满足这条语句的条件。
4.\result:表示方法返回值
5.\old(expr):表示方法执行前表达式expr的取值
6.public normal_behavior:表示正常时的方法行为
7.public exceptional_behavior:表示异常时的方法行为
8.signals:当expr为true时抛出异常
9.signals_only:只要满足前置条件就抛出相应异常
10.\forall表达式:全称量词,表示对于给定范围内的元素,每个元素都满足相应的约束。
11.\exists表达式:存在量词,表示对于给定范围内的元素,存在某个元素满足相应的约束。
应用工具链
OpenJML:检查规JML语言的语法并验证基本逻辑正确性
JUnit:对JML规格进行单元测试
SMT solver:通过静态分析代码,检查代码是否满足规格
二、部署SMT solver
三、部署JMLUnitNG/JMLUnit
编写openjml与jmlunitng文件:
生成测试文件并进行测试:
MyPath.java测试结果:
其中constructor与compareTo未能通过测试,因为测试数据与require的条件不符
四、架构分析
第一次作业
MyPath中使用ArrayList保存节点,并使用HashSet保存不同的节点,方便调用getDistinctNodeCount方法。
MyPathContainer中使用了2个HashMap分别来保存pathId与path,建立二者之间的对应关系。再创建了一个HashMap用来储存Node与NodeCnt,使得调用getDistinctNodeCount方法更加方便。这3个HashMap都会在调用AddPath与RemovePath的时候进行更新。
第二次作业
第二次作业我对于MyPathContainer直接进行了重构。
第二次作业是要建立一个图结构。由于题目要求保证在任何时刻图中的节点数都不超过250,因此考虑用250*250的二维数组来储存图。由于节点取值在int整型范围类,因此需要将节点映射到[0,249]区间。这里我通过HashMap存储映射关系,因为映射关系需要多次查找,使用HashMap可以减少查找耗时。
查找最短路径我使用floyd算法,每次在AddPath或者RemovePath之后就更新图,并使用floyd算法更新每个节点之间的最短路径长度,这样可以多次调用getShortestPathLength方法而不会超时。
第三次作业
第三次作业中我的MyRailwaySystem继承了MyGraph类,对其中的一些方法进行了重写。
第三次作业要建立一个地铁交通系统,要求实现给出两个节点,能够正确计算出两个节点之间的最低票价、最少换乘次数、最低不满意度以及连通块数目。求连通块数目我使用并查集的方法,而最低票价、最少换乘次数、最低不满意度依然使用floyd方法。总体上与第二次作业类似。
五、BUG修复
第一次作业
第一次作业BUG出现在getDistinctNodeCount方法上,在进行AddPath与RemovePath时计算出错,导致最后在统计出的节点数目有误。
第二次作业
第二次作业BUG在于HashMap的key选取有误,有时会出现不同数据具有相同key的情况。
第三次作业
第三次作业未发现BUG。
六、心得体会
本单元的主题是规格。通过阅读JML规格,测试人员可以从设计层面判断方法的正确性;而且,由于规格的严谨与简洁,开发人员不仅能够正确理解规格而不会产生歧义,还能专注于代码的编写。掌握JML能够有利于我们培养了规格设计与规范编程的思想,这对我们日后进行面向对象开发大有帮助。