1、梳理JML语言的理论基础、应用工具链情况

JML基础理论:

JML(Java Modeling Language)是用于对Java程序进行规格化设计的一种表示语言。JML是一种行为接口规格语言,基于Larch方法构建。JML可以为严格地程序设计提供一套行之有效的方法。通过JML及其支持工具,不仅可以基于规格自动构造测试用例,并整合了SMT Solver等工具以静态方法来检查代码实现对规格的满足情况。

从我个人的理解上,JML语言以简洁严谨的形式描述了代码规格要求,有利于代码的规格化设计,实现上层设计人员与底层实现人员的通信,保证对工程实现上的一致性。而对于我们而言,可以用工具来检查自己所写的代码是否符合课程要求,实现静态代码的检查。

JML注释结构:

块注释:/*@ annotation @*/

行注释://@annotation

JML表达式:

\result:表示一个非 void 类型的方法执行所获得的结果,即方法执行后的返回值。

\old( expr )表达式:用来表示一个表达式 expr 在相应方法执行前的取值。

\not_modifified(x,y,...)表达式:与上面的\not_assigned表达式类似,该表达式限制括号中的变量在方法执行期间的取 值未发生变化。

\nonnullelements( container )表达式:表示 container 对象中存储的对象不会有 null

\type(type)表达式:返回类型type对应的类型(Class)

\typeof(expr)表达式:该表达式返回expr对应的准确类型。

\forall表达式:全称量词修饰的表达式,表示对于给定范围内的元素,每个元素都满足相应的约束。

\exists表达式:存在量词修饰的表达式,表示对于给定范围内的元素,存在某个元素满足相应的约束。

\sum表达式:返回给定范围内的表达式的和。

\product表达式:返回给定范围内的表达式的连乘结果。

\max表达式:返回给定范围内的表达式的最大值。

\min表达式:返回给定范围内的表达式的最小值。

\num_of表达式:返回指定变量中满足相应条件的取值个数。

方法规格:

前置条件:requires P;

后置条件:ensures P;

副作用范围限定:assignable、modifiable

signals子句与signals only子句

类型规格:

不变式invariant

状态变化约束constraint

JML应用工具链:

OpenJML:这是一个用于检查JML的工具,可以帮助我们检查自己编写的jml规格是否符合JML语法规则,是否具有正确且清晰的逻辑,防止错误的JML导致代码的错误。

JMLunitNG:是一个用于自动化检测代码的工具,可以根据JML规格自动生成测试代码TestNG来对代码进行检查,检查代码的实现是否正确,以及是否与JML的规格保持语义上的一致。

JMLUnit:可以根据JML规格自动生成单元测试代码,结合JMLunitNG可以对JML实现自动化检测。

关系:OpenJML可以检测我们所写的JML是否有基础的语法错误或者明显的逻辑不清,而JMLunit则可以根据JML自动生成测试代码,进而使用JMLunitNG就可以对改代码进行自动化测试,这三个工具配合使用可以保证JML的正确性。

2、部署JMLUnitNG/JMLUnit,针对Graph接口的实现自动生成测试用例

部署完毕JMLUnitNG

使用的测试代码非常简陋,如下

执行jmlunitng工具得到所有的测试代码


随后对这些代码进行编译,得到了他们的.class文件

但此处问题出现了,我选择执行testng的时候却无论如何也执行不了,不知道是哪里出了问题

此次还是收获了很多,我会尽快在课下解决这个问题

3、代码结构

第一次作业:

第一次作业的MyPath并没有什么难度,只需要严格遵守jml规格编写代码即可,问题是node是用什么数据结构,这里我用的是ArrayList,考虑到这里需要传迭代器而数组并没有现成的迭代器因此使用arraylist,其余均不难实现。

MyPathContainer的实现唯一可能爆复杂度的是distinctNodeCount这个函数,它需要数出所有path中不重复的node,我使用的数据结构是HashMap,这里我很惨地超时了,原因是我使用的方法是遍历所有的点数出不同的点,实际上后来发现使用HashSet在每次addPath的时候记录不同的点即可实现不超时的算法。

第二次作业

第二次作业的架构沿袭了第一次作业,MyPath的代码没有任何改动,在Graph中用HashMap嵌套HashMap实现了图的存储,实际上是记录了各个点之间的关系,实际使用的是邻接链表来存储图,最短路径我使用的是dfs,这里是这次作业的最大败笔,dfs实际上是深度优先的遍历算法,对于寻找最短路径并不合适,增加了时间复杂度,而实际上使用bfs即可解决,bfs平均找下来,最先找到的一条路径即是最短路径,显然在时间复杂度上会优于dfs

第三次作业

第三次作业我的实现思路是拆点,每个path读入的时候只要node首次出现在该path中就新建node,如果node已经在同一条path中出现多次则只创建一次这样保证了线内不算换乘,最低票价和最少不满意度基本上沿袭这个思路去写。

