OO_Unit3_Summary
JML这一单元是真的有含金量,很有难度。而且这难点和前两单元完全不同,前两单元是容易架构混乱导致细节出问题,JML单元是读不懂JML规格的话架构都构不出来,以及即使能够读懂JML规格了,让自己写规格的时候又蒙圈了(大哭.jpg)。以及部署JML相关工具的时候能够比以上都令人崩溃(暴风哭泣.jpg)。
一、JML语言及工具
JML语言
JML(java Modeling Language)是用于对Java程序进行规格化设计的一种表示语言。其利用前置条件、后置条件、不变式等约束语法,描述了Java程序的数据、方法和类的规格,是一种契约式程序设计的实现工具。
1.原子表达式
\result: 方法(非void类型)执行后的返回值。
\old(expr): 表达一个表达式expr相应方法执行前的取值。
2.量化表达式
\forall: 全称量词修饰的表达式,表示对于给定范围内的元素,每个元素都满足相应的约束。
\exists: 存在量词修饰的表达式,表示对于给定范围内的元素,每个元素都满足相应的约束。
\sum: 返回给定范围内的表达式的和。
3.操作符
<==>, <=!=>: 等价关系操作符
== >,< ==: 推理操作符
\nothing, \everything: 变量引用操作符
4.方法规格
requires: 前置条件
ensures: 后置条件
assignable, modifiable, pure: 副作用范围限定
signals, signals_only: 异常抛出语句
5.类型规格
invariant: 不变式
constraint: 变化约束
以上仅是对JML最简单且最常用语法等的梳理。其次,仅仅知晓这些基础语法是不够的,一定要多看代码,多书写JML规格进行练习(否则就会在要求写JML的时候大翻车)。
工具部分
- OpenJML: 对JML进行规范性检查
- JMLUnitNg: 结合OpenJml可实现对代码的自动化测试。
二、SMT Solver验证
对于OpenJml的部署,参考了学长的这篇博客https://www.cnblogs.com/lutingwang/p/openjml_basic.html(可以不用添加环境变量,直接命令行到对应文件夹下运行openjml命令即可)。下面是我的测试经过……

略过出现这个结果的各种报错,终于算是弄出来一个稍微能看的结果,此处报错显示Person类的缺失,然后我放入Person类进行测试……

(上图*.java仅包含Person类和Group类,均为官方第三次作业接口代码)然后出现了这个错,然后表示看不懂以及弄不懂了之后,遂放弃使用openjml进行进一步测试。
三、JMLUnitNg测试
此处工具的部署参考J哥的博客https://www.cnblogs.com/pekopekopeko/p/12920417.html
在其流程上修改为对自己的MyGroup类的测试(将Group的规格扔进了MyGroup类),同时魔改了Person类避免各种恼人的报错。

