JML规格编程系列——OO Unit3分析和总结
本文是BUAA OO课程Unit3在课程讲授、三次作业完成、自测和互测时发现的问题,以及倾听别人的思路分享所引起个人的一些思考的总结性博客。主要包含JML相关梳理、SMT Solver验证、JML单元测试、设计策略、代码度量、BUG测试和心得体会等内容。
目录
一、JML简单梳理
1.1 JML语言理论基础
The Java Modeling Language (JML) is a behavioral interface specification language that can be used to specify the behavior of Java modules. It combines the design by contract approach of Eiffel and the model-based specification approach of the Larch family of interface specification languages, with some elements of the refinement calculus.
JML(Java建模语言)是一种进行详细设计的符号语言,它鼓励我们用一种全新的方式看待Java的类和方法。面对对象的分析和设计的一个终于原则就是过程性的思考应该尽可能地推迟。Java建模语言在Java代码中增加了一些符号,这些符号用来标识一个方法是干什么的,却不关心它的实现。通过这种方式,JML把过程性的思考延迟到了方法设计中,从而拓展了面对对象的这个原则,同时通过引入大量用于描述行为的结构,比如有模型域、量词、断言可视范围、预处理、后处理、正常行为与异常行为等等,这些结构就使得JML非常强大了。通过分析JML,我们能够更为精确地了解代码的用途,减小引入bug的几率,更高效地检测并纠正代码的bug等。
1.2 JML应用工具链
除了OpenJML、JML Editing、JMLUnitNG以外,常用的JML工具还包括以下:
- The AspectJML tool is able to specify and do runtime assertion checking for both Java and AspectJ programs. Ajmlc uses aspect-oriented compilation techniques to provide significantly improved runtime assertion violation messages, and also works with JavaME.
- The jml4c tool is a JML compiler built on the Eclipse Java compiler. It translates a significant subset of JML specifications into runtime checks. Notable features of JML4c include (1) support for Java 5 features such as generics and enhanced
for
loops, (2) support for nested classes, (3) improved compilation speed, and (4) improved error messages. Using JML4c, one can now verify Java 5 classes annotated with JML specifications. - Sireum/Kiasan for Java, which is a JML contract-based automatic verification and test case generation tool-set for Java program units.
- JMLEclipse, which is a pre-alpha version of the JML tool-suite developed on top of Eclipse's JDT compiler infrastructure.
- JMLOK is a tool that uses random tests to check Java code against JML specifications and suggest likely causes for non-conformance problems it finds.
二、SMT Solver的部署和验证
因OpenJML不能支持\forall、\exists,本次作业中无法完成测试验证,略。
三、JML单元测试
为了规避\forall和\exists,作业中的其他方法过于简单,改为使用以下测试代码进行测试:
package test; public class Test extends Exception{
public static void main(String[] args) {
try {
divide(35, 7);
} catch (Exception e) {}
} /*@ public normal_behavior
@ requires b != 0;
@ ensures \result == a / b;
@ also
@ public exceptional_behavior
@ requires b == 0;
@ signals (Exception e);
@*/
public static int divide(int a, int b) throws Exception {
if (b == 0) {
throw new Exception("Divided by zero!");
} else {
return a / b;
}
}
}
即一个简单的除法(整除),要求除数为零时报错,否则需要输出正确的答案。
测试的结果如下:
可见自动构造的测试数据是使用0,最大正数和最大负数等几个极端数据生成的,这一定程度的和易出现bug的情况相符。
四、架构设计梳理
4.1 第一次作业
4.1.1 类图
4.1.2 简析
第一次作业较为简单,从互测来看同学们的实现也较为类似,基本上按照规格实现功能不需要做很大的改动,选择合适的容器即可完成任务。即对于Path,使用ArrayList即可;对于PathContainer,我采用了双ArrayList,现在来看,实际上使用双HashMap在编写时更直观清晰一些。
4.2 第二次作业
4.2.1 类图
4.2.2 简析
本次作业继承了PathContainer,在保持其原有功能的同时增加了两点间的距离计算,此为本次核心任务。大致有两种不同的设计理念,其一是在add Path和remove Path时使用Dijstra、Floyd等算法计算并缓存所有点之间的距离等信息,可以使查询在瞬间完成,另一种是在查询时才使用DFS等算法来计算距离,则对图结构影响的操作执行起来更快。我采取的是前者,主要在影响图结构的操作执行时更新所有路径容器、距离矩阵、自环统计这三个容器。在修复的时候,为了提升性能,我映入了映射机制,将输入的结点映射到1到250并改用静态数组。因此,除了增加映射机制从而改变了Path的容器和添加、删除方法之外,其他方面基本上无需对上一次的代码进行重构,而增加新功能。
4.3 第三次作业
4.3.1 类图
4.3.2 简析
本次作业继承了Graph,在保持其原有功能的同时增加了更多的要求,基本上都可理解为带权路径的相关最小路径求解,以及需要求联通块数。仍然存在刚才提到的两种设计理念。我仍然使用在图的结构改变时计算所有结果的理念,并继续使用了映射机制。本次对最小路径、最少换乘、最少费用、最低不满意度的计算,实际上是拥有相似性的,都可以通过单程最近距离+换乘两步使用两次Floyd算法完成,因此我将上一次的代码重构为工厂模式,将进行某种特定距离的矩阵的运算封装成产品。联通块数目则单独使用一种算法,由于距离矩阵已经被计算,也可以非常简单地算出。
五、测试与BUG分析
5.1 第一次作业
本次作业中强测出现了超时的问题,但功能是正确的,原因在于代码设计不够合理。原先采用的设计是每次调用计算distinct nodes把所有点加入HashSet重新计算一遍,这是没有必要的,应该直接设置一个HashSet容器来存储所有distinct nodes,并改成每次加入或删除Path时就更新一次该容器,则查询时不再需要重新计算,从而节约CPU运行时间。
本次作业的互测中没有发现bug。
5.2 第二次作业
本次作业中强测也出现了超时的问题,但功能是正确的,原因在于使用的算法不够合理。使用的是一种添桥式的动态规划算法,但由于是每增加一条边更新一次,效率实在太慢,因为增加一条路径时可能有很多条边,而标准的Floyd算法只需要在添加后更新一次即可,就节约了CPU时间,从而不会超时。
由于超时严重,在本次作业的互测分组中发现了较多的bug,主要有使用了错误的算法、容器选择不合理等。主要根据测试的限制构造几乎达到上限的随机数据进行测试即可测出主要的bug。
5.3 第三次作业
本次作业的强测中没有出现bug,互测时也没有找到别人的bug。
六、心得体会
本单元的学习中,我感到规格的特点和好处,尤其在大型项目中,规格是顶层的设计对底层实现的一种很好的规范和约束,免去了思考具体实现,却又能保证正确性。不仅如此,规格能够清晰界定每个模块的功能,这非常有利于高内聚低耦合化的开发。结合单元测试,规格能使程序具有更好的健壮性和可维护性,规格和文档相结合对团队的合作也有较好的帮助。
我感到撰写规格的时候和写程序时既有相似又有不同之处。相似之处在于写规格时也用到了很多相似度很高的语句,而最大不同之处在于规格的目的并不是分析问题解决问题,而是描述某一事物的所有可能性和状态。如正常情况、异常情况,何种条件下会导致怎么样的结果,对哪些数据有影响,哪些数据没有改变。如果想要准确的描述,还应保证语句的规范,例如对数理逻辑中全称量词和存在量词的使用,才能使规格达到要求。为了能使用OpenJML编写时还应注意一些语法格式,由于这方面工具的不充分(没有自动补全、高亮、纠错等),需要格外注意。
本单元中运用的数据结构技巧也很多,我认为最为精巧的设计方法是第三次作业中将票价、最少换乘、最低不满意度、最近距离问题全部转化为单程最近距离+换乘两步使用两次Floyd算法,仅仅有细节上的差异,因此可以使用工厂模式来进行求值,从而使所有查询都能在极短时间内完成。
JML规格编程系列——OO Unit3分析和总结的更多相关文章
- UML系列——OO Unit4分析和学期总结
一.本单元的架构设计 1.类图 第一次 第二次 2.关键方法和架构简述 总体而言是读取图的时候就完成大部分计算(完成缓存),调用查询方法时只是展示计算的结果,少部分直接计算.主要是设计了各种自己定义的 ...
- 电梯系列——OO Unit2分析和总结
一.摘要 本文是BUAA OO课程Unit2在课程讲授.三次作业完成.自测和互测时发现的问题,以及倾听别人的思路分享所引起个人的一些思考的总结性博客.主要包含设计策略.代码度量.BUG测试和心得体会等 ...
- 多项式求导系列——OO Unit1分析和总结
一.摘要 本文是BUAA OO课程Unit1在课程讲授.三次作业完成.自测和互测时发现的问题,以及倾听别人的思路分享所引起个人的一些思考的总结性博客.本文第二部分介绍三次作业的设计思路,主要以类图的形 ...
- 2019年北航OO第三单元(JML规格任务)总结
一.JML简介 1.1 JML与契约式设计 说起JML,就不得不提到契约式设计(Design by Contract).这种设计模式的始祖是1986年的Eiffel语言.它是一种限定了软件中每个元素所 ...
- OO第三单元总结——JML规格设计
• 1.JML语言的理论基础.应用工具链情况 JML(Java Modeling Language)—— java建模语言,是一种行为接口规范语言( behavioral interface spec ...
- OO第三单元总结——JML规格
一.JML简介 1.JML语言的理论基础 JML(Java Modeling Language)是用于对Java程序进行规格化设计的一种表示语言.JML是一种行为接口规格语言 (Behavior In ...
- OO Unit3 总结
OO Unit3 总结 OO课Unit3人际关系网JML应用技术回顾 BUAA.1823.邓新宇 2020/5/23 梳理JML语言的理论基础.应用工具链情况 方法规格 JML中,同一个方法在不同的条 ...
- OO unit3 summary
Unit3 JML(Java Modeling Language) 是用于对 Java 程序进行规格化设计的一种表示语言,它对于方法内部具体是如何实现的并无要求,只是对方法的接口以及行为进行限制, ...
- 猫哥网络编程系列:HTTP PEM 万能调试法
注:本文内容较长且细节较多,建议先收藏再阅读,原文将在 Github 上维护与更新. 在 HTTP 接口开发与调试过程中,我们经常遇到以下类似的问题: 为什么本地环境接口可以调用成功,但放到手机上就跑 ...
随机推荐
- 退出状态、测试(test or [])、操作符、[]与[[]]区别
一.退出状态 系统每执行一个命令,都会返回一个退出状态,若返回退出状态为0,表示命令执行成功, 若返回退出状态不为0,表示命令执行有错误. echo $? 可以打印出退出状态. 例如:ls echo ...
- 剑指offer:孩子们的游戏(圆圈中最后剩下的数)
题目描述: 每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此.HF作为牛客的资深元老,自然也准备了一些小游戏.其中,有个游戏是这样的:首先,让小朋友们围成一个大圈.然后,他随机 ...
- GPU性能越来越强大,为何直到现在还是不能取代CPU?
从思路上说,GPU相当于火车,一个车头带几十节车厢,一下子把成千上万吨货全给你拉目的地:CPU相当于汽车,拉货旅游样样能干.因此,如果单纯比运力,一列火车比得过成百上千辆汽车:但如果几百人有几百个 ...
- Python17个常用内置模块总结
Python17个常用内置模块总结 1.getpass 2.os 3.sys 4.subprocess 5.hashlib 6.json 7.pickle 8.shutil 9.time 10.dat ...
- 方法名同类名相同如果没有__construct,会被当做构造函数。
简介本文主要罗列些例子,看看当php类名和函数名重名时,php是如何处理的例子<?php class TestObject{ public $subject; private $message ...
- 026_如何在MAC下输入主要国家货币符号?
由于出国旅游啥的经常会记录一些东西,不避免的会遇到各种货币符号 一. 人民币: ¥(sogo输入法切换到中文模式,然后"shift键 + 4"即可) 美元: $(sogo输入法切换 ...
- zk集群部署
一.环境准备 当前环境:centos7.3三台软件版本:zookeeper-3.5.2部署目录:/usr/local/zookeeper启动端口:2181配置文件:/usr/local/zookeep ...
- python初级(302) 2 easygui简单使用
一.复习之前的两个练习,巩固计数循环和条件循环 1.系统生成一个随机数1到5,然后让用户的猜测,若猜对了,提示恭喜你,猜对了,否则提示,对不起,你猜错了(提示,1到5的随机数为:secret = ra ...
- net::ERR_ABORTED 404 (Not Found)
对于按需加载(on-demand-load)或加载外部资源(external resources)(如图片.文件等)来说,webpack的配置,output.publicPath是很重要的选项.如果指 ...
- LLBLGen update table with join
Table1 id Name 1 xxx 2 ooo Table2 Table1Id Table1Name Column1 Column2 Column3 1 sss xxxx xxxx xxxx 2 ...