OO 第三单元总结
1. JML梳理
根据JML LEVEL 0手册梳理常用条目
1.1 JML 理论基础
- \result表达式 : 表示方法返回值
- \old( expr )表达式:表示方法执行之前expr表达式取值,若expr为相关引用,只能判断引用本身是否发生了变化
- \type(type)表达式:返回类型type对应的类型。
- \typeof(expr)表达式:该表达式返回expr对应的准确类型。
- \forall表达式:(\forall int i ; exprA ; exprB) 通俗理解为 ∀i(exprA -> exprB)
- \exists表达式: (\forall int i ; exprA ; exprB) 通俗理解为 ∃i(exprA -> exprB)
- 前置条件(pre-condition) : requires expr
- 后置条件(post-condition) : ensures expr
- 副作用范围限定(side-effects) : assignable、modifiable
- 正常功能 :public normal behavior
- 异常功能 :public exceptional_behavior
- 抛出异常 : signals
- 不变式invariant : 要求在所有可见状态下都必须满足的特性
- 状态变化约束constraint : 对象状态变化是两次满足的一定约束,不变式的子集。
1.2 JML应用工具链
对于含有JML注释的代码,可以使用如Openjml进行JML注释语法检查、静态检查、编译成支持rac的class文件。可以配合junitng自动化生成的测试用例对代码运行时正确性进行测试。
2. JMLUnitNG自动生成测试尝试
2.1首先是讨论区大佬给出样例的复现
哪怕是复现讨论区中测试仍然菜出了许多问题,归结于原因为不是很了解java和javac寻找文件的方式,同时报错信息只有找不到***让人十分头大,最终笔者采用将Demo.java直接放到Openjml文件夹中才得以解决相关问题。
$ tree
.
|-- JMLTest.iml
`-- openjml-0.8.-
|-- LICENSE.rtf
|-- OpenJMLUserGuide.pdf
|-- Solvers-linux
| |-- cvc4-1.6
| |-- z3-4.3.
| |-- z3-4.3.
| `-- z3-4.7.
|-- Solvers-macos
| |-- cvc4-1.6
| |-- z3-4.3.
| |-- z3-4.5.
| |-- z3-4.6.
| `-- z3-4.7.
|-- Solvers-windows
| |-- cvc4-1.6.exe
| |-- z3-4.3..exe
| `-- z3-4.7..exe
|-- VERSION_INFO
|-- epl-v10.html
|-- jml-reference-manual.pdf
|-- jmlruntime.jar
|-- jmlspecs.jar
|-- jmlunitng
|-- jmlunitng.bat
|-- jmlunitng.jar
|-- openjml
|-- openjml-template.properties
|-- openjml.bat
|-- openjml.jar
`-- src
`-- demo
`-- Demo.java
初始文件树
第一步:jmlunitng生成测试代码
jmlunitng src/demo/Demo.java
$ tree
.
|-- LICENSE.rtf
|-- OpenJMLUserGuide.pdf
|-- Solvers-linux
| |-- cvc4-1.6
| |-- z3-4.3.
| |-- z3-4.3.
| `-- z3-4.7.
|-- Solvers-macos
| |-- cvc4-1.6
| |-- z3-4.3.
| |-- z3-4.5.
| |-- z3-4.6.
| `-- z3-4.7.
|-- Solvers-windows
| |-- cvc4-1.6.exe
| |-- z3-4.3..exe
| `-- z3-4.7..exe
|-- VERSION_INFO
|-- epl-v10.html
|-- jml-reference-manual.pdf
|-- jmlruntime.jar
|-- jmlspecs.jar
|-- jmlunitng
|-- jmlunitng.bat
|-- jmlunitng.jar
|-- openjml
|-- openjml-template.properties
|-- openjml.bat
|-- openjml.jar
`-- src
`-- demo
|-- Demo.java
|-- Demo_InstanceStrategy.java
|-- Demo_JML_Data
| |-- ClassStrategy_int.java
| |-- ClassStrategy_java_lang_String.java
| |-- ClassStrategy_java_lang_String1DArray.java
| |-- compare__int_lhs__int_rhs__0__lhs.java
| |-- compare__int_lhs__int_rhs__0__rhs.java
| `-- main__String1DArray_args__10__args.java
|-- Demo_JML_Test.java
|-- PackageStrategy_int.java
|-- PackageStrategy_java_lang_String.java
`-- PackageStrategy_java_lang_String1DArray.java
第一步后文件树
第二步:javac 编译 JMLUnitNG 生成文件
javac -cp jmlunitng.jar -sourcepath src src/demo/**/*.java
$ tree
.
|-- LICENSE.rtf
|-- OpenJMLUserGuide.pdf
|-- Solvers-linux
| |-- cvc4-1.6
| |-- z3-4.3.
| |-- z3-4.3.
| `-- z3-4.7.
|-- Solvers-macos
| |-- cvc4-1.6
| |-- z3-4.3.
| |-- z3-4.5.
| |-- z3-4.6.
| `-- z3-4.7.
|-- Solvers-windows
| |-- cvc4-1.6.exe
| |-- z3-4.3..exe
| `-- z3-4.7..exe
|-- VERSION_INFO
|-- epl-v10.html
|-- jml-reference-manual.pdf
|-- jmlruntime.jar
|-- jmlspecs.jar
|-- jmlunitng
|-- jmlunitng.bat
|-- jmlunitng.jar
|-- openjml
|-- openjml-template.properties
|-- openjml.bat
|-- openjml.jar
`-- src
`-- demo
|-- Demo.java
|-- Demo_InstanceStrategy.java
|-- Demo_JML_Data
| |-- ClassStrategy_int.class
| |-- ClassStrategy_int.java
| |-- ClassStrategy_java_lang_String.class
| |-- ClassStrategy_java_lang_String.java
| |-- ClassStrategy_java_lang_String1DArray.class
| |-- ClassStrategy_java_lang_String1DArray.java
| |-- compare__int_lhs__int_rhs__0__lhs.class
| |-- compare__int_lhs__int_rhs__0__lhs.java
| |-- compare__int_lhs__int_rhs__0__rhs.class
| |-- compare__int_lhs__int_rhs__0__rhs.java
| |-- main__String1DArray_args__10__args.class
| `-- main__String1DArray_args__10__args.java
|-- Demo_JML_Test.java
|-- PackageStrategy_int.class
|-- PackageStrategy_int.java
|-- PackageStrategy_java_lang_String.class
|-- PackageStrategy_java_lang_String.java
|-- PackageStrategy_java_lang_String1DArray.class
`-- PackageStrategy_java_lang_String1DArray.java
第二步文件树
第三步 :Openjml 编译
openjml -rac demo/Demo.java
$ tree
.
|-- LICENSE.rtf
|-- OpenJMLUserGuide.pdf
|-- Solvers-linux
| |-- cvc4-1.6
| |-- z3-4.3.
| |-- z3-4.3.
| `-- z3-4.7.
|-- Solvers-macos
| |-- cvc4-1.6
| |-- z3-4.3.
| |-- z3-4.5.
| |-- z3-4.6.
| `-- z3-4.7.
|-- Solvers-windows
| |-- cvc4-1.6.exe
| |-- z3-4.3..exe
| `-- z3-4.7..exe
|-- VERSION_INFO
|-- epl-v10.html
|-- jml-reference-manual.pdf
|-- jmlruntime.jar
|-- jmlspecs.jar
|-- jmlunitng
|-- jmlunitng.bat
|-- jmlunitng.jar
|-- openjml
|-- openjml-template.properties
|-- openjml.bat
|-- openjml.jar
`-- src
`-- demo
|-- Demo.class
|-- Demo.java
|-- Demo_InstanceStrategy.java
|-- Demo_JML_Data
| |-- ClassStrategy_int.class
| |-- ClassStrategy_int.java
| |-- ClassStrategy_java_lang_String.class
| |-- ClassStrategy_java_lang_String.java
| |-- ClassStrategy_java_lang_String1DArray.class
| |-- ClassStrategy_java_lang_String1DArray.java
| |-- compare__int_lhs__int_rhs__0__lhs.class
| |-- compare__int_lhs__int_rhs__0__lhs.java
| |-- compare__int_lhs__int_rhs__0__rhs.class
| |-- compare__int_lhs__int_rhs__0__rhs.java
| |-- main__String1DArray_args__10__args.class
| `-- main__String1DArray_args__10__args.java
|-- Demo_JML_Test.java
|-- PackageStrategy_int.class
|-- PackageStrategy_int.java
|-- PackageStrategy_java_lang_String.class
|-- PackageStrategy_java_lang_String.java
|-- PackageStrategy_java_lang_String1DArray.class
`-- PackageStrategy_java_lang_String1DArray.java
第三步文件树
第四步 :运行
java -cp jmlunitng.jar demo.Demo_JML_Test
[TestNG] Running:
Command line suite Passed: racEnabled()
Passed: constructor Demo()
Passed: static compare(-, -)
Failed: static compare(, -)
Failed: static compare(, -)
Passed: static compare(-, )
Passed: static compare(, )
Passed: static compare(, )
Failed: static compare(-, )
Passed: static compare(, )
Passed: static compare(, )
Passed: static main(null)
Passed: static main({}) ===============================================
Command line suite
Total tests run: , Failures: , Skips:
===============================================
测试结果
2.2 对Graph 进行测试
对graph测试时由于相关原因没能引入规格,因此只进行了边界测试,结果如下(仅给出Fail Case):
[TestNG] Running:
Command line suite ...... Passed Case ignored. Failed: <<MyGraph@47d384ee>>.getPathById(-)
Failed: <<MyGraph@2d6a9952>>.getPathById()
Failed: <<MyGraph@22a71081>>.getPathById()
Failed: <<MyGraph@3930015a>>.getPathId(null)
Failed: <<MyGraph@629f0666>>.getShortestPathLength(-, -)
Failed: <<MyGraph@1bc6a36e>>.getShortestPathLength(, -)
Failed: <<MyGraph@1ff8b8f>>.getShortestPathLength(, -)
Failed: <<MyGraph@387c703b>>.getShortestPathLength(-, )
Failed: <<MyGraph@224aed64>>.getShortestPathLength(, )
Failed: <<MyGraph@c39f790>>.getShortestPathLength(, )
Failed: <<MyGraph@71e7a66b>>.getShortestPathLength(-, )
Failed: <<MyGraph@2ac1fdc4>>.getShortestPathLength(, )
Failed: <<MyGraph@5f150435>>.getShortestPathLength(, )
Failed: <<MyGraph@1c53fd30>>.isConnected(-, -)
Failed: <<MyGraph@50cbc42f>>.isConnected(, -)
Failed: <<MyGraph@75412c2f>>.isConnected(, -)
Failed: <<MyGraph@282ba1e>>.isConnected(-, )
Failed: <<MyGraph@13b6d03>>.isConnected(, )
Failed: <<MyGraph@f5f2bb7>>.isConnected(, )
Failed: <<MyGraph@73035e27>>.isConnected(-, )
Failed: <<MyGraph@64c64813>>.isConnected(, )
Failed: <<MyGraph@3ecf72fd>>.isConnected(, )
Failed: <<MyGraph@483bf400>>.removePathById(-)
Failed: <<MyGraph@21a06946>>.removePathById()
Failed: <<MyGraph@77f03bb1>>.removePathById()
Failed: <<MyGraph@326de728>>.removePath(null) ===============================================
Command line suite
Total tests run: , Failures: , Skips:
===============================================
Graph边界测试结果
可以看到测试主要数据由0、null、MAX、MIN等边界数据构成。
3.架构设计
3.1 Project 9
搜索利用Hashmap,保存使用ArrayList