上图为成功运行时文件内容。
C:\xxxxxxx\jml>java -cp jmlunitng.jar test.MyGroup_JML_Test
[TestNG] Running:
Command line suite
Failed: racEnabled()
Passed: constructor MyGroup(-2147483648)
Passed: constructor MyGroup(0)
Passed: constructor MyGroup(2147483647)
Failed: <<test.MyGroup@6842775d>>.addPerson(null)
Passed: <<test.MyGroup@6c629d6e>>.addRelation(-2147483648, -2147483648, -2147483648)
Passed: <<test.MyGroup@27abe2cd>>.addRelation(0, -2147483648, -2147483648)
Passed: <<test.MyGroup@51016012>>.addRelation(2147483647, -2147483648, -2147483648)
Passed: <<test.MyGroup@1517365b>>.addRelation(-2147483648, 0, -2147483648)
Passed: <<test.MyGroup@60215eee>>.addRelation(0, 0, -2147483648)
Passed: <<test.MyGroup@768debd>>.addRelation(2147483647, 0, -2147483648)
Passed: <<test.MyGroup@449b2d27>>.addRelation(-2147483648, 2147483647, -2147483648)
Passed: <<test.MyGroup@66133adc>>.addRelation(0, 2147483647, -2147483648)
Passed: <<test.MyGroup@24273305>>.addRelation(2147483647, 2147483647, -2147483648)
Passed: <<test.MyGroup@1c2c22f3>>.addRelation(-2147483648, -2147483648, 0)
Passed: <<test.MyGroup@5a42bbf4>>.addRelation(0, -2147483648, 0)
Passed: <<test.MyGroup@4f4a7090>>.addRelation(2147483647, -2147483648, 0)
Passed: <<test.MyGroup@769c9116>>.addRelation(-2147483648, 0, 0)
Passed: <<test.MyGroup@12bc6874>>.addRelation(0, 0, 0)
Passed: <<test.MyGroup@1ef7fe8e>>.addRelation(2147483647, 0, 0)
Passed: <<test.MyGroup@5d3411d>>.addRelation(-2147483648, 2147483647, 0)
Passed: <<test.MyGroup@6979e8cb>>.addRelation(0, 2147483647, 0)
Passed: <<test.MyGroup@2be94b0f>>.addRelation(2147483647, 2147483647, 0)
Passed: <<test.MyGroup@50675690>>.addRelation(-2147483648, -2147483648, 2147483647)
Passed: <<test.MyGroup@47d384ee>>.addRelation(0, -2147483648, 2147483647)
Passed: <<test.MyGroup@3930015a>>.addRelation(2147483647, -2147483648, 2147483647)
Passed: <<test.MyGroup@1ff8b8f>>.addRelation(-2147483648, 0, 2147483647)
Passed: <<test.MyGroup@c39f790>>.addRelation(0, 0, 2147483647)
Passed: <<test.MyGroup@5f150435>>.addRelation(2147483647, 0, 2147483647)
Passed: <<test.MyGroup@75412c2f>>.addRelation(-2147483648, 2147483647, 2147483647)
Passed: <<test.MyGroup@f5f2bb7>>.addRelation(0, 2147483647, 2147483647)
Passed: <<test.MyGroup@3ecf72fd>>.addRelation(2147483647, 2147483647, 2147483647)
Failed: <<test.MyGroup@77f03bb1>>.delPerson(null)
Passed: <<test.MyGroup@7a92922>>.equals(null)
Passed: <<test.MyGroup@5474c6c>>.equals(java.lang.Object@4b6995df)
Passed: <<test.MyGroup@445b84c0>>.getAgeMean()
Passed: <<test.MyGroup@63d4e2ba>>.getAgeVar()
Passed: <<test.MyGroup@7006c658>>.getConflictSum()
Passed: <<test.MyGroup@7cdbc5d3>>.getId()
Passed: <<test.MyGroup@3834d63f>>.getPeopleSum()
Passed: <<test.MyGroup@34340fab>>.getRelationSum()
Passed: <<test.MyGroup@3ab39c39>>.getValueSum()
Failed: <<test.MyGroup@546a03af>>.hasPerson(null)
===============================================
Command line suite
Total tests run: 121, Failures: 10, Skips: 0
===============================================
上图为MyGroup类的实际测试效果(已删除部分测试代码)。由上图具体测试数据分析可知,JMLUnitNg测试数据几乎全部都是边界数据、0和null对象,感觉这样的测试意义也不太大,不具有普适性,不能起到很好的效果。
使用上面所述的工具的整体感受就是,这些工具真的很不完善,以及太鸡肋了,感觉意义不大。
四、作业架构分析
从总结课上知晓了这次作业的实际意图是让我们抽象出图结构,明晰代码的层次架构,从而更好的理解面向对象的思想。但是emmmmmm感觉自己的大多数时候其实是照着规格写代码,虽然抽象出了一定的图结构从而使用一定的图算法来优化,但是感觉还是离这一单元真正的目标有点差距。
三次作业的迭代关系和递进关系很明显,Person类即为一个节点,relation为边,在整个network里,将所有的person抽象为一幅图,在图中进行操作。Group类似于network的子图,其拥有完全不同于network的功能。
第一次作业:

第一次作业,基本按照规格实现,难点在于对规格的理解和对细节的掌握。在将架构抽象为图之后即可按照图的算法来解决iscircle问题,在此我选用的bfs算法,虽然不会超时,但是还是没有以后作业用的并查集香。
第二次作业

第二次作业增加了Group类,并且对于network类增加和Group类交互的功能,对于新增功能的实现都是按部就班的根据规格实现即可,但是由于测试数据集的增加,就要求我们在实现的时候要注意效率。所以我在Group内缓存了group类需求的所有数据,极大的节省了时间。其实感觉group类更像是节点的集合,并且维护集合内节点的共同属性。
第三次作业

