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

  第三单元,我们学习了JML语言,用来进行形式化设计。本单元包括三次作业,通过给定的JML来实行了一个对路径的管理系统,最后完成了一个地铁系统,来管理不同的线路,求得关于价格、换乘、不满意度等最短路信息。

  本文将介绍:JML语言理论基础、应用工具链和工具的使用方法;SMT Solver;JMLUnitNG自动生成测试用例;三次作业的架构设计;Bug查找策略;个人心得。

JML

  JML(Java Modeling Language)是用于对Java程序进行规格化设计的一种表示语言。JML是一种行为接口规格语言(Behavior Interface Specification Language,BISL),基于Larch方法构建。BISL提供了对方法和类型的规格定义手段。所谓接口即一个方法或类型外部可见的内容。JML主要由Leavens教授在Larch上的工作,并融入了Betrand Meyer, John Guttag等人关于Design by Contract的研究成果。近年来,JML持续受到关注,为严格的程序设计提供了一套行之有效的方法。通过JML及其支持工具,不仅可以基于规格自动构造测试用例,并整合了SMT Solver等工具以静态方式来检查代码实现对规格的满足情况。
  一般而言,JML有两种主要的用法:

  • 开展规格化设计。这样交给代码实现人员的将不是可能带有内在模糊性的自然语言描述,而是逻辑严格的规格。
  • 针对已有的代码实现,书写其对应的规格,从而提高代码的可维护性。这在遗留代码的维护方面具有特别重要的意义。

  一般JML规格中,会描述 requires先验条件,ensures后验条件,assignable可能改变的内容,exceptional_behavior异常抛出条件。对类的规格描述有invariant不变式,constraint变化约束。

  可以使用开源的openJML工具来进行对JML规格进行原语检查、静态验证以及动态验证。

原语检查

  由于已经有很多同学讲解了在Linux下的使用方法,我这里主要说下在Windows下的使用。

  首先把所有需要测试或相关的java文件路径写到一个.txt中。可以使用windows下dir指令将目录下所有java文件写到java.txt中。

 dir *.java /s /b > java.txt

  之后就可以使用openjml来检查JML规格是否书写正确。

 java -jar yourPath\openjml.jar -exec yourPath\Solvers-windows\z3-4.7..exe -check @java.txt -encoding UTF-

  注意需要使用-encoding UTF-8,否则中文编码会报错。

静态验证


 java -jar yourPath\openjml.jar -exec yourPath\Solvers-windows\z3-4.7..exe -esc @java.txt -encoding UTF-

  在使用静态验证的时候可能报错:

  

  根据提示,需要加上-exec 来指定使用的SMT solver的版本。

动态验证

 java -jar yourPath\openjml.jar -exec yourPath\Solvers-windows\z3-4.7..exe -rac @java.txt -encoding UTF-
java -cp jmlruntime.jar; Main

  这里要注意的是,使用-cp的时候包后边加上分号,否则也会有报错。 :)

SMT Solver

  SMT( Satisfiability modulo theories )求解器在形式化方法、程序语言、软件工程、以及计算机安全、计算机系统等领域得到了广泛应用。

JMLUnitNG

   关于对MyGraph类使用JMLUnitNG生成测试用例。

  首先需要将相关类中的中文注释全部删除(com.oocourse.space2.models内的所有文件),否则会出现编码错误。

 java -jar E:\workspace\OO\openJML\jmlunitng-1_4.jar java\MyGraph.java java\com\oocourse\specs2\models\*.java

  使用如上指令进行测试用例生成。

  如果出现关于HashMap的报错,需要将new HashMap中的模板补全。

  生成测试用例后,可以通过Idea运行。

  我的结果中有出现了很多“错误”,根据测试信息,大概发现是因为很多测试都是边缘测试,测了Int的极值,可以检测出,但是由于返回了异常,所以会报错。

  可以看出,JMLUnitNG生成的单元测试,比较关注于数据边界,可以用来提醒程序员考虑数据边界。但是对于基本简单的测试,还是需要手动生成。

三次作业架构设计

