oo第三单元作业总结

oo第三单元作业总结

一、JML理论基础及应用工具链

1.1 JML基本介绍

  JML(Java Modeling Language)是用于对Java程序进行规格化设计的一种表示语言,通过JML及其支持工具,不仅可以基于规格自动构造测试用例,还可以以静态方式来检查代码实现对规格的满足情况。一般而言,其有以下两点主要用途:

  1. 开展规格化设计。这样交给代码实现人员的将不是可能带有内在模糊性的自然语言描述,而是逻辑严格的规格。

  2. 针对已有的代码实现,书写其对应的规格,从而提高代码的可维护性。这在遗留代码的维护方面具有特别重要的意义。

 

1.2 JML理论基础

  JML以javadoc注释的方式来表示规格,主要定义了方法规格和类型规格。

  类型规格指针对Java程序中定义的数据类型所设计的限制规则,一般而言,就是指针对类或接口所设计的约束规则。从面向对象角度来看,类或接口包含数据成员和方法成员的声明及或实现。本单元中主要涉及到不变式限制和约束限制。

方法规格则较为复杂,通常而言,一个方法的JML规格由requires, assignable, ensures(前置条件、副作用范围限定、后置条件)三部分组成,顾名思义,前置条件即为要求调用者确保的条件,后置条件即为本方法确保执行结果满足的条件,副作用范围限定即为执行过程中所修改数据的范围,这样的结构明显体现了契约式编程的思想。

  至于具体表达式的形式,由于较好理解且同离散数学谓词逻辑等有相近之处,故不在此赘述。

 

1.3 JML工具链

  目前JML相关工具链仅有JMLUnit,JMLUnitNG,OpenJML等少数几种,将在下文中尝试将其应用于本单元的作业。

1.3.1 OpenJML验证

  以Network接口为例,使用jar包和solver进行验证,分别进行JML静态检查、Solver静态检查、z3软件检查,命令分别如下:

 java -jar openjml.jar -exec /e/oo/Unit3/Tools/Solvers-windows/z3-4.7.1.exe /e/oo/Test/1Saber/src/com/oocourse/spec3/main/Network.java
 java -jar openjml.jar -check /e/oo/Test/1Saber/src/com/oocourse/spec3/main/Network.java
 java -jar openjml.jar -esc /e/oo/Test/1Saber/src/com/oocourse/spec3/main/Network.java

  其结果如下所示:

  可以看到问题基本上都是找不到符号,我检查了相关路径和包,但也没有查出问题所在。而若使用其验证单个类的项目,则可以通过检测,其中具体原因我也不得而知,也可能是我使用方式根本就不正确,欢迎各位大佬在评论区不吝赐教。

 

1.3.2 JMLUnitNG生成及分析

  首先我们对规格与实现较为简单的方法尝试进行生成和测试,方法、JML规格、自动生成测试结果具体如下:

     /*@ public normal_behavior
       @ requires a!=5;
       @ ensures esult == a + b;
       @ also
       @ public normal_behavior
       @ requires a == 5;
       @ ensures esult == 0;
       @*/
  public static int add(int a, int b)
  {
  return a + b;
  }

  可以看到,此存在明显错误的方法完美的通过了所有样例,且不难发现JMLUnitNG所自动生成的测试样例中仅含有诸如null, 0, Interger.MAX, Interger.MIN等极端数据,可以说是根本没有针对具体的JML规格做出针对性的测试,虽然确实有那么一点用,但是其离真正的自动化生成样例与测试还有很长的路要走。而若将其应用到对MyGroup类各种方法的检测中,抛开很多不支持的语法带来的劈头盖脸的报错之外,我也很难相信它能够构造出有用的测试样例,故不再尝试使用。但是,我认为类似插件指明了一条很好的思路,针对性的自动生成测试样例必将给测试带来质的飞跃,希望我在将来能够有幸见到不管是JML,抑或是其他规格在自动化测试方面所带来的益处。

  综上所述,在我看来,JML相关工具链暂时并没有真正形成体系,且许多项目均已数年没有跟进,用户体验较差,完全不推荐使用。

 


二、作业架构设计

2.1 架构分析

  由于本单元三次作业间差异较小,且不存在重构的情况,因此仅选取最后一次作业架构进行分析,其UML类图如下所示(仅展示自己实现的类,且已略去部分方法):

  MyPersonMyNetworkMyGroup三类主要依照JML规格的限制所设,并实现相应方法。由于部分方法中需要使用到堆优化dij和bfs等图论相关算法,若其全部堆积在MyNetwork类里会使得其超出500行,且不符合单一职责的原则,因此我另设MapAlgorithmEdge类用于相关图论算法。

  MapAlgorithm中,我仅使用虚拟节点id和虚拟边(即将节点和边add的顺序作为其id)进行相关算法的实现,这样不仅使得其更接近于一般算法模板,也省去了查找各类容器带来的时间损耗。

 

