一、JML语言的理论基础、应用工具链情况

  Java Modeling LanguageJML)是一种java的规格描述语言,以特殊格式的注释块形式写在java代码中,描述java类中各方法模块的行为,实现对java程序进行规格化设计的目的。JML语言具有以下特点:

  ·JML语言以注释的形式存在,对java程序的编译与运行没有影响。

  ·JML语言是逻辑语言,无二义性,便于团队之间交流和理解模块的功能。

  ·JML语言通过验证运行结果描述模块的功能,而不必描述中间过程的具体实现,为描述模块功能提供便利。

  由于JML语言的无二义性和验证结果的功能,可以通过程序解释JML语言并在运行过程中检测程序模块的正确性。目前常用的开源JML工具如下:

  ·STM solver

  SMT solver工具可以静态分析代码,检查代码对规格的满足情况。

  ·openJML

  OpenJML可以根据JML代码自动生成针对该模块的junit测试数据,并可以在运行中检测模块运行结果是否符合规格描述。

 

二、自动生成针对MyPathContainer类的测试用例

  由于课程官方提供的接口的JML描述在我的电脑上出现了各种奇怪的编码错误,无奈之下我选择在实现了接口的类中重新编写JML代码,定义规格并测试。自动生成的测试数据与测试结果如下:

  可以看出自动生成的测试数据在传入的参数为基本数据类型时会对多个极端数据进行测试,而当传入的参数为对象时只能测试null的情况。如此自动生成的测试局限性很大,仍然需要自行构造数据进行测试。本次测试中我知使用了openJML默认的测试数据生成方法,我将继续探索是否有能够生成更复杂的测试数据的方法。

 

 

三、作业架构设计

 

  本单元的三次作业均是在课程组提供了JML语言定义的规格的情况下实现接口的定义,每一次作业均继承前一次作业的接口,在原有的功能上添加新的功能。

 

三次作业的类图如下:

 

 

  本次的后两次作业的规格均是继承了前一次作业接口的规格,在其基础上拓展原有的功能或增加新的功能。本意是让我们也通过继承的方式去拓展功能,但由于我每次作业都基本上重构了很多,所以继承的思想在我的作业中体现较少。

  由于Path接口自第一次作业实现之后没有大的改动,因此在讨论程序架构时不再讨论。

  第一次的PathContainer实现了添加、删除路径,查询路径的基础功能,和一个查询不同节点个数的特殊功能。使用nodeList记录每个节点在全部路径中出现次数,并在添加、删除路径时对其进行维护。

  第二次的Graph添加了判断两点是否连通和计算最短路径的功能。我没有继承原来的MyPathContainer,而是直接将它改了名字改成了MyGraph……我不擅长处理继承关系中父子类之间的保护和重载关系,因此保险起见使用了如此的方式。为实现新增的功能,在类中新增了edgeList变量,用于储存path构成的无向图的信息。edgeList是一个稀疏二维数组,使用HashMap嵌套来存储,edgeList[i][j] = n表示由idi的节点到idj的节点有n条边。edgeList也在添加或删除路径时进行维护,计算最短路径时使用广度优先遍历算法进行。

  第三次的RailwaySystem添加了计算多种加权最短路程的功能。因为计算中涉及到换乘的问题,第二次作业中的无向图无法解决,因此维护了一种新的图——拆点图,即将同一编号但属于不同路径的节点视作不同的节点,并在编号相同的节点之间连接一条“换乘边”。因为两个图之间容易混淆,第三次作业中将普通的无向图和拆点图各作为一个类抽象出来(EdgeMapDivideMap类)(实际上普通无向图类在第二次作业中就应该抽象出来),并在拆点图中使用dijsktra算法计算加权最短路径。

  从第三次作业的最终结构中还是可以看出每次添加新需求后形成的模块化结构。MySubway中实现第一次作业中基本的路径添加、删除、查询功能,并植入了edgeMapDivideMap两个类。EdgeMap实现第二次作业的查询连通、最短路径功能和第一次作业特殊的不同节点数功能。DivideMap实现第三次作业的加权路径功能。我是以组合而非继承的方式实现功能的拓展。

 

 

四、bug分析

 

  第三次作业中,我在计算某边的不满意度时,将计算公式由(nodeId % 5 + 5) % 5写成了(nodeId + 5) % 5,导致我遇到ID小于-5的点时便会出现错误,最终甚至没能通过中测。这是一个疏忽,但这侧面证明了自己构造测试数据十分片面,难以注意到自己未曾注意到的方面,我将重点一直放在dijsktra算法的正确性上,完全忽视了节点可能为负数的情况。这时如果能善用openJML来自动生成一些评测数据的话,也许就能避免这一遗憾了。

 

 

 

五、心得体会

 

  由于我尚未能掌握使用工具根据JML规格生成测试用例或在运行中检测模块是否符合JML规格描述的方法,JML对我来说暂时只是一个无二义性描述模块功能的描述性文字。我还需要继续去探索JML工具的更多功能,尤其是自动测试和运行时测试的功能,这对不擅长构造测试数据的我将是极大的帮助。。。

 

posted on 2019-05-22 20:36  黄启元  阅读(186)  评论(0编辑  收藏  举报