第一次作业

  对Path接口的实现,主要按照JML来设计。用ArrayList来记录node顺序。为了加速求DistinctNode个数,用了Hashmap来存储每个节点出现的次数。

  对PathContainer接口的实现,我用了Hashmap来将每条Path的编号与Path本身做映射。在查找Path对应的Id时,直接使用了枚举操作(Path的个数不会很多)。同样为了加速求DistinctNode个数,用了Hashmap存储了每个节点出现次数,在addPath和removePath时维护Hashmap的内容。

第二次作业

  和上次作业相比,这次作业出现了图的概念,需要维护节点、边和最短路。由于添加、删除Path的次数很少,因此这次作业采用了在每次加减Path的时候,重新建立相关数据,然后查询的时候直接O(1)查询。用二维数组,记录边和最短路的信息。最短路用floyd算法求解。

  Path接口的实现与第一次作业一样。

  Graph接口的实现,我是直接在上次PathContainer的基础上添加了一些属性和方法。首先对getPathId方法,我新建了一个Hashmap,建立了Path和PathId之间的映射。

  因为点是离散的,我是用Hashmap将点进行了重新编号,把原本分布于Int范围内的点,映射到1~n之间,方便计算和存储。

  对图的维护,每当有修改路径时,我都重新对点编号,构建最短路矩阵和连边矩阵。

  对图的查询操作比较简单,直接从相关容器中查询就行。

第三次作业

  在这次作业之前,我对第二次作业进行了分析,发现Graph类的功能过于庞大。因此这次的作业采用了继承机制。每个接口都对应一个具体类,类的继承关系和接口的继承关系相同。这样每个类的都只实现对应接口的功能。具体类图如下:

  

  对于4种最短路的实现,采用了Floyd来一次性计算,然后O(1)查询。建图方法参考了讨论区wjy的做法(wjynb)。关于她的建图方法,我的理解是每条边<u, v>表示,从u走到v然后换乘。所以最后要减去一次换乘的代价。这样可以避免因为拆点处理换乘带来的点过多(120 -> 5000)导致复杂度增加。

  为了方便维护图,所有关于图的操作我都放到Graph类(非MyGraph)里,里面实现了加边、计算、查询这些方法。关于图连通性的维护也在这里,使用了染色算法,dfs查询后存储下来,O(1)查询。

  MyGraph类内部,主要是实现了当增加和删除Path时,重构graph(Graph类的实例)。由于按照wjy的做法,需要计算出每条Path内部的最短路,因此我实现了PathGraph类,来记录已添加的Path内部最短路,这样可以减少重复计算带来的时间损耗。

  MyRailwaySystem中,主要是参考JML规格跑出异常,然后调用graph内的方法来查询就行。

Bug查找策略

  这三次作业我分别采用了不同的测试方法。

第一次作业

  我使用了JUnit来进行单元测试,对Path和PathContainer的每个方法都进行了测试。同时我也使用JUnit做了压力测试,添加了很多Path,然后多次查询,最终发现了DistinctNode会超时。

第二次作业

  第二次作业我也使用了JUnit,和上次作业类似。

  我还使用了JMLUnitNG,参考了讨论区伦佬的方法。补全了MyPath类的JML规格,然后生成了一组测试样例进行测试。但是可能规格没有设计清楚,导致测试时出了一些问题。

第三次作业

  由于新增的方法,大多都是查询方法。所以这次作业我主要采取随机测试,主要用来测试时间和正确性。由于我写了俩种算法(dijkstra和floyd),可以通过将进行对比。

  JUnit是必要的,我将上次作业的测试拷贝过来,来保证上次作业的方法的正确性。

个人心得

  在学习本单元之前,我对于关于形式化方法的理解不够深入。通过这个JML的学习,我认识到可以从架构设计层面就开始形式化。有了JML,每个类之间的设计、调用可以不依赖类的具体实现,根据规格就可以知道该如何使用该类、该方法。因此学习JML是非常有必要的,JML也可以用在今后设计之中。

