一. JML语言

1. 理论基础

  首先,JML不是JAVA的一部分,它是一群研究者为JAVA设计的扩展部分,但还没有得到官方的支持。因此,JAVA编译器并不支持JML,所以要想JML起作用,只能采用类似openJML这样的第三方来编译,将JML 规格编译为运行时检查的语句,即RAC code(runtime assertion checking)。如果代码实现与其JML规格不一致,将引发运行时JML exception。

  JML遵从契约式设计范式(DBC),Design by contract是软件开发的一种方法,核心是类与其客户之间达成契约。JML是一种形式化的、 面向 JAVA的行为接口规格语言。

  推荐一篇step by step以一个比较复杂的例子来讲解JML语法和设计的教程:https://www.ibm.com/developerworks/library/j-jml/

2. 应用工具链

  • jmlrac: test for violations of assertions during execution
  • ESC/Java2: static verification; compile-time proving that contracts are never violated
  • jmldoc: javadoc-style documentation
  • jmlc: assertion-checking compiler
  • jml4c: a new JML compiler built upon the Eclipse JDT open-source platform

  上述工具很多都已经不再维护(跟不上java的升级,大多支持到java 1.5), 看大家抱怨openJML坑,就想找找有没有更好用的JML工具,结果发现openJML竟然是最好用的。

  • openJML:目前对JML支持最好,维护最积极的JML编译器了
  • jmlunit/jmlunitNG: unit testing tool

二. 部署SMT Solver

  maven+openJML+Eclipse试了一下午还是报错,命令行没试过,不知道怎么样,这一部分只好放弃了。

二. JMLUnitNG

  下述过程可复现,代码和运行结果是一致的,如果有兴趣,可以参照我的步骤在本地试一试。

  配置过程参见讨论区https://course.buaaoo.top/assignment/71/discussion/199  ,为了保证配置成功,我也是在Linux下配置。

  Graph接口方法的规格几乎全部含有 \exists 或 \old,根本搞不了,于是只能退而求其次,去验证Path类。Path类里面的\sum等语法也不支持,于是我就模仿MyPath,写了个比减法稍复杂的demo。

 // yifan/MyPath.java
package yifan; public class MyPath {
private/*@ spec_public @*/ int[] nodes; public MyPath(int[] nodeList) {
nodes = new int[nodeList.length];
for (int i = 0; i < nodeList.length; i++) {
nodes[i]=nodeList[i];
}
} //@ ensures \result == nodes.length;
public /*@pure@*/ int size() {
return nodes.length;
} /*@ requires index >= 0 && index < size();
@ assignable \nothing;
@ ensures \result == nodes[index];
@*/
public /*@pure@*/ int getNode(int index) {
return nodes[index];
} //@ ensures \result == (nodes.length >= 2);
public /*@pure@*/ boolean isValid() {
return nodes.length >= 2;
} public static void main(String args[]) {
return;
}
}

运行过程 step-by-step:

./jmlunitng yifan/MyPath.java
javac -cp jmlunitng.jar yifan/**/*.java
./openjml -rac yifan/MyPath.java
javac -cp jmlunitng.jar yifan/MyPath_InstanceStrategy.java
java -cp jmlunitng.jar yifan.MyPath_JML_Test

运行前目录

运行后目录

运行结果

结果讨论

  • MyPath(null),MyPath.java中会调用length,错误,意料之中;
  • 明明已经requires index>=0了,为什么生成的测试例子里还会有负数?就算刚开始nodes=new int[10],避免nodes为null的情况还是这种结果;
  • 似乎JmlUnitNG只会生成int的边界值和0,不管requires? 这只是我的猜想。

有个问题需要讨论一下:

  • 为什么不写成
//@ public instance model non_null int[] nodes;
private ArrayList<Integer> nodes;

openJML会把规格和实现里的nodes当成一个nodes,会报错。

那这么写不就行了吗?

//@ public instance model non_null int[] nodes;
private ArrayList<Integer> myNodes;

非也,会报下述错误

yifan/MyPath.java:6: 警告: JML model field is not implemented: nodes
//@ public model int[] nodes;
^

nodes没实现?对的。要想解决这个问题,就得写抽象函数,可以看看这篇论文https://digitalcommons.utep.edu/cgi/viewcontent.cgi?referer=https://www.google.com.hk/&httpsredir=1&article=2073&context=cs_techrep ,我大概写了个抽象函数,没bug,但也没起作用,还是报nodes没实现的错误,所以这里就不贴我的抽象函数了。

从上图可以看到如果不实现nodes,大多数方法都被skip掉了。

三. 架构设计

1. 第一次作业

直接继承接口,简单地实现了两个类。

2. 第二次作业

为了更改方便,直接ctrl+v把MyPathContiner的代码复制到MyGraph。

3. 第三次作业

