oo第三次博客-JML规格
这三周的作业主要是围绕以JML来约束代码开发,以确保程序的正确性与鲁棒性。
Part 1:三次作业的实现与bug
第一次作业没有任何算法和数据结构上的难度,对于Path和PathContainer的各个方法的实现按照给出的规格复读即可。唯一的难点(大约也不算难点)便是将NodeId进行映射,用hashmap就好,不过注意不要做一个调包侠,hashmap中有的方法譬如遍历很慢,虽然看上去只差常数,但是这个常数巨大,如果在第一次作业中不加处理就会在第二次作业中TLE。
第一次作业也让我们了解了抛异常,我个人认为JML对于抛异常的处理是值得称道的,通过这样的约束可以控制程序在犯了一些明显的错误后及时停止而不是越错越远浪费计算资源,造成更严重的后果。
第二次作业是在第一次的基础上写一个Graph类,这个类继承PathContainer,将不同的Path汇总成一个图,并能够查询最短路。
对于第二次作业,首先要吐槽的是给出的接口,在需要继承的情况下应该声明为protect,才能更好地实现数据的继承,而给出的接口使用了private,给我们的选择便只有重新声明数据,每当使用的时候get一次以更新或者将第一次PathContainer的代码复制到Graph中,我为了偷懒选择了后者,结果第三次就只能靠疯狂压行来改正代码风格。
对于第二次图的实现,介于图中边权均为1,求最短路和是否连通均可以使用BFS。在BFS中将查找到的点均进行更新就好,这样,在询问两点是否连通或者他们的最短路时,可以先查找对应图中两点间值是否为初始值,若是则BFS查找更新,否则直接返回结果。同时只有当需要查找两点间最短路或者连通情况且Path有过remove或add且上一次Path改变后没有更新才更新图。
对于第三次作业,其实是在求带权最短路。这里再使用BFS就不太合适了。
对于连通块数量,可以使用并查集,也可以选择图中一个点开始BFS,终止后若没有遍历所有点则选择一个未遍历的点继续BFS,如此往复至图中所有点被搜索过即可。这两者后者更快。
对于三种不同的最短路,王嘉仪同学给出的关于图的数学性质是正确的,利用这个性质我们可以更简洁的完成最短路。
以最短花费为例,设边权为1,跨路径一次消耗2,则最终消耗=边数+2*换乘数-2,此时,对于同一路径内任意两点,我们先求出图内floyd最短路图,将其中的值全部加上2,再将这些图合并后使用迪杰斯特拉求出两点间最短路,得到的值减去2就是正确答案。注意求起点a到终点b的最小花费时,使用迪杰斯特拉算法更新的点答案均是正确的,所以若是询问的两点的最短路值不是初始值就可以直接输出了。其余几种最短路可以类推。


