一. JML理论基础&应用工具链
1.JML理论基础:
JML(Java Modeling Language)是用于对Java程序进行规格化设计的一种表示语言。
JML有两种主要的用法:
(1)开展规格化设计。这样交给代码实现人员的将不是可能带有内在模糊性的自然语言描述,而是逻辑严格的规格。
(2)针对已有的代码实现,书写其对应的规格,从而提高代码的可维护性。
JML语法整理:
a.注释结构
行注释://@annotation
块注释:/* @ annotation @*/
b.JML表达式(仅选取部分罗列出来):
(1)原子表达式
esult表达式:表示一个非void 类型的方法执行所获得的结果,即方法执行后的返回值。
old( expr )表达式:用来表示一个表达式expr 在相应方法执行前的取值。
(2)量化表达式
forall表达式:全称量词修饰的表达式,表示对于给定范围内的元素,每个元素都满足相应的约束。
exists表达式:存在量词修饰的表达式,表示对于给定范围内的元素,存在某个元素满足相应的约束。
um_of表达式:返回指定变量中满足相应条件的取值个数。
(3)集合表达式
可以在JML规格中构造一个局部的集合(容器),明确集合中可以包含的元素。
(4)操作符
子类型关系操作符: E1<:E2 ,如果类型E1是类型E2的子类型(sub type),则该表达式的结果为真,否则为假。
等价关系操作符: b_expr1<==>b_expr2
推理操作符: b_expr1==>b_expr2
c.方法规格
(1)前置条件:requires P;
(2)后置条件:ensures P;
(3)副作用范围限定:assignable P;
(4)signals子句: signals (***Exception e) b_expr;
d.类型规格
(1)不变式invariant
(2)状态变化约束constraint
2.JML工具链
(1)使用OpenJML对实现的代码进行检查:Openjml使用SMT Solver来对检查程序实现是否满足所设计的规格(specification),包括JML语法静态检查,代码静态检查,运行时检查。
(2)使用JMLUnitNG根据JML语言自动生成TestNG测试。
(3)JMLdoc工具可在生成的HTML格式文档中包含JML规范。
二. 部署SMT SOLVER
三、部署JMLUnitNG/JMLUnit
四、作业架构设计
1. 第九次作业
架构设计:
由于是本单元第一次作业,代码很少,所以只是按照jml规格编写了代码,未在架构上花费心思。
类图分析:
复杂度分析:
2. 第十次作业
架构设计:
此次架构直接复制了上回代码,实现了新的类MyGraph。
类图分析:
复杂度分析:
3. 第十一次作业
架构设计:
本次作业,我提出了一种不拆点的做法,帮助了很多同学。在设计时为了复用原来的代码,将之前的PathContainer和Graph声明为了Abstract类,但这也带来了极大的隐患。由于checkstyle对于父类声明为public或protected属性子类使用有极大的限制,导致在完成整个作业后我不得不重构了部分代码,使很多逻辑堆积到了PathContainer类。在重构过程中还因为手残把某处的代码写错,在强测中影响极大。
类图分析:
复杂度分析:
五、bug和修复情况
在本单元最后一次作业中,为了使得代码通过checkstyle修改了部分代码,导致出错,具体如下。
六、对规格的理解和心得
JML是用于对Java程序进行规格化设计的一种表示语言。由于自然语言描述具有二义性,容易产生理解上的偏差,例如在实际工程中,测试人员与程序开发者对于相同问题和需求的理解差异就会造成测试结果的误差。而采用规格化的设计,通过严谨的规格设计,可以避免这样的二义性的出现,也更方便程序员编写精确的高质量代码。在两次课上实验中,即使是一些比较简单的方法,想用JML语言描述好也有一定的困难。在阅读JML方面,第一次作业和第二次作业规格部分还是比较容易读懂的。但是遇到一些功能十分复杂的函数,其对应的规格描述看上去让人十分头疼。尤其是第三次作业中新增方法的规格描述,逻辑复杂,很难理解。想要写出一份语法完全正确的规格描述其实很困难或者说是要花的时间远远比完成程序多。
总之,通过这个单元的学习,了解了规格的相关内容,学习了JML这个规格描述语言,对于面向对象程序的测试是很有帮助的,希望在未来可以多多使用规格描述,掌握这种契约式的编程方式。