由于第二次作业比较复杂,再去动很可能出bug,于是在写第三次作业的时候对于第二次作业已有的代码我一行都没动,只是在MyGraph类里加了求连通块个数的Public的函数。这样一来bug少了,但新加的架构和已有的架构看起来很不协调。

看了std码之后,惊呼:我之前竟将所有代码都直接放在src文件夹下。好的分层设计应该像标程一样,起码得有多个文件夹吧,比如base,core,util,grpha等。

四. bug和修复情况

三次作业均无bug。

五. 心得体会

撰写:规格的撰写用到了很多离散数学的知识,掌握常见的几种模式后,就能够比较容易地写出一些简单函数的规格。以我目前的水平看,写代码还是要比写规格来得容易。

理解:实操中,我实际上是先看的指导书,对于含混的地方,(比如起点和终点相同的情况下,算不算换乘,最小费用算多少?同一路径中如果有环该怎么算?)我会去详细阅读规格,因为规格严谨的描述了某一个方法该干什么。(但这次直觉上的理解实际上更靠谱,比如同一路径中有环的情况,直觉上的理解是不用非得绕着环走一圈多余的路,但死扣规格,确实得绕,事后证明是老师或助教的规格写错了)。

JML和JmlunitNG:JML设计期望太高,其目的是写出规格后,就可以自动生成测试用例,还可直接检查代码是否准确实现了规格;但相关工具链及其难用,功能及其有限,目前我只能写个简单的demo探索一下它的性质,体验一下整个流程。

OO第三单元总结--根据JML写代码的更多相关文章

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

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

  2. OO第三单元作业总结

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

  3. OO第三单元个人总结

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

  4. oo第三单元学习总结

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

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

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

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

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

  7. OO第三单元作业(JML)总结

    OO第三单元作业(JML)总结 目录 OO第三单元作业(JML)总结 JML语言知识梳理 使用jml的目的 jml注释结构 jml表达式 方法规格 类型规格 SMT Solver 部署JMLUnitN ...

  8. OO第三单元——JML规格化设计

    OO第三单元--JML规格化设计 JML语言的理论基础以及应用工具链情况 理论基础 JML是对JAVA程序进行规格化设计的一种表示语言,是一种行为接口规格语言.JML整合了Java和JAVAdoc,并 ...

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

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

随机推荐

  1. 植物大战僵尸游戏的开发(python)

    装备东西: 搭建好python环境, 四张图片,(背景图片,炮弹图片,僵尸图片,豌豆图片),就ok了  没有安装pygame的需要进行安装  pip install pygame 参考视频 # 植物大 ...

  2. Python3简明教程(四)—— 流程控制之分支

    我们通过 if-else 语句来做决定,来改变程序运行的流程. if语句 语法如下: if expression: do this 如果表达式 expression 的值为真(不为零的任何值都为真), ...

  3. New Arrival MB SD Connect Compact 5 (MB SD C4) Star Diagnosis

    MB SD Connect Compact 5 has same function as SD C4 but with new design, support both cars and trucks ...

  4. python爬虫---实现项目(二) 分析Ajax请求抓取数据

    这次我们来继续深入爬虫数据,有些网页通过请求的html代码不能直接拿到数据,我们所需的数据是通过ajax渲染到页面上去的,这次我们来看看如何分析ajax 我们这次所使用的网络库还是上一节的Reques ...

  5. 洛谷 3519 && bzoj 2213 Difference

    联考考试考到了这个题,随机化40分,现在来秒掉它吧. 题意: 给一个字符串,求其中的一段,使得出现次数最多的字符与出现次数最少的字符的出现次数之差最大. 输入输出样例 输入样例#1: 复制 10 aa ...

  6. STL源码分析-iterator(迭代器)

    1. GOF 迭代器设计模式 前面一篇文章有写到stl_list的实现,也实现了一下相应的iterator,但是后面觉得,实现具体容器之前有必要介绍一下iterator(迭代器) .那么迭代器是什么呢 ...

  7. UVA12633 Super Rooks on Chessboard

    题目描述 题解: 第一眼满眼骚操作,然后全部否掉. 然后屈服于题解,才发现这题这么执掌. 首先,如果这个东西是普通的车,那我们可以记录一下$x,y$的覆盖情况,然后减一下; 但是这个可以斜着走. 所以 ...

  8. [模板] Exgcd

    求解一组ax+bc=gcd(a,b) #include<iostream> #include<cstdio> using namespace std; int exgcd(in ...

  9. 第三讲:post-processsing with vcs+ files

    1,dump wave  by system function $vcdpluson(level_number,module_instance,....|net_or_reg) $vcdplusoff ...

  10. (二十)python 3 匿名函数

    匿名函数lambda Python使用lambda关键字创造匿名函数.所谓匿名,意即不再使用def语句这样标准的形式定义一个函数.这种语句的目的是由于性能的原因,在调用时绕过函数的栈分配.其语法是: ...