第三次作业,对group新增del_person方法,对netwerk类新增更多的方法。其中group类的新增方法要求我们对缓存数据的更新需要更加小心,否则会wa的很惨。其次,network的新增方法抽象来看就是求连通块数目,求最短路径,判断两点是否强联通,这些都是图论的算法,这些方法的增加就要求了我们对这一单元作业的架构的抽象和理解。在理解了架构之后基本按照图论算法按部就班的写代码即可。
对于连通块数目的判断,我采用的并查集方式,同时也更新了iscircle方法,进一步节省了时间。
求最短路径采用了堆优化的迪杰斯特拉算法。
两点强联通我开始用的是暴力删点进行bfs判断联通的方法,但是中测结束前和同学对拍被暴打之后,遂花费一天的时间研究了一波tarjan算法,极大的缩短了时间(但是tarjan算法真的太容易错了,不然我也不会花费一天的时间了),虽然最后助教说暴力解法能过,但是至少多收获了一种算法。
第三次作业本质是大一数据结构的复(huan)习(zhai)作业。(bushi
五、代码实现的bug
在三次强测和互测中均未出现问题。
由于这一单元作业我强迫自己缓慢并且认真读规格,所以除开第三次算法部分,其余都是一次性过关,但是在和室友对拍的时候,室友总会冒出各种各样的小细节问题,同时也顺便给自己重新检查了一次,以及对作业的坑点有了进一步的了解。(虽然和室友对拍了很多,但是室友好像偶尔还是在强测或者互测出点问题,遗憾没能大家一起满分)
在前两次的互测中,由于屋内都是大佬,所以在测试完几个易错点和部分朴实数据之后就放弃了。当然最终结果还是屋内一直安静到底。但是在第三次互测中,由于自己摸了点鱼,评测机的数据针对性不强,所有在大部分人都hack了一个点的情况下,我的评测机毫无收获(我和我的评测机都太菜了)。
六、心得体会
虽然仅仅接触JML了三四周,但是确实也感受了契约式编程的优点和魅力,以及写的好的JML的无歧义是真的比普通的语言描述简洁而且舒服多了。但是JML也是真的难写(手动捂脸),非常容易描述不全,描述不清楚,和对情况的考虑的不完整……考虑的事情和细节太多太杂了,此处感谢此单元助教的辛苦付出(
其次,这一单元帮我复习了很多了图论的算法,迪杰斯特拉算法、bfs、dfs还新学了tarjan算法,收获颇丰。同时对算法的复习,也让我对程序性能有了更进一步的理解。总的来说这一单元的体验是真的不错,此处再次感谢老师和助教和付出。
OO_Unit3_Summary的更多相关文章
随机推荐
- c++ 获取和设置 窗口标题
有些窗口标题中含有中文,可能识别不出来,可以改一下 SetWindowTextW GetWindowTextW 设置: SetWindowTextW( (HWND)0x00370868/*窗口句柄*/ ...
- vue技术栈
1 vue 说明:vue生命周期:技术点:1:常用的API:computed,methods,props,mounted,created,components 2vue-cli说明:vue绞手架,用于 ...
- 使用 Castle 实现 AOP,以及 Autofac 集成 Castle
Castle 是 2003 年诞生于 Apache Avalon 项目,目的是为了创建一个IOC 框架.发展到现在已经有四个组件: ORM组件:ActiveRecord IOC组件:Windsor 动 ...
- Java自学第6期——Collection、Map、迭代器、泛型、可变参数、集合工具类、集合数据结构、Debug
集合:集合是java中提供的一种容器,可以用来存储多个数据. 集合和数组既然都是容器,它们有啥区别呢? 数组的长度是固定的.集合的长度是可变的. 数组中存储的是同一类型的元素,可以存储基本数据类型值. ...
- 玩遍博客网站,我整理了 Hugo 及其流行的风格主题
搭建博客网站是个人进入互联网世界的最常见方式之一.伴随着网站技术的发展,如何搭建博客网站已经变得非常容易了.当然,你可以选择诸如 新浪博客.CSDN.博客园 之类的大型网站,快速创建依赖于大平台的个人 ...
- 清晰图解深度分析HTTPS原理
前言 很高兴遇见你~ Https现在基本已经覆盖所有的http请求了,作为一个伟大的发明,保障了我们的通信安全.在Android中对于HTTPS其实感知不多,因为这些内容都有成熟的框架帮我们完成了,例 ...
- Docker 下Elasticsearch 的安装 和ik分词器
(1)docker镜像下载 docker pull elasticsearch:5.6.8 (2)安装es容器 docker run -di --name=changgou_elasticsearch ...
- iOS之CoreBluetooth
思路 手机与设备间的通讯方式CoreBluetooth是比较常见且通用的.在iOS开发中需明晰以下几点 蓝牙4.0最多可联机7个设备,iPhone6以上都是蓝牙4.0 两台iPhone并不直接通过蓝牙 ...
- 13. Vue CLI脚手架
一. Vue CLI 介绍 1. 什么是Vue CLI? Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统.Vue CLI 致力于将 Vue 生态中的工具基础标准化.它确保了各种构建工 ...
- TestLink测试用例管理工具使用说明
TestLink使用说明 打开网页,登录账号:(这里的账号是已经注册过的,并且拥有admin权限,可以创建用户.当然也可以通过点击登录页面的"新用户注册"按钮进行注册,但是权限是g ...