目录

  • 写在前面
  • JML理论基础
  • JML工具链
  • JMLUnitNG的使用
  • 架构设计
  • Bug分析
  • 心得体会

写在前面

OO的第三单元学习结束了,本单元我们学习了如何使用JML语言来对我们的程序进行规格化设计。并对openjml以及JMLUnitNG、JUnit等工具的使用有了初步的了解。

JML理论基础

注释结构

JML以javadoc注释的方式来表示规格,每行都以@起头。

JML表达式

JML表达式有一下几种:

  • 原子表达式:如\result\old等。
  • 量化表达式:如\forall\exists等。
  • 集合表达式:这个不怎么常用,比如new JMLObjectSet {Integer i | s.contains(i) && 0 < i.intValue()}
  • 操作符:常用的包括等价关系<==>,推理关系==>,变量引用\nothing等。

JML方法规格

  • 前置条件:通过\requires P表示,是对方法调用者的要求,意思是调用者确保P为真。
  • 后置条件:通过\ensures P表示,是对方法实现者的要求,意思是方法实现者确保方法执行返回结果一定满足谓词P的要求,即确保P为真。
  • 副作用范围限定:通过\assignable x表示,其中x为此方法可以更改的对象,极端情况为\nothing\everything
  • signals子句:一般用来限制抛出异常的条件。

JML类型规格

  • 不变式invariant:是要求方法在所有可见状态下都必须满足的特性。
  • 状态变化约束constraint:是要求对象的状态在变化时也要满足的约束。

JML工具链

  • 使用OpenJML对实现的代码进行检查:包括JML语法静态检查,代码静态检查,运行时检查。
  • 使用JMLUnitNG根据JML语言自动生成TestNG测试。

JMLUnitNG的使用

针对如图的compare方法,利用JMLUnitNG生成测试样例:

生成的样例点:

可以看到,自动生成的样例点对方法的各种边界情况进行了测试,包括正数和正数,正数和负数,负数和负数,还有0的情况,如果我们写的方法出现了加减法溢出的问题,这些测试样例也都会检测出来并报Failed。

架构设计

第九次作业

本次作业主要内容是实现Path和PathContainer,其中主要的查询方法是不同节点数的个数,我使用了均摊策略,即把查询的时间复杂度平均到addPath和removePath中,每次添加或删除路径时更近存放节点的HashMap,这样可以实现O(1)复杂度的查询方法。

第十次作业

本次作业是实现Path和Gragh,而Gragh是继承了PathContainer的,所以我在写的时候也使用了继承。本次作业的主要查询方法是最短路径,所以我重写了PathContainer里面的addPath和removePath方法,在添加删除路径的时候重新建图,并更新最短路径。对于PathContainer里面的其他方法,直接继承使用。

本次作业我使用的方法:

  • Floyd多源最短路算法
  • HashMap嵌套实现邻接矩阵的存储

第十一次作业

本次作业是实现Path和RaiwaySystem,其中RailwaySystem继承了Gragh。本次作业涉及到加权图以及换乘的代价,所以算法难度较大。在拓展的时候,我还是重写了addPath和removePath方法,并添加了几个方法来计算新的最短路问题。

本次作业我使用的方法:

  • 分层的Floyd算法:即图结构变更之后,先对每条路径内部的点使用Floyd算法更新最短路,然后加上换乘代价,再对所有路径中的所有节点使用Folyd算法,即可实现带换乘代价的最短路算法。
  • 静态数组存储结构:即用二维静态数组替代HashMap嵌套来实现邻接矩阵的存储,这样做的优点是计算速度,存取速度快,减少时间复杂度。缺点是不好维护和拓展。如果不是追求极致性能,还是慎用此类方法。
  • 计算连通块的数量:使用并查集。

Bug分析

第九次作业

本次作业中,我的bug是减法溢出,具体是因为:我在实现compareTo方法的时候,采用的是两个整数相减来判断大小。而如果出现减法溢出的情况,那么判断结果跟正确答案是正好相反的。为此我也炸了强测+互测的20多个点。

本次作业中,同组同学的bug有:查询方法复杂度过高从而导致TLE,还有跟我一样的减法溢出问题。

第十次作业

本次作业中我的程序未被发现bug,我也未发现其他同学的bug

第十一次作业

本次作业中我的程序也未被发现bug,我也未发现其他同学的bug

心得体会

规格撰写方面

本单元让我体会到真正参与编写一个工程的感觉,即在一整个工程中分出一小部分让我们完成,并且要符合工程的要求。在这种情况下,JML语言体现出非常大的作用,它非常方便,不关注方法的实现过程,只专注于前因后果,因为只有前因后果才是把整个工程的思路贯穿起来的渠道。