【OO学习】OO第三单元作业总结的更多相关文章

  1. BUAA OO 2019 第三单元作业总结

    目录 总 JML规格化设计 理论基础 工具链 规格验证 验证代码 代码静态检查 自动生成测试样例 生成结果 错误分析 作业设计 第九次作业 架构 代码实现 第十次作业 架构 代码实现 第十一次作业 架 ...

  2. OO第三单元作业总结

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

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

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

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

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

  5. 北航OO第三单元作业总结(3.1~3.3)

    JML简介及相关工具链使用 1.JML规格描述语言介绍 本单元学习的内容是JML规格描述语言.我们知道,面向对象方法是一个抽象过程,需求者仅需关注方法的规格.规格是对一个方法/类/程序的外部可感知行为 ...

  6. OO第三单元作业小结

    一.JML理论基础及应用工具链情况 理论基础 1.JML表达式 \result:表示方法执行后的返回值. \old(expr):表示一个表达式expr在相应方法执行前的取值. \foall:全称量词修 ...

  7. 2019北航OO第三单元作业总结

    1.梳理JML语言的理论基础.应用工具链情况 JML基础理论: JML(Java Modeling Language)是用于对Java程序进行规格化设计的一种表示语言.JML是一种行为接口规格语言,基 ...

  8. OO第三单元作业分析

    一.JML的理论基础应用工具链 JML是用于对Java程序进行规格化设计的一种表示语言.基于Larch方法构建. (1)注释 JML以javadoc注释的方式来表示规格,每行都以@起头.有两种注释方式 ...

  9. 2019OO第三单元作业总结

    OO第三单元的作业主题是JML规格化设计,作业以图及图的最短路径相关计算为载体,体现接口的规格化设计. ------------------------------------------------ ...

随机推荐

  1. 服务器收不到支付宝notify_url异步回调请求的问题排查

    小背景 最近在调整支付宝支付的功能时发现,不能够正常接收支付宝付款成功之后的回调通知了,从代码到配置最后到服务器配置都排查了一遍,最终发现问题原因竟然是因为我们的回调地址notify_url是http ...

  2. python unittest套件加载用例时,出现No tests were found,Empty test suite

    错误信息: 之前运行好好的脚本,突然报No tests were found,Empty test suite,详情错误信息如下所示: Launching pytest with arguments ...

  3. 第07组 Beta冲刺(2/5)

    队名:摇光 队长:杨明哲 组长博客:求戳 作业博客:求再戳 队长:杨明哲 过去两天完成了哪些任务 文字/口头描述:代码编辑器 展示GitHub当日代码/文档签入记录:(组内共用,已询问过助教小姐姐) ...

  4. mysql索引原理及优化(二)

    索引原理分析:数据结构 索引是最常见的慢查询优化方式其是一种优化查询的数据结构,MySql中的索引是用B+树实现,而B+树就是一种数据结构,可以优化查询速度,可以利用索引快速查找数据,优化查询. 可以 ...

  5. flask 开发用户登录注册功能

    flask 开发用户登录注册功能 flask开发过程议案需要四个模块:html页面模板.form表单.db数据库操作.app视图函数 1.主程序 # app.py # Auther: hhh5460 ...

  6. 在evernote中如何使序号正常连续?

    答: 在二级内容之前按Shift + Enter键,再次换行即可序号正常,示例如下: 1. 第一行(在此处按下Shift+Enter键) 第一行第一列(在此处按下Shift+Enter键) 第一行第二 ...

  7. pycharm安装pyinstaller将pygame打包成exe

    首先,使用pycharm自带的下载包工具,File-Settings-Project Interpreter,如图: 安装完成后,发现安装到了Python根目录下,我的在C:\python34\Scr ...

  8. [LeetCode] 3.Longest Substring Without Repeating Characters 最长无重复子串

    Given a string, find the length of the longest substring without repeating characters. Example 1: In ...

  9. [LeetCode] 125. Valid Palindrome 验证回文字符串

    Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignori ...

  10. (二)主板BIOS设置与硬盘分区、调整

    1.主板BIOS设置 前提,你得有一台电脑,台式机或笔记本电脑都行. BIOS负责开机时对系统中各个硬件进行初始化设置和测试,以确保系统能正常工作,是电脑硬件与软件程序之间的一座桥梁. 电脑在开机启动 ...