这三次作业只有最后一次有bug,我将最短路的图设置为了1000,没想到UnpleasentValue的最小值超过了1000.
关于这三次作业的不足,我觉得最大的问题在于继承复用上。因为接口里给出的类型是private,没有办法使用protected继承数据,导致继承时需要把所以数据使用时get一次,而我选择了偷懒的办法,直接将被继承的代码写入了新的代码中,这导致我第三次作业的Railway很长很丑。
Part 2:关于JML
JML(Java Modeling Language)是用于对Java程序进行规格化设计的一种表示语言。
JML能够用形式化语言来规范代码,提高代码可维护性。
JML以注释形式存在,每行以@开始,分为行注释(表示为//@......)和块注释(表示为/*@......@*/)。
JML有原子表达式,量化表达式,集合表达式等等,以及约束类型的类型规格和约束方法的方法规格。
原子表达式有\result和\old()两种,前者用来约束一个方法的返回值,后者用来表示括号内内容在方法执行前的内容。
量化表达式有forall,\exists和\sum,forall表示某范围内的元素均应满足某条件,为全称量词,相应的\exists为存在量词,而\sum返回的是给定范围内表达式的和。
集合表达式则构造一个容器,明确其包含的元素。
操作符包含子类型操作符<,等价操作符<==>,不等价操作符<=!=>,推理操作符==>,上述操作符均返回bool型值。
对于方法规格,我们通过requires语句约束前置条件,通过ensures语句约束后置条件,同时JML也给出了副作用、异常的约束,通过saaignable和modifiable来约束副作用,并利用signals来抛异常。
对于类型规格,主要利用不变式invariant P来进行约束。
部署JML UnitNG/JML Unit
安装后,编写测试样例如下:

测试结果如下:

关于JML的使用,我个人感觉它只应该是一种严格的约束。事实上,我们的代码和JML都是形式化语言,而我们使用JML是为了自然语言表述不清导致代码bug。
我认为,规格应该是宏观的,整体的,针对于方法的输入输出形式,而不应该是对于代码实现的全盘描述,若是后者,那写代码岂不成为了对于规格的翻译?那我们为什么不直接写规格?规格应该是规范而不涉及具体的内部实现。
举个例子,形式化的规格语言可以作为伪代码来描述算法,我们利用这种形式化的语言来详尽的描述算法,在用java语法来翻译规格语言,这显然是在做重复无谓的工作。
在这几次作业中,尤其是最后一次作业,我们可以发现,新增的方法具有大量的规格,不少同学都吐槽过这个规格又臭又长,而我发现这些又臭又长的规格真正有用的部分是在于对于输入输出数据合法性判断以及抛异常的部分,剩下的部分其实是在表达算法思想,而我认为描述算法不应该是规格应该做的。
oo第三次博客-JML规格的更多相关文章
- OO第三次博客作业——规格
OO第三次博客作业——规格 一.调研结果: 规格的历史: 引自博文链接:http://blog.sina.com.cn/s/blog_473d5bba010001x9.html 传统科学的特点是发现世 ...
- [BUAA OO]第三次博客作业
OO第三次博客作业 1. 规格化设计的发展 我认为,规格化设计主要源自于软件设计的两次危机.第一次是由于大量存在的goto语句,让当时被广泛应用的面向过程式的编程语言臃肿不堪,在逻辑性上与工程规模上鱼 ...
- 2019年北航OO第三次博客总结
一.JML语言理论基础及其工具链 1. JML语言理论基础 JML是用于对Java程序进行规格化设计的一种表示语言,是一种行为接口规格语言(Behavior Interface Specificati ...
- oo第三单元博客作业
JML语言理论基础 Java建模语言(Java Modeling Language,JML)是一种进行详细设计的符号语言,他鼓励你用一种全新的方式来看待Java的类和方法.JML是一种行为接口规格语言 ...
- OO第三次博客作业(第三单元总结)
(1)梳理JML语言的理论基础.应用工具链情况 Java 建模语言(JML)将注释添加到 Java 代码中,这样我们就可以确定方法所执行的内容,而不必说明它们如何做到这一点.有了 JML,我们就可以描 ...
- 渡过OO的死劫,了解规格的意义——OO第三次博客总结
当熬过了一次次黑暗,迎接我们的却是被扣的惨不忍睹的JSF ┭┮﹏┭┮ 一.总结调研 规格的历史 传统科学的特点是发现世界,而软件的特点是构造世界.软件的最底层就是0,1,两个离散的值.程序设计语言的三 ...
- OO第三次博客作业---透过代码看设计
不得不说的JSF 经过前几次作业的煎熬.出租车的代码量不断地增多.而出租车问题在不断的完善,这也就牵涉到一个问题,那就是最初出租车程序的设计问题,如果一开始设计的就有问题的话,那么在后来的过程中就会遇 ...
- OO第三次博客作业--第三单元总结
一.JML 语言的理论基础及应用工具链 JML 是一种行为接口规格语言,提供了对方法和类型的规格定义手段.通过 JML 和其支持工具,不仅可以基于规格自动构造测试用例,并整合了 SMT Solver ...
- OO第三次博客作业
一.规格化的发展历史 最早的程序设计都是面向机器,从一开始使用的机器语言,到后面的汇编语言,都是面向机器的语言,编写困难也容易出错.随着需求的发展,程序的编写从面向机器走向面向过程,但由于goto语句 ...
随机推荐
- mysql远程连接以及错误解决&命令行基本操作
现在大家的程序服务基本都是部署在云服务器上,今天我分享记录一下:使用mysql数据库过程中比较常见操作和遇到的问题 环境:lunix 系统(阿里云服务器,华为云服务器,腾讯云等均适用) + mysql ...
- 一文了解Promise使用与实现
前言 Promise 作为一个前端必备技能,不管是从项目应用还是面试,都应该对其有所了解与使用. 常常遇到的面试五连问: 说说你对 Promise 理解? Promise 的出现解决了什么问题? Pr ...
- .NET5修改配置不重启自动生效
.NET Core,.NET5默认配置都是只加载一次,修改配置时都需要重启才能生效,如何能修改即时生效呢,下面来演示一遍. 一.设置配置文件实时生效 1.1配置 在Program.cs的CreateH ...
- .Net Core with 微服务 - 分布式事务 - 可靠消息最终一致性
前面我们讲了分布式事务的2PC.3PC , TCC 的原理.这些事务其实都在尽力的模拟数据库的事务,我们可以简单的认为他们是一个同步行的事务.特别是 2PC,3PC 他们完全利用数据库的事务能力,在一 ...
- Jmeter扩展组件开发(1) - 创建maven工程
前言 没有安装IDEA的伙伴先安装.url:https://www.cnblogs.com/gltou/p/14956060.html 扩展开发实现的两种方式 继承AbstracJavaSampler ...
- Shell系列(4)- 历史命令
格式:history [选项] [历史命令保存文件] 选项: -c:清空历史命令 -w:把缓存中的历史命令写入到历史命令保存文件~ /.bash_history;用户的家目录下 例子: [root@l ...
- django ORM教程(转载)
Django中ORM介绍和字段及字段参数 Object Relational Mapping(ORM) ORM介绍 ORM概念 对象关系映射(Object Relational Mapping,简 ...
- libcurl 概述(翻译)
l名称 libcurl 客户端 URL 传输 描述 这是一个如何使用libcurl进行C语言编程的简短概述.这里提到的每个功能都有特定的手册页.还有 libcurl-easy 手册页,libcurl- ...
- bzoj#4423-[AMPPZ2013]Bytehattan【并查集】
正题 题目链接:https://darkbzoj.tk/problem/4423 题目大意 给出一个\(n*n\)的网格图,然后四联通的点之间连接.每次删掉一条边求这条边的两个点是否连通.强制在线. ...
- P4640-[BJWC2008]王之财宝【OGF,Lucas定理】
正题 题目链接:https://www.luogu.com.cn/problem/P4640 题目大意 \(n\)种物品,其中\(t\)种物品是有个数限制的,第\(i\)种限制为\(b_i\),求选出 ...