3.2 Project 10、11
后两次使用了bfs + 优先级队列求最短路径的思路,加入了缓存计算的概念。记录数据通过键值对<CacheEntry, value>构成,每次算法遍历之前优先审查Cache中是否有相应结果,当然最重大的bug也出现在这里,下面会提到。


4. Bug分析
在第三次作业中,由于缓冲层的加入翻了车。由于这个bug很有意思,在此和大家分享:
从初始结点A bfs,每次从优先级队列中取出队首元素,优先级队列中排列的元素为各种走法,排在队首的为当前队列中长度(或票价、换乘数量、不舒适度)最小的走法之一。被取出的合法走法被认为是当前两点间的最优解(因为如果有更优解的话应该在这之前被取了)。
Cache的工作原理是每当出现最优解时便将最优解存入。Cache的使用方法为如果当前中转点 B 与终点 C 中存在CacheEntry,便将 B 后的搜索全部剪枝,因为我们可以确定的是不可能存在经过当前起点 B 的更优解。
错误 1 :最初的bug比较低级,即当Cache搜索成功后直接返回,但是错误在于Cache查询成功并不代表找到了A点 -> C点的最优解,由于B点不一定在最优解路径上。
错误 2 :当查出错误1后便松懈了,没有意识到更重大的bug :当我们使用Cache进行剪枝后,实际上这之后从队首取出的走法就不是最优解了,因此此处应该在是否继续更新Cache和剪枝之间做出权衡。
5. 心得体会
此次题目与实际生活真实情况相差较远,甚至在关键定义上有悖常理,给代码架构设计与理解上主观上加入许多bug的可能。比如一条Path可以重复经过同一个站点多次,虽然这一要求在第一次作业中已经提出,但是仍然让人感到很困惑。以第三次作业为例,设想一条Pathid为1的Path为 1 2 3 4 5 3 6 3 7, 如果我们将3这一数字抽象为一个地铁站,经过地铁站的不同Pathid抽象为站台的话,考察站点3的1号线站台会意识到乘客可以在此站台不换乘而选择去往2、4、5、6、7五站,这不禁让人感到困惑列车为何可以随乘客意愿选择路线而无需乘客换乘。虽说合理的设计可以解决这些问题,但是我并不认为这种架构是解决实际地铁问题时良好的设计思路。
OO 第三单元总结的更多相关文章
- OO第三单元作业总结
OO第三单元作业总结--JML 第三单元的主题是JML规格的学习,其中的三次作业也是围绕JML规格的实现所展开的(虽然感觉作业中最难的还是如何正确适用数据结构以及如何正确地对于时间复杂度进行优化). ...
- 规格化设计——OO第三单元总结
规格化设计--OO第三单元总结 一.JML语言理论基础.应用工具链 1.1 JML语言 JML(java modeling language)是一种描述代码行为的语言,包括前置条件.副作用等等.J ...
- 【OO学习】OO第三单元作业总结
[OO学习]OO第三单元作业总结 第三单元,我们学习了JML语言,用来进行形式化设计.本单元包括三次作业,通过给定的JML来实行了一个对路径的管理系统,最后完成了一个地铁系统,来管理不同的线路,求得关 ...
- OO第三单元(地铁,JML)单元总结
OO第三单元(地铁,JML)单元总结 这是我们OO课程的第二个单元,这个单元的主要目的是让我们熟悉并了解JML来是我们具有规格化编程架构的思想.这个单元的主题一开始并不明了,从第一次作业的路径到第二次 ...
- OO第三单元——基于JML的社交网络总结
OO第三单元--基于JML的社交网络总结 一.JML知识梳理 1)JML的语言基础以及基本语法 JML是用于java程序进行规格化设计的一种表示语言,是一种行为接口规格语言.其为严格的程序设计提供了一 ...
- OO第三单元作业——魔教规格
OO第三单元作业--魔教规格 JML的理论基础和相关工具 JML(Java Modeling Language,Java建模语言),在Java代码种增加了一些符号,这些符号用来标志一个方法是干什么 ...
- OO第三单元个人总结
OO第三单元个人总结 JML理论与基础与应用工具链 JML是什么? Java建模语言(JML)是一种行为接口规范语言,可用于指定Java模块的行为 .它结合了Eiffel的契约设计方法 和Larch ...
- 2020 OO 第三单元总结 JML语言
title: 2020 OO 第三单元总结 date: 2020-05-21 10:10:06 tags: OO categories: 学习 第三单元终于结束了,这是我目前为止最惨的一单元,第十次作 ...
- 2020北航OO第三单元总结
2020北航OO第三单元总结 本单元要求是根据JML规格完善代码,初看是一个简单的代码照搬实现的东西,但最后才发现由于CPU时间的限制,还考察了大量优化策略及数据结构中关于图的知识,是一次非常注重细节 ...
- OO第三单元作业(JML)总结
OO第三单元作业(JML)总结 目录 OO第三单元作业(JML)总结 JML语言知识梳理 使用jml的目的 jml注释结构 jml表达式 方法规格 类型规格 SMT Solver 部署JMLUnitN ...
随机推荐
- 使用SwingWorker为界面执行异步任务
------------------siwuxie095 工程名:TestSwingWorker 包名:com.siwuxie095.swing ...
- 项目中缺少org.wltea.ik-analyzer如何解决?
IKAnalyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包.从2006年12月推出1.0版开始,IKAnalyzer已经推出了3个大版本.最初,它是以开源项目Luence为应用主体 ...
- javascript 操作符小结
简单总结一下JavaScript的几个操作符: var. in. delete. typeof. new. instanceof.void var 定义变量要使用var操作符, 使用var操作符定义的 ...
- redis系列:通过共同好友案例学习set命令
前言 这一篇文章将讲述Redis中的set类型命令,同样也是通过demo来讲述,其他部分这里就不在赘述了. 项目Github地址:https://github.com/rainbowda/learnW ...
- windows配置换行符
CR.LF.CR/LF为不同操作系统上使用的换行符: Windows/DOS系统:采用CR/LF表示下一行: Unix/Linux系统:采用LF表示下一行: Mac OS系统:采用CR表示下一行: M ...
- [转]Node.JS package.json 字段全解析
Name 必须字段. 小提示: 不要在name中包含js, node字样: 这个名字最终会是URL的一部分,命令行的参数,目录名,所以不能以点号或下划线开头: 这个名字可能在require()方法中被 ...
- .net core 中的配置文件
前言 在 .NET Core 项目中,配置文件有着举足轻重的地位:与.NetFramework 不同的是,.NET Core 的配置文件都以 .json 结尾,这表示一个标准的 json 格式 ...
- InnoDB信息说明
InnoDB是MySQL数据库发展至今一款至关重要的数据库存储引擎,其不仅支持事务特性,并且具有丰富的统计信息,便于数据库管理人员了解最近InnoDB存储引擎的运行状态. 早期版本的InnoDB存储引 ...
- Codeforces Round #558 (Div. 2)C(计算几何,排列组合,模拟)
#include<bits/stdc++.h>using namespace std;typedef struct{ double k,b;}node;node k[1000007];bo ...
- ERROR 1010 (HY000): Error dropping database (can't rmdir './nsd', errno: 39)
在删除数据库的时候报标题所示错误 mysql> drop database test; ERROR 1010 (HY000): Error dropping database (can't rm ...