本文是BUAA OO课程Unit3在课程讲授、三次作业完成、自测和互测时发现的问题,以及倾听别人的思路分享所引起个人的一些思考的总结性博客。主要包含JML相关梳理、SMT Solver验证、JML单元测试、设计策略、代码度量、BUG测试和心得体会等内容。

目录

一、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分析和总结的更多相关文章

  1. UML系列——OO Unit4分析和学期总结

    一.本单元的架构设计 1.类图 第一次 第二次 2.关键方法和架构简述 总体而言是读取图的时候就完成大部分计算(完成缓存),调用查询方法时只是展示计算的结果,少部分直接计算.主要是设计了各种自己定义的 ...

  2. 电梯系列——OO Unit2分析和总结

    一.摘要 本文是BUAA OO课程Unit2在课程讲授.三次作业完成.自测和互测时发现的问题,以及倾听别人的思路分享所引起个人的一些思考的总结性博客.主要包含设计策略.代码度量.BUG测试和心得体会等 ...

  3. 多项式求导系列——OO Unit1分析和总结

    一.摘要 本文是BUAA OO课程Unit1在课程讲授.三次作业完成.自测和互测时发现的问题,以及倾听别人的思路分享所引起个人的一些思考的总结性博客.本文第二部分介绍三次作业的设计思路,主要以类图的形 ...

  4. 2019年北航OO第三单元(JML规格任务)总结

    一.JML简介 1.1 JML与契约式设计 说起JML,就不得不提到契约式设计(Design by Contract).这种设计模式的始祖是1986年的Eiffel语言.它是一种限定了软件中每个元素所 ...

  5. OO第三单元总结——JML规格设计

    • 1.JML语言的理论基础.应用工具链情况 JML(Java Modeling Language)—— java建模语言,是一种行为接口规范语言( behavioral interface spec ...

  6. OO第三单元总结——JML规格

    一.JML简介 1.JML语言的理论基础 JML(Java Modeling Language)是用于对Java程序进行规格化设计的一种表示语言.JML是一种行为接口规格语言 (Behavior In ...

  7. OO Unit3 总结

    OO Unit3 总结 OO课Unit3人际关系网JML应用技术回顾 BUAA.1823.邓新宇 2020/5/23 梳理JML语言的理论基础.应用工具链情况 方法规格 JML中,同一个方法在不同的条 ...

  8. OO unit3 summary

    Unit3 ​ JML(Java Modeling Language) 是用于对 Java 程序进行规格化设计的一种表示语言,它对于方法内部具体是如何实现的并无要求,只是对方法的接口以及行为进行限制, ...

  9. 猫哥网络编程系列:HTTP PEM 万能调试法

    注:本文内容较长且细节较多,建议先收藏再阅读,原文将在 Github 上维护与更新. 在 HTTP 接口开发与调试过程中,我们经常遇到以下类似的问题: 为什么本地环境接口可以调用成功,但放到手机上就跑 ...

随机推荐

  1. Kubernetes Pod 生命周期

    一. Pod Hook Kubernetes 为我们提供了生命周期钩子,就是我们所说的Pod Hook,Pod Hook是由kubelet发起的,当容器中的进程启动前或者容器中的进程终止之前运行.这是 ...

  2. Windows下多个JDK版本的切换方法

    问题 因我之前在window中无法命令行输入,后来发现是电脑中存在多个JDK,导致设置混乱. 于是,我继续深入研究了当电脑存在多个JDK的情况下,如何设置想要的JDK版本. 步骤 1.更改环境变量 进 ...

  3. Scala函数柯里化(Currying or Curry)

    柯里化(Currying) 把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术. 简单的实现如下: scala> def ...

  4. 剑指offer:链表中环的入口结点

    题目描述: 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null. 思路分析: 这道题首先需要判断链表是否存在环,很快就能想到用快慢指针来判断. 由于快慢指针的相遇位置并不一定为链 ...

  5. flask 开发接口测试平台

    flask 开发接口测试平台 数据库,forms  views  视图, 数据库如下: # encoding: utf-8 ''' @author: lileilei @file: models.py ...

  6. 含有虚拟列的表 怎么用EXP导出?

    最近导一个测试库,报有虚拟列的表不支持,如下: EXP-00107: Feature (VIRTUAL COLUMN) of column CTB_CLIENT_SUBMIT_TIME_MONTH i ...

  7. node 部署教程二

    转:https://www.cnblogs.com/yesyes/p/7168449.html 这篇文章主要介绍如何在服务端跑vuejs的项目,如果上一篇教程你成功输出了hello world,那这一 ...

  8. android -------- DES加密解密算法

    DES全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1977年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),并授权在非密级政府通信 ...

  9. Electron 入门第一篇

    官网:http://electronjs.org/docs/tutorial/application-architecture 转载:https://blog.csdn.net/qq_33323731 ...

  10. [转]IntelliJ IDEA 2019 上手

    原文地址:https://www.jianshu.com/p/77f81d5fcf02 一.聊一聊Java IDE 作为程序员,经常会看到这么一类的话题:文本编辑器与IDE哪家强.常见的文本编辑器如E ...