JML理论基础

jml是基于一阶谓词逻辑来对类进行形式化描述的语言,jml语言通过表达式、方法规格、类规格三个部分来进行描述。其中表达式是在java语言的基础上扩展了非修改类型的表达式;方法规格中包括了前置条件、后置条件、副作用作用范围三个部分;类规格包含不变式和状态变化约束两个部分。jml相较于自然语言而言,可以消除歧义,同时配合相关工具进行形式化验证。

jml方法规格写法举例

 /*@ public normal_behavior  //正常行为规格
@ requires (\exists int i; 0 <= i && i < acquaintance.length; //前置条件
@ acquaintance[i].getId() == person.getId());
@ assignable \nothing; //副作用范围
@ ensures (\exists int i; 0 <= i && i < acquaintance.length; //后置条件
@ acquaintance[i].getId() == person.getId() && \result == value[i]);
@ also
@ public normal_behavior
@ requires (\forall int i; 0 <= i && i < acquaintance.length;
@ acquaintance[i].getId() != person.getId());
@ ensures \result == 0;
@*/

JML工具链

目前能用的jml工具链不多,我在本单元使用了openjml和jmlunitng两种工具

openjml使用

openjml使用过程中槽点相当之多,包括jdk版本、大量报错,静态检查巨慢等...

除了用官网的简单代码的测试外,我是用魔改了的MyPerson类来进行了静态测试,结果如下:

可以看到有很多奇怪的报错,后面我用原版的MyPerson执行

java -jar $opjml/openjml.jar  -cp ../../explaintion/package/offical.jar -esc MyPerson.java

结果如下

可以看到时间相当长,而且报了7个奇怪的错误,怀疑可能是opjml支持性的问题

为了证明opjml的效果,我改了一下MyPerson的getId()方法

结果如下

可以看到静态检查确实发现了问题,但是有价值的错误信息混在大量无意义的信息中无疑加大了阅读难度

openjml总结

虽然opjml能够发现问题,但是时间长、报错多的问题使得它并不是特别实用

jmlunitng使用

jmluniting的使用由于Group一直报错,我就自己写了一个MainClass来测试。

MainClass代码如下:

public class MainClass{
private /*@spec_public@*/ int id;
private /*@spec_public@*/ String s;
/*@ assignable id;
@ ensures id == \old(id)+1;
@*/
public void addid(){
id++;
} /*@ requires num>=0;
@ assignable id;
@ ensures id == \old(id)+num;
@*/
public void main(int num){
if(num<0||num>150) return;
for(int i=1;i<=num;i++){
addid();
} } /*@ requires ins!= null;
@ assignable s;
@ ensures !s.equals(ins);
@*/
public void setString(String ins){
this.s = ins;
} /*@ requires ss != null;
@ assignable \everything;
@ ensures id == 0 && s==ss;
@*/
public MainClass(String ss){
s=ss;
id=0;
} }

使用如下的指令来进行测试:

java -jar %opjml%/jmlunitng.jar MainClass.java
javac -cp %opjml%/jmlunitng.jar *.java
java -jar %opjml%/openjml.jar -rac MainClass.java //生成openjml的断言
java -cp .;%opjml%/jmlunitng.jar MainClass_JML_Test
pause

运行结果

可以看到主要对于边界数据进行了一些测试,其实按照官方文档的说法是可以在生成的代码里面添加自己想要测试的数据的,但是这样的化其实会比写junit好一点,自己写junit的话如果理解错误就凉凉了。

代码分析

第一次作业

非常简单,自己写了一个并查集,其余的就是一步步按照jml来,这也为后来的错误埋下了伏笔

第二次作业

同样非常简单,就是把理按照jml一步步来,把某些事件复杂度大的方法稍加修改,结果由于第一次的getPerson采用遍历的方式,导致强测直接原地爆炸,强测0分。

第三次作业

这次作业复杂一些,我先理解完了jml后然后再按照自己的方法来写,其中把queryAgeSum、queryMiPath、queryStrongLink三个方法的实现封装在了Work里面。

测试&bug分析

在这个单元中可以说吃了测试不全的大亏,导致三次作业分数都非常不理想。

黑盒测试

黑盒测试是我这次在互测中采用的主要方法,我的测试主要由两部分构成,一部分是数据生成器,一部分是对拍器。对排器比较简单,主要讲讲数据生成生成。我本来是随机生成的,后来第一次作业观摩了房内某个基本道道全中的dalao的数据,发现采用不同权重的随机数,对于权重高的数据每次生成一小批,例如

A
A
A
B
C
C
C
B

这种,同时尽可能多的把图变得稠密,这样也能增加数据的强度。

在本单元的测试中,前两次我都是用黑盒测试来互相测试,第三次我利用黑盒和同学的代码进行对拍。比较血亏的是我以为queryAgeSum的缩写是qas结果导致本地一个数组开小的错误没有测出,互测中数据强度也不太够,只刀了4个人。

白盒测试(Junit)

本单元,我觉得Junit测试有一定风险,如果对jml理解错误就会导致一些比较尴尬的情况。我觉得junit测试方面有两个心得,一个是要尽可能多的覆盖掉所有代码路径,这样能够比较大限度地判断已经完成代码逻辑与没有问题。另外一个方面是尽可能多地覆盖数据的情况,对数据进行分类,比如采用判断表法或者数据等价类划分能够很好地解决黑盒测试中难以生存的某些边界数据问题。

总结

在本单元的学习中,我对于形式化验证的方法有了一定了解,但也认识到形式化验证还存在效率不高等问题。同时本单元的连续多次踩坑,也让我更加注重测试的重要性,对测试代码的迭代也让我了解了许多测试的方法。当然本单元学习还是有一些遗留问题,比如为什么jml的是如此设计的,为什么通过前置和后置条件副作用就能完美地描述一个方法,这其实有赖于对于公理逻辑系统的理解,希望以后有空能去看看相关论文深入了解下。