2.2 算法选取

  对于一些时间复杂度可能偏高的方法,我均进行了一些优化:queryMinPath方法使用堆优化dij进行单源点最短路径的搜索;isCircle使用并查集的思想,在addRelation时更新各节点最终祖先,以实现查询时O(1)的复杂度,同时实现了queryBlockSum方法的线性复杂度;queryAge系列方法采取缓存的策略,将重要数据在addtoGroup, delFromGroup时进行更新,实现查询O(1)的复杂度;而对于queryStrongLink方法,由于我不知道如何将Tarjan算法用于无向图,且道听途说很容易出错,于是我选择了较为暴力的先查找一条路径,再依次删除其上的点再判断是否连通的方式,也没有超出所规定的的时间范围,值得注意的是,此方法需要对两点直接相连的情况作出特判,我的处理方式是将其直接相连的边删去跑一遍bfs,从结果上来看也是正确的。

  在测试时,针对这些复杂度可能偏高的方法构造针对性的边界数据,并保证其在一个合理的时间范围内。

 


三、bug分析与互测策略

3.1 bug分析

  由于本单元主要易错点在于对JML的理解,因此若搭建评测机的方式是在内部维护一个相同的关系图再与待测程序输出相比较,则可能会出现相同的理解上的错误,显得没有意义。因此,我尝试使用了诸如JUnit单元测试、黑箱对拍等多种测试方法,且主要使用黑箱对拍的方式。

  然而,由于其测试范围有限,且生成的数据对于异常没有较好的覆盖,我在第二次作业的强测中出现了一个bug,其主要是由于addtoGroup方法中异常和正常情况的判断顺序与JML要求不一致而导致的,即我对JML的理解出现了偏差。若我认真使用JUnit单元测试,编写全覆盖的样例,则可以避免这个错误。

 

3.2 互测策略

  本单元的互测我主要采取黑箱对拍的方式,只需少量改动自测阶段所用对拍器便可应用于互测中,其效果如下图1所示,同时,加强对可能出现的算法复杂度过高而超时的测试,为此我专门编写了另一个数据生成器以针对复杂度可能过高的queryMinPath, queryStrongLink等方法生成较为刁钻的数据,以了解极限条件下所用时间,其效果如下图2所示。

 

   此外,我在自测阶段会根据自己对JML的理解记录下一些针对性数据(如1111的限制,queryStrongLink使用找路-删路-找路方法导致错误的数据等),并用在互测中。

 


四、心得体会

  本单元主要内容为JML规格,同时涉及到部分基础算法的实现。

  就JML本身而言,其理解与根据JML实现代码并不难,与前两单元相比可以说是容易了许多,然而,我相信JML本身并不是课程组设置这一单元的重点所在,JML只是规格的一个具体表现形式,而规格才是本单元的核心。通过规格,使得设计顶层架构时无需考虑底层实现细节,而实现代码时根据已有规格进行实现又变的容易了许多,我认为这本质上也是一种解耦。此外,规格对于测试也有着积极的作用。

  此外,通过这一单元对JML的阅读不难发现,JML往往会把简单的方法复杂化,由于其没有诸如路径、强连通分量等离散数学中相关中间概念,所以全部采用了谓词逻辑描述的方式,这种方法对读写JML都造成了很大的困扰,在方法较为复杂时这种问题更为突出,而其贫瘠的工具链更是雪上加霜。在我看来,虽然JML体现了契约式编程的思想,有着一些优点,但其暂时不具有应用价值。

  而对于部分基础算法,这单元暴露出我对其理解仍不够深刻,练习仍不足够的问题。就堆优化dij而言,虽然我理解其原理与具体方法,但习惯了用C实现算法的我在面对java的一系列容器和特性时仍显得手足无措,花费了许多时间用于实现和调试。至于Tarjan算法,我在学习了有向图相关后却不知道如何将其应用在本单元的无向图上,遂作罢。今后我应当更重视基本算法的理解,多加练习,勇于发散。

 


限于水平,本篇难免有纰漏之处,欢迎各位大佬在评论区进行斧正,以上。

原文地址:https://www.cnblogs.com/gottfriede/p/12933806.html