4、bug与修复:

本次出现的bug主要是在算法层面时间复杂度太高导致超时,而其他的bug只在第一次作业中出现,bug出在对于两个Integer类型的变量使用==判断相等,在将==改为equals之后bug即可得到修复,而这也让我对这一点十分深刻。

后面出现的bug在于dfs复杂度太高,应该使用bfs。

5、反思总结

本单元作业给我最深刻的感受并不在于算法如何设计,具体如何实现,而在于jml规格要求下如何去编写自己的架构,在开始的时候我是选择几乎完全翻译jml,死板地编写代码,但在不断的编写过程中发现自己初始的架构实际上并不适合后面的方法实现,我也认识到jml到代码的过程并不是翻译而是参考和尽可能契合地实现,这也就要求我们通读所有的方法jml规格结合类的规格后仍然要做出自己的架构规划,选择合适的数据结构,决定好算法大体如何实现。

2019北航OO第三单元作业总结的更多相关文章

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

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

  2. 2019北航oo课程第二单元作业总结..#_#..

    学习了之前在写代码是从来没有见过的多线程之后,便迎来了此次电梯作业.说实话,这次作业做得十分的辛苦,虽然在前三次作业中领悟到了java面向对象的精髓,但是再加上了多线程之后,又开始理不清思路,对自己的 ...

  3. 2020北航OO第三单元总结

    2020北航OO第三单元总结 本单元要求是根据JML规格完善代码,初看是一个简单的代码照搬实现的东西,但最后才发现由于CPU时间的限制,还考察了大量优化策略及数据结构中关于图的知识,是一次非常注重细节 ...

  4. OO第三单元作业总结

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

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

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

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

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

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

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

  8. 北航OO第四单元作业总结(4.1~4.3)及课程总结

    前言 在学习过JML规格描述语言之后,本单元进行了UML(Unified Modeling Language)的学习.和JML单纯用语言描述的形式不同,UML通过可视化的图形形式,对一系列有关类的元素 ...

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

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

随机推荐

  1. 大数据应用期末总评——Hadoop综合大作业

    作业要求来自:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/3339 Hadoop综合大作业 要求: 1.将爬虫大作业产生的csv文件 ...

  2. 【软工实践】Alpha冲刺(5/6)

    链接部分 队名:女生都队 组长博客: 博客链接 作业博客:博客链接 小组内容 恩泽(组长) 过去两天完成了哪些任务 描述 任务界面设计,任务功能后端实现 任务计时功能及界面实现 展示GitHub代码签 ...

  3. XmlIgnore的解释和使用

    XmlIgnore是一个自定义属性,用来指明在序列化时是否序列化一个属性.如下面的例子: public class Group { public string GroupName; [XmlIgnor ...

  4. Oracle定时任务执行存储过程备份日志记录表

    写在前面 需求 1.备份系统日志表T_S_LOG, 按照操作时间字段OPERATETIME, 将每天的日志增量备份到另一张表. 思路 1.创建一张数据结构完全相同的表T_S_LOG_BAK作为备份表 ...

  5. html网页调用本地exe程序的实现方法(转)

    https://blog.csdn.net/ilovecr7/article/details/46803711 最近在做一个项目,要什么网页里调exe...开始以为不能实现,后来想想很多就跟淘宝网页上 ...

  6. Samba通过ad域进行认证并限制空间大小

    最近正在做单位电脑的AD域管理. 为漫游用户文件,研究配置Samba通过ad域进行认证并限制空间大小. 参考了很多资料,现总结如下: DC:windows server 2016(配置安装域控制器)略 ...

  7. java 多线程 面试

    1.多线程有什么用? (1)发挥多核CPU的优势: 当前,应用服务器至少也都是双核的,4核.8核甚至16核的也都不少见,如果是单线程的程序,那么在双核CPU上就浪费了50%,在4核CPU上就浪费了75 ...

  8. 【网络开发】详谈socket请求Web服务器过程

    最开始我们需要明白一件事情,因为这是这篇文章的前提: HTTP协议只是一个应用层协议,它底层是通过TCP进行传输数据的.因此,浏览器访问Web服务器的过程必须先有"连接建立"的发生 ...

  9. 【神经网络与深度学习】【CUDA开发】服务器(多GPU)caffe安装和编译

    一. 前提 多GPU交互在神经网络是常见的,所以在安装caffe之前需要安装NCCL,来保证多GPU之间的相互交流.  多GPU,这里指的是2个及2个以上英伟达显卡,而不是笔记本中的集显和独显. 二. ...

  10. Ansible-Hoc--样例

    一.常用场景 1. 列出支持的模块及模块功能说明: 2. sudo用法: 3. 检查服务器存活,复制本地文件到远程: 4. 多线程判断服务器的存活: 5.  显示所有主机的hostname: 6. 列 ...