【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. python的tecplot模块(tecplot新特性)

    Python的tecplot模块仅支持tecplot2017以上 首先安装tecplot2017 安装完成以后,安装python的tecplot模块 可以通过终端转入tecplot安装目录下的pyte ...

  2. node.js使用cluster实现多进程

    首先郑重声明: nodeJS 是一门单线程!异步!非阻塞语言! nodeJS 是一门单线程!异步!非阻塞语言! nodeJS 是一门单线程!异步!非阻塞语言! 重要的事情说3遍. 因为nodeJS天生 ...

  3. AOP通知类型

    AOP通知类型 前置通知 在目标方法执行之前进行操作 后置通知 在目标方法执行之后 进行操作 环绕通知 在目标方法执行之前 和之后进行操作 public Object arount() 异常抛出通知 ...

  4. arcgis python脚本工具实例教程—栅格范围提取至多边形要素类

    arcgis python脚本工具实例教程-栅格范围提取至多边形要素类 商务合作,科技咨询,版权转让:向日葵,135-4855_4328,xiexiaokui#qq.com 功能:提取栅格数据的范围, ...

  5. C#使用SHA1加密类(RSAFromPkcs8)支持1024位和2048位私钥

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.I ...

  6. ThinkPHP5 基础知识入门 [入门必先了解]

    一.目录结构 下载最新版框架后,解压缩到web目录下面,可以看到初始的目录结构如下: project 应用部署目录 ├─application 应用目录(可设置) │ ├─common 公共模块目录( ...

  7. 微信小程序开发——使用第三方插件生成二维码

    需求场景: 小程序中指定页面需要根据列表数据生成多张二维码. 实现方案: 鉴于需要生成多张二维码,可以将生成二维码的功能封装到组件中,直接在页面列表循环中调用就好了.也可以给组件添加slot,在页面调 ...

  8. 这42个Python小例子,太走心

    告别枯燥,60秒学会一个Python小例子.奔着此出发点,我在过去1个月,将平时经常使用的代码段换为小例子,分享出来后受到大家的喜欢. 一.基本操作 1 链式比较 i = 3print(1 <  ...

  9. Python3基础 tuple list转为tuple

             Python : 3.7.3          OS : Ubuntu 18.04.2 LTS         IDE : pycharm-community-2019.1.3    ...

  10. 企业微信域名IP列表

    https://res.mail.qq.com/zh_CN/wework_ip/latest.html?st=C98F886B96A94AD2207D9F0B2970B93DFD5A76DF94CED ...