OO_Unit3总结
OO_Unit3总结
一、JML情况
理论基础
JML(Java Modeling Language)是用于对Java程序进行规格化设计的一种表示语言,为严格的程序设计提供了一套行之有效的方法。通过JML及其支持工具,不仅可以基于规格自动构造测试用例,并整合了SMT Solver等工具以静态方式来检查代码实现对规格的满足情况。
JML有两种主要的用法:
(1)开展规格化设计。这样交给代码实现人员的将不是可能带有内在模糊性的自然语言描述,而是逻辑严格的规格。
(2)针对已有的代码实现,书写其对应的规格,从而提高代码的可维护性。这在遗留代码的维护方面具有特别重要的意义。
由于本次作业中未涉及JML的类型规格,故下文不做进一步讨论。
在JML最核心的语言特征,即level 0中,JML构建了一套完整的语法体系,在这个语法体系里,我们使用表达式来表示方法执行过程中可能涉及的数据,使用前置条件、副作用范围限定和后置条件构建了方法规格。这样做的意义是多方面的,其一给规格的设计者以合理的表达方式,剔除了自然语言的模糊性的前提下,使得规格的设计者需要更全面的思考以涵盖需求的各个方面;其二为规格的实现者指明了实现的方向,通过阅读JML可以直接从逻辑上理解方法应该做到哪些方面;其三为测试人员测试代码提供了途径,测试人员测试代码时只需要判断方法是否实现了规格,而这在一定程度上可以由工具代劳,减少了程序测试对人的依赖。
应用工具链
OpenJml:用于检查JML语法
SMT Solver:检查实现和规格的等价性
JMLUnitNG:基于JML的单元测试工具
二、关于SMT Solver
第一次尝试:在阅读了往届博客以及其他同学的博客之后,我已经对其不报太大希望,由于SMT Solver只能做静态验证,我选择了第一次作业的Person.java进行验证,因为其方法不是很依赖以往的执行情况。第一次尝试以发现JML域和java域不能重名告终。

第二次尝试:修改了JML域的名称后我进行了第二次尝试,使用z3-4.3.2.exe,得到了以下报错信息。

使用另外两个exe运行得到了以下报错信息。

