作者:包子F3R | 来源:互联网 | 2024-10-19 11:48
JML基础梳理及工具链JML的全称是JavaModelinglanguage,即Java建模语言。JML是一种行为接口规格。它为严格的程序设计提供了一套行之有效的方法。通过JML不仅可以
JML基础梳理及工具链
JML的全称是Java Modeling language,即Java建模语言。JML是一种行为接口规格。它为严格的程序设计提供了一套行之有效的方法。通过JML不仅可以基于规格自动构造测试样例,还可以以静态方式检查代码对规格的满足情况。
一、注释结构
行注释://@annotation
块注释:/*@ annotation @*/
二、JML表达式
(1)原子表达式
\result
表达式:表示一个非 void 类型的方法执行所获得的结果,即方法执行后的返回值。
\old(expr)
表达式:用来表示一个表达式expr在相应方法执行前的取值。
\not_assigned(x,y,…)
表达式:用来表示括号中的变量是否在方法执行过程中被赋值。
\not_modified(x,y,…)
表达式:限制括号中的变量在方法执行期间的取值未发生变化。
\nonnullelements(container)
表达式:表示container对象中存储的对象不会有null。
(2)量化表达式
\forall表达式
:全称量词修饰的表达式,表示对于给定范围内的元素,每个元素都满足相应的约束。
\exists
表达式:与forall表达式使用结构类似,为存在量词修饰的表达式,表示对于给定范围内的元素,存在某个元素满足相应的约束。
\sum
表达式:返回给定范围内的表达式的和。
\product
表达式:返回给定范围内的表达式的连乘结果。
\max
表达式:返回给定范围内的表达式的最大值。
\min
表达式:返回给定范围内的表达式的最小值。
\num_of
表达式:返回指定变量中满足相应条件的取值个数。
(3)集合表达式
集合构造表达式:可以在JML规格中构造一个局部的集合(容器),明确集合中可以包含的元素。
(4)操作符
(1) 子类型关系操作符: E1<:E2 ,如果类型E1是类型E2的子类型(sub type),则该表达式的结果为真,否则为假。
(2) 等价关系操作符: b_expr1<==>b_expr2 或者 b_expr1<=!=>b_expr2 ,这两个表达式的意思是 b_expr1==b_expr2 或者 b_expr1!=b_expr2 。
(3) 推理操作符: b_expr1==>b_expr2 或者 b_expr2<==b_expr1 。
(4) 变量引用操作符:JML提供了几个概括性的关键词来引用相关的变量。\nothing指示一个空集;\everything指示一个全集.
三、方法规格
(1) 前置条件:requires
(2)后置条件:ensures
(3)副作用范围限定:assignable或modifiable
四、类型规格
从课程要求来看有
(1)不变式限制
(2)约束限制
部署JMLUnitNG/JMLUnit及实现自动生成测试样例
针对如下的compare代码
利用JMLUnitNG生成测试样例:
可以看到自动生成的测试样例包括了正数,负数,0以及边界条件的各种组合。覆盖非常的全面。
架构设计分析
第一次作业直接填写方法,没有太多自己设计的地方。
第二次作业需要设计一个图结构来计算最短路径。
增加了一个数点个数的HashMap,来判断增删路径后结点是否还存在。
增加了一个数路径的HashMap,来判断增删路径后边是否还存在。
增加了记录一个点与哪些点连接的HashMap。
第三次作业比较麻烦。我参考的是讨论区的拆点法,然后用迪杰斯特拉求解最短路径,特殊的,在求解最少换乘时采用的是染色算法。
bug分析及修复情况
第一次作业的bug很惨。当时比较大小只写了同长度比较大小的算法,备注了三个?,然后忘了没写完,就把备注删了,导致最后提交的时候出现了bug。
第二次作业难度依旧很小。没有什么bug。互相测试时出现一个判断大小的bug,原因是一个判断条件写错了。
第三次作业比较难。拆点之后用的迪杰斯特拉算法。但是我并没有完全按照讨论区的做法,导致算法上有误。在修修补补多处之后仍然无济于事的我最后选择了重构。
心得体会
OO作业每次发布的时候都会觉得好难,感觉无法完成。把作业指导书反复地读几遍之后,任务看起来似乎又很简单,只要做到A,B,C三点问题就解决了。然而实际操作的过程中,A,B,C似乎轻而易举地解决了,但是一旦把代码跑起来,就发现漏洞百出,各种莫名其妙的bug。然后一环一环地测试,每一小步都会发现问题。码代码贵在细节。无论哪里错了,结果都会相去甚远。