此外,我也尝试过自己根据已有方法编写JML,也是有很大难度的,一定程度上,比我们写代码要难得多,这也体现出来规格化的重要性。

JUnit初体验

针对本单元各种小型模块的测试,我第一次使用了JUnit这个工具。可以说这个工具非常强大。如果说评测机是狂轰滥炸的飞弹,那么JUnit就是一把可以精确打击的匕首,也许你可以侥幸逃过狂轰滥炸,但是你绝对逃不过那精确一击。

一般JUnit测试所用样例都是自己精心构造的数据。随着代码不断完善进行补充。最方便的一点是:在每次版本更新后,都可以用JUnit一键回归测试,看是否改错了某些地方,可以说是非常强大的工具。

此外,JUnit还可以在运行的时候检测代码覆盖率,我们可以看到哪些地方被测试过,哪些地方还没有做测试,方便之后针对那些没有被覆盖的地方,继续补充测试样例。

OpenJML的使用

使用OpenJML工具可以对代码进行静态检查,有时候可以发现一些非逻辑错误导致的问题。比如我在第九次作业中出现的减法溢出的问题,其实是可以用OpenJML发现的,但当时对这种工具的使用还不是很了解,所以导致出现了bug。这也更加证明了在一个工程中,做好充分测试的必要性,不要让一个庞大的工程因为一个细小的错误而全盘崩塌。

OO第三单元总结——JML的更多相关文章

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

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

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

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

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

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

  4. OO第三单元总结——JML规格设计

    • 1.JML语言的理论基础.应用工具链情况 JML(Java Modeling Language)—— java建模语言,是一种行为接口规范语言( behavioral interface spec ...

  5. 2019年北航OO第三单元(JML规格任务)总结

    一.JML简介 1.1 JML与契约式设计 说起JML,就不得不提到契约式设计(Design by Contract).这种设计模式的始祖是1986年的Eiffel语言.它是一种限定了软件中每个元素所 ...

  6. OO第三单元总结——JML规格

    一.JML简介 1.JML语言的理论基础 JML(Java Modeling Language)是用于对Java程序进行规格化设计的一种表示语言.JML是一种行为接口规格语言 (Behavior In ...

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

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

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

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

  9. OO第三单元作业总结

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

随机推荐

  1. life of a NPTL pthread

    这是2013年写的一篇旧文,放在gegahost.net上面 http://raison.gegahost.net/?p=91 March 7, 2013 life of a NPTL pthread ...

  2. javaee 第七周作业

    一.什么是JSON? JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式.它基于 ECMAScript (欧洲计算机协会制定的js规范)的一 ...

  3. 4.03 使用NULL代替默认值

    问题:在一个定义了默认值的列插入数据,并且需要不管该列的默认值是什么,都将该列值设为NULL.考虑一下下面的表: create table D (id interger default 0, foo ...

  4. 汇编4OPCODE

    opcode原理 前缀域 切换操作数大小前缀 : 066h 可以将32位的操作数切换成16位的操作数 B8 00010000 | MOV EAX,0x100     66:B8 0001 | MOV ...

  5. 北京区域赛I题,Uva7676,A Boring Problem,前缀和差分

    转载自https://blog.csdn.net/weixin_37517391/article/details/83821752 题解 其实这题不难,只要想到了前缀和差分就基本OK了. 我们要求的是 ...

  6. npm与cnpm

    npm介绍 说明:npm(node package manager)是nodejs的包管理器,用于node插件管理(包括安装.卸载.管理依赖等) 使用npm安装插件:命令提示符执行npm instal ...

  7. python关于入参中,传入的是指针还是引用

    偶然看到别人的代码,发现有的会传入参数之后,做一次copy,试验一下,关于入参中,传入的是指针还是引用先说自己的结论:1.如果传入的是简单的类型,那么传入应该是引用的数值,2.假如传入的是df这种类型 ...

  8. WebDriverException: Message: unknown error: Chrome failed to start: crashed

    the last answer WebDriverException: Message: unknown error: Chrome failed to start: crashed

  9. [JOYOI] 1071 LCIS

    拖了好久的LCIS f[i][j]表示a串前i个,b串以b[j]结尾的LCIS长度. 转移时考虑a[i]和b[j]是否相等,如果不等: 那么既然是以j结尾,说明a串前i-1位有一个字符和b匹配了,所以 ...

  10. JSTL标签判断list是否为空

    jsp页面判断获得action传的list的是否为空或者list.size的长度,就可以用fn这个标签: <c:if test="${list== null || fn:length( ...