在善用搜索引擎后,我发现这些错误我无法处理,遂放弃。
三、关于JMLUnitNG
修改了Group.java和Person.java,去除了其缓存机制,保证每次调用对应方法时不依赖以往的执行结果,使之能适应JMLUnitNG的要求,依次输入下列指令
java -jar jmlunitng.jar test/Group.java
javac -cp jmlunitng.jar test/*.java
java -jar openjml.jar -rac test/Group.java test/Person.java
java -cp jmlunitng.jar test.Group_JML_Test
得到如下信息:
看起来除了第一个不明意义的fail之外其他都passed了,这在我的意料之中,因为修改后的代码照搬了jml的定义,是最原始的实现方法。
但是我注意到,这些信息中传入的参数不是INT_MAX,0,INT_MIN就是null,这似乎是希冀于边界数据能够测出程序的问题,通过阅读其他同学的博客可以发现,这似乎就是其所有的测试策略。我认为这对于一个工具而言只能是不合格,可能存在其他的测试方式我没有找到,希望其他同学看到后可以补充。
四、架构设计
基本架构已经由JML给出,几次作业只需要注意容器的选择和方法采用何种算法即可。
hw9
MyPerson中,由于频繁出现根据id访问对应的person的需求,兼之考虑到,person和value的一一对应,故采用了HashMap<Integer, Pair<Person, Integer>>,以id值作为键,person,value对作为值保存。
MyNetwork中,由于也需要根据id访问对应的person的需求,且有遍历people的需求,故牺牲空间,同时维护HashMap<Integer, Person>,ArrayList< Person >两个容器,但这也同时牺牲了addPerson的时间,故最后结果孰好孰坏取决于输入情况。
isCircle的实现使用了最简单的bfs,因为并查集如果涉及delRelation我还不会处理,故采用保守策略。
hw10
新增了Group相关代码,为了提高相关方法的效率,我采用了缓存中间变量的做法,每次增加人时更新这些变量。但这种方式有一定局限性,如果person先加入group再加关系,就无法更新relation相关的中间变量。为此,只得牺牲部分封闭性,给MyNetwork以更新这些变量的能力。
需要注意求方差的数学公式不能过度化简,否则会和JML的精度相悖。
hw11
这次作业着力点在于对图的相关算法的考察,分别是求最短路,求点双连通分量,求连通块数量。
求最短路我采用了dijkstra算法,测试后发现时间复杂度较高,在询问其他同学后使用了优先队列,优化了dijkstra过程中获取最小值的复杂度。
点双连通分量我采用了在讨论过程中牟钰同学提出的一种方法,即遍历每个点,如果删去这个点后,id1和id2不再连通,则这个点是割点,如果不存在割点则点双连通。需要注意两点,一是,两者仅直接相连的情况不符合题意,不能被这种方法排除,只能另行判断;二是,可以先bfs找到一条路径,再遍历路径上的点而不是全部点,因为割点一定存在于所有路径上。

Bug相关
在第一次作业中,由于理解JML时出现偏差,对isCircle的异常处理顺序错误,导致某种应当抛异常的情况被我漏过去了,因此第一次作业强测仅得了40分。让我充分认识到了中测=不测的事实,在后两次作业中更谨慎地读JML。
第二次作业强测没有出现问题,在互测中被hack了tle,因为isCircle方法太暴力了,没有充分利用person的acquaintance,导致时间复杂度较高。
第三次在吸收前两次教训的基础上谨慎读JML且注意各个方法的时间复杂度,最后没有出现问题。
互测hack他人的策略就是利用自己的随机数据生成器,大量生成随机数据对其他成员进行测试。第一次测出了其他6名成员的8个bug,第二次也测出了其他成员的tle问题,第三次测出了一位同学的tarjan算法的实现问题。
心得体会
JML似乎给出了一种理想的契约式编程的方式,在分工明确的基础上,一部分进行规格设计,一部分进行代码实现,使得架构设计可以被形式化验证,为我们写代码提供了正确的方向。
三次作业出现的bug也证明了这一点,没有正确实现规格->强测40分;没有高效实现规格->互测被hack;正确且高效地实现规格->没有问题。我对JML的作用的认识依次增加。
但是我也认识到了JML的一些不足。
其一是读JML:读JML需要理解规格所用的谓词逻辑语言,虽然保证了不存在歧义,也大大加大了读JML人的理解难度。在离散数学里,我们有许多定义,如连通分量等,就是为了每次表述这些高频使用的概念时不用每次都写一长串的表达式。因此我觉得JML也应该有一些高阶表达式以类似自然语言的形式描述相关要求,并且由于这仅仅是一种助记符,自然语言的歧义性也不存在,对写规格和实现规格的人都更友好。
其二是工具链的不完善:理想情况下,我们可以,1.写出规格并用相关工具验证正确性;2.实现规格并用相关工具验证等价性;3.测试代码以完成对规格的补充。然而这三方面我均没有看到有好用的工具。
这两点都需要更多的人参与开发JML的工作,希望在今后能看到JML继续发展,给我们带来更好的体验。
OO_Unit3总结的更多相关文章
随机推荐
- java数据类型(基础篇)
			
public class note02 { public static void main(String[] args) { //八大基本数据类型 //1.整数 byte num1 = 1; shor ...
 - NDK android Error:Expected caller to ensure valid ABI: MIPS
			
android studio 安装NDK之后,报错 Error:Expected caller to ensure valid ABI: MIPS 环境: android studio 2.3 gra ...
 - [转]Ubuntu16 压缩解压文件命令
			
原文地址:http://blog.csdn.net/feibendexiaoma/article/details/73739279,转载主要方便随时查阅,如有版权要求,请及时联系. ZIP zip是比 ...
 - 一文学会Dockerfile语法
			
接应上篇,续讲前文.今天咱来聊一下Dockerfile的使用 . 虽然可以通过docker commit命令来手动创建镜像,但是通过Dockerfile文件,可以帮助我们自动创建镜像,并且能够自定义创 ...
 - Go | Go 结合 Consul 实现动态反向代理
			
Go 结合 Consul 实现动态反向代理 代理的核心功能可以用一句话概括:接受客户端的请求,转发到后端服务器,获得应答之后返回给客户端. Table of Contents 反向代理 实现逻辑 Go ...
 - 后端程序员之路 33、Index搜索引擎实现分析2-对外接口和大体流程
			
# index_manager的单例是index server对外的唯一接口,part_indexer是index搜索的核心部分,index_manager持有了一组part_indexer. typ ...
 - 如何进BAT,有了这个篇面试秘籍,成功率高达80%!!(附资料)
			
多年前自己刚来北京找工作的时候,面了一个星期 面了七八家公司才拿到一个offer.而上次跳槽面了不到10家公司基本全过而且都给到了期望的薪资,本来自己在面试前没想到能够这么顺利,回想起来还是自己准备的 ...
 - Java垃圾回收机制详解
			
前言 Java 相比 C/C++ 最显著的特点便是引入了自动垃圾回收 (下文统一用 GC 指代自动垃圾回收),它解决了 C/C++ 最令人头疼的内存管理问题,让程序员专注于程序本身,不用关心内存回收这 ...
 - CentOS 7关闭firewalld启用iptables 开放端口
			
在CentOS7中,有很多CentOS 6中的常用服务发生了变化. 其中iptables是其中比较大的一个.防火墙iptables被firewalld取代. 本文将介绍,如果采用systemctl关闭 ...
 - pytorch(02)tensor的概念以及创建
			
二.张量的简介与创建 2.1张量的概念 张量的概念:Tensor 张量是一个多维数组,它是标量.向量.矩阵的高维拓展 Tensor与Variable Variable是torch.autograd(t ...