第三单元博客作业
一、梳理JML语言的理论基础、应用工具链情况
- JML语言
(1)JML表达式
\old(expr):表示expr在方法执行前的值
\result:表示方法的返回值
\not_assigned:表示括号中变量在方法执行过程中是否被赋值
\nonnullelements(container):表示container对象中存储的对象没有null
\type(type):返回type对应的class
\typeof(expr):返回expr对应返回的准确类型
\forall:全称量词修饰的表达式,对于给定范围内元素,每个元素都满足相应约束
\exists:存在量词修饰表达式,存在元素满足相应约束
\sum,\product,\max,\min,\num_of:给定范围内表达式求和、求连乘积、最大值、最小值和满足相应条件取值的个数
<:子类型关系操作符
<==>,<=!=>:等价不等价操作符
==>:推理操作符
(2)方法规格
前置条件:requires
后置条件:ensures
副作用范围限定:可赋值:assignable
可修改:modifiable
方法异常行为:signals
(3)类型规格
不变式限制:在所有条件下都要满足的表达式
约束限制:对于可见状态和当前可见状态的约束
-
工具链
OpenJML:专门针对JML语言设置的验证工具,它可以检查JML规格语法的正确性,也可以根据方法的JML规格和具体实现来初步验证一个方法的实现是否其符合规格。
JMLUnitNG:可以自动生成测试数据来检验代码是否正确。
JUnit:单元测试工具,我们需要自己针对代码设置规范化样例。可以比较有针对性地检验单个方法的正确性。
二、部署STM Solver
为了不报错我把所有文件放到了一个文件夹中。
使用如下命令生成结果。
我选择了3个方法进行检查,分别是:delFromGroup,queryMinPath和queryStrongLinked
对于delFromGroup,由于我在程序中使用的是hushmap储存的groups和people,所以它会报如下错误:
test/MyNetwork.java:309: 错误: 需要数组, 但找到HashMap
@ requires (\exists int i; 0 <= i && i < groups.length; groups[i].getId() == id2) &&
test/MyNetwork.java:310: 错误: 需要数组, 但找到HashMap
@ (\exists int i; 0 <= i && i < people.length; people[i].getId() == id1) &&
并且由于是hushmap,他也无法找到一个外部可见的length属性:
test/MyNetwork.java:310: 错误: An identifier with private visibility may not be used in a requires clause with public visibility
@ (\exists int i; 0 <= i && i < people.length; people[i].getId() == id1) &&
对于其他两个方法报错也都大同小异。
以下是部分报错信息:
三、部署JMLUnitNG
只用测试Group的话只要保留MyPerson类和MyGroup类即可。我将其重新命名为Person和Group,并去除了@override和implement实现,以保证代码可以跑通。
我们可以看到,有一些测试时没有通过的,基本上是一些边缘数据和添加null。对于null的相关测试没有通过是因为我们在上层调用的时候已经排除了这样的数据,如果想增加程序的鲁棒性可以在这里再进行一下处理。对于边界上的大数,真是防不胜防。我们可以从输入数据上进行限制。事实上我们的指导书上对于各个数据的范围也有一个规定,所以实际情况下不会出现这种情况。
四、作业框架设计
这是我第三次作业的锁也框架设计。除了要用优先队列的时候加入了Node类储存信息,基本上就是直接根据jml写的。在写的过程中,私以为这样写层次也是比较清晰的,因为我们的需求基本上是由MyNetwork完成的。而如果Group和Person都是由MyNetwork管理的,所以就直接由Network来对他们进行操作了。但这样也造成了MyNetwork中代码较多的问题。
五、bug相关
-
本人bug
本单元的三次作业在强测中并没有出现bug
-
发现bug
课下检查正确性是通过与同学对拍实现的。在互测中发现bug基本上是基于阅读代码和构造测试单一方法的数据进行判断的。
六、心得体会
通过这个单元的学习,我们学习到了jml的相关知识,能够进行一定的jml构造以及根据jml编写代码。
总的来说,这个单元相对于前两个单元来说相对要简单一些。因为有jml,所以只要根据jml编写代码即可。