OO第三单元小结的更多相关文章

  1. oo第三单元学习总结

    OO第三单元小结 一.JML语言理论基础及工具链梳理 在本单元我们学习了JML语言的一些基础知识,能够让我们看懂简单的JML规格并写出对应代码, 主要用到的知识点有:   1.requires 该子句 ...

  2. OO第三单元作业总结

    OO第三单元作业总结--JML 第三单元的主题是JML规格的学习,其中的三次作业也是围绕JML规格的实现所展开的(虽然感觉作业中最难的还是如何正确适用数据结构以及如何正确地对于时间复杂度进行优化). ...

  3. 规格化设计——OO第三单元总结

    规格化设计--OO第三单元总结 一.JML语言理论基础.应用工具链 1.1 JML语言 ​ JML(java modeling language)是一种描述代码行为的语言,包括前置条件.副作用等等.J ...

  4. 【OO学习】OO第三单元作业总结

    [OO学习]OO第三单元作业总结 第三单元,我们学习了JML语言,用来进行形式化设计.本单元包括三次作业,通过给定的JML来实行了一个对路径的管理系统,最后完成了一个地铁系统,来管理不同的线路,求得关 ...

  5. OO第三单元(地铁,JML)单元总结

    OO第三单元(地铁,JML)单元总结 这是我们OO课程的第二个单元,这个单元的主要目的是让我们熟悉并了解JML来是我们具有规格化编程架构的思想.这个单元的主题一开始并不明了,从第一次作业的路径到第二次 ...

  6. OO第三单元——基于JML的社交网络总结

    OO第三单元--基于JML的社交网络总结 一.JML知识梳理 1)JML的语言基础以及基本语法 JML是用于java程序进行规格化设计的一种表示语言,是一种行为接口规格语言.其为严格的程序设计提供了一 ...

  7. OO第三单元作业——魔教规格

    OO第三单元作业--魔教规格 JML的理论基础和相关工具   JML(Java Modeling Language,Java建模语言),在Java代码种增加了一些符号,这些符号用来标志一个方法是干什么 ...

  8. OO第三单元个人总结

    OO第三单元个人总结 JML理论与基础与应用工具链 JML是什么? Java建模语言(JML)是一种行为接口规范语言,可用于指定Java模块的行为 .它结合了Eiffel的契约设计方法 和Larch ...

  9. 2020 OO 第三单元总结 JML语言

    title: 2020 OO 第三单元总结 date: 2020-05-21 10:10:06 tags: OO categories: 学习 第三单元终于结束了,这是我目前为止最惨的一单元,第十次作 ...

随机推荐

  1. 使用docker mediawiki,搭建网页wiki

    我只是想做一个大家都能访问的wiki,用于成员间共享和维护一些文档.找到了docker的mediawiki,这里记录一下我怎么搭的吧. 首先,如果你在一个局域网里,有公用的可以访问的服务器,那可以直接 ...

  2. bluestein算法

    我们熟知的FFT算法实际上是将一个多项式在2n个单位根处展开,将其点值对应相乘,并进行逆变换.然而,由于单位根具有"旋转"的特征(即$w_{m}^{j}=w_{m}^{j+m}$) ...

  3. 力扣832. 翻转图像-C语言实现-简单题

    题目 传送门 文本 给定一个二进制矩阵 A,我们想先水平翻转图像,然后反转图像并返回结果. 水平翻转图片就是将图片的每一行都进行翻转,即逆序.例如,水平翻转 [1, 1, 0] 的结果是 [0, 1, ...

  4. sql语句的练习,已练习的会以绿色标注!!!

    表架构 Student(S#,Sname,Sage,Ssex) 学生表 Course(C#,Cname,T#) 课程表 SC(S#,C#,score) 成绩表 Teacher(T#,Tname) 教师 ...

  5. 一文读懂什么是kubernetes?

    kubernetes概述 kubernetes面世不过短短几年时间,kuberenetes已经成为容器编排领域事实上的标准,无论是公有云,私有云或混合云,kubernetes都将作为一个为任何应用,任 ...

  6. Cannot resolve MVC View

    在搭建springboot项目时报错:Cannot resolve MVC View "index" 那是因为在pom中缺少依赖 <dependency> <gr ...

  7. JUC-ThreadLocal

    目录 ThreadLocal ThreadLocal测试 ThreadLocal类结构 前言 多线程访问同一个共享变量的时候也别容易出现并发问题,特别是在多线程需要对一个共享变量进行写入的时候.为了保 ...

  8. Redis-第十章节-链表

    目录 数组和链表 链表 对比 总结 1.数组和链表 数组: 数组会在内存中开辟一块连续的空间存储数据,这种存储方式有利也有弊端.当获取数据的时候,直接通过下标值就可以获取到对应的元素,时间复杂度为O( ...

  9. 剑指 Offer 33. 二叉搜索树的后序遍历序列 + 根据二叉树的后序遍历序列判断对应的二叉树是否存在

    剑指 Offer 33. 二叉搜索树的后序遍历序列 Offer_33 题目详情 题解分析 本题需要注意的是,这是基于一颗二叉排序树的题目,根据排序二叉树的定义,中序遍历序列就是数据从小到大的排序序列. ...

  10. HDOJ-3065(AC自动机+每个模板串的出现次数)

    病毒侵袭持续中 HDOJ-3065 第一个需要注意的是树节点的个数也就是tree的第一维需要的空间是多少:模板串的个数*最长模板串的长度 一开始我的答案总时WA,原因是我的方法一开始不是这样做的,我是 ...