OO第三次博客作业

 JML

JML(Java Modeling Language)是用于对Java程序进行规格化设计的一种表示语言。JML是一种行为接口规格语言 (Behavior Interface Specification Language,BISL),基于Larch方法构建。BISL提供了对方法和类型的规格定义 手段。所谓接口即一个方法或类型外部可见的内容。JML主要由Leavens教授在Larch上的工作,并融入了Betrand Meyer, John Guttag等人关于Design by Contract的研究成果。近年来,JML持续受到关注,为严格的程序设计提供 了一套行之有效的方法。通过JML及其支持工具,不仅可以基于规格自动构造测试用例,并整合了SMT Solver等工具 以静态方式来检查代码实现对规格的满足情况。

JML的表达式是对Java表达式的扩展,新增了一些操作符和原子表达式。同样JML表达式中的操作符也有优先级的概 念。请参见JML语言手册12.3节(Expression)获得完整的优先级列表。需要提醒的是,JML相对于Java新增的表达式成 分仅用于JML中的断言(assertion)语句和其他相关的注释体。特别需要提醒,在JML断言中,不可以使用带有赋值语 义的操作符,如 ++,--,+= 等操作符,因为这样的操作符会对被限制的相关变量的状态进行修改,产生副作用。

原子表达式

\result表达式:表示一个非 void 类型的方法执行所获得的结果,即方法执行后的返回值。\result表达式的类型就是 方法声明中定义的返回值类型。如针对方法: public boolean equals (Object o) ,\result的类型是 boolean , 任意传递一个 Object 类型的对象来调用该方法,可以使用\result来表示 equals 的执行结果( true 表示 this 和 o 相等; false 表示不相等)。

\old( expr )表达式:用来表示一个表达式 expr 在相应方法执行前的取值。该表达式涉及到评估 expr 中的对象是否 发生变化,遵从Java的引用规则,即针对一个对象引用而言,只能判断引用本身是否发生变化,而不能判断引用所指 向的对象实体内容是否发生变化。假设一个类有属性 v 为 HashMap ,假设在方法执行前v的取值为 0x952ab340 ,即 指向了存储在该地址的具体 HashMap 对象,则\old( v )的值就是这个引用地址。如果方法执行过程中没有改变 v 指向 的对象,则 v 和old( v )有相同的取值,即便方法在执行过程中对 v 指向的 HashMap 执行了插入或删除操作。因此 v.size() 和\old( v ). size() 也有相同的结果。很多情况下,我们希望获得 v 在方法执行前所管理的对象个数,这 时应使用\old( v.size() )。作为一般规则,任何情况下,都应该使用\old把关心的表达式取值整体括起来。

\not_assigned(x,y,...)表达式:用来表示括号中的变量是否在方法执行过程中被赋值。如果没有被赋值,返回为 true ,否则返回 false 。实际上,该表达式主要用于后置条件的约束表示上,即限制一个方法的实现不能对列表中 的变量进行赋值。

\not_modified(x,y,...)表达式:与上面的\not_assigned表达式类似,该表达式限制括号中的变量在方法执行期间的取 值未发生变化。

量化表达式

\forall表达式:全称量词修饰的表达式,表示对于给定范围内的元素,每个元素都满足相应的约束。 (\forall int
i,j; 0 <= i && i < j && j < 10; a[i] < a[j]) ,意思是针对任意 0<=i<j<10,a[i]<a[j] 。这个表达式如果
为真( true ),则表明数组a实际是升序排列的数组。
\exists表达式:存在量词修饰的表达式,表示对于给定范围内的元素,存在某个元素满足相应的约束。 (\exists
int i; 0 <= i && i < 10; a[i] < 0) ,表示针对0<=i<10,至少存在一个a[i]<0。
\sum表达式:返回给定范围内的表达式的和。 (\sum int i; 0 <= i && i < 5; i) ,这个表达式的意思计算[0,5)
范围内的整数i的和,即0+1+2+3+4==10。注意中间的 0 <= i && i < 5 是对i范围的限制,求和表达式为最后面的
那个 i 。同理,我们构造表达式 (\sum int i; 0 <= i && i < 5; i*i) ,则返回的结果为1+4+9+16。
\product表达式:返回给定范围内的表达式的连乘结果。 (\product int i; 0 < i && i < 5; i) ,这个表达式的
意思是针对(0,5)范围的整数的连乘结果,即1* 2* 3 * 4==24。
\max表达式:返回给定范围内的表达式的最大值。 (\max int i; 0 <= i && i < 5; i) ,这个表达式返回[0,5)中
的最大的整数,即4。
\min表达式:返回给定范围内的表达式的最小值。 (\min int i; 0 <= i && i < 5; i) ,这个表达式返回[0,5)中
的最小的整数,即0。
\num_of表达式:返回指定变量中满足相应条件的取值个数。 (\num_of int x; 0<x && x<=20;x%2==0) ,这个表
达式给出(0,20]以内能够被2整除的整数个数,得到的数目为10。一般的,\num_of表达式可以写成 (\num_of T x;
R(x);P(x)) ,其中T为变量x的类型,R(x)为x的取值范围;P(x)定义了x需要满足的约束条件。从逻辑上来看,该表达
式也等价于 (\sum T x;R(x)&&P(x);1) 。

工具链:基于JML的工具较为完善。Iowa State JML tools提供了断言检查编译器jmlc;jmldoc可以生成含有额外JML信息的Javadoc;jmlunit根据JML生成单元测试。此外还有ESC/Java2(拓展的静态检查工具)、OpenJML(ESC/Java2的继承者)等等。

junit

部署Junit:

第一种方法:

  1、下载junit的jar包,目前它的版本是junit4.12,可以从www.junit.org上下载。

  2、在要使用Junit的project名上,点击properties--java build path-libraries, 点击Add External JARs,把Junit包点上就行了。如图所示,点击Add External JARs,选择相应的Junit包

第二种方法:

  1、在要使用Junit的project名上,点击properties--java build path-libraries, 点击Add library,选择JunitT即可。如图所示,点击Add library,在弹出的对话框中选择Jnuit。

架构设计

第一次作业

 

 

第二次作业

 

 

第三次作业

 

 

 

 

 分析代码实现的bug和修复情况

第一次作业的bug来源于cpu时间超出范围,在上了当周五的研讨课后发现内存限制相对较为宽松,而cpu_time限制相对严格,于是改用数组和hashSet两种数据结构进行处理并成功修复bug。

第二次作业未发现bug。

第三次作业因为自己大一的时候数据结构就没有学得太好,没有设计出一个很好的算法,emmm,就是用的最笨的方法,每次查询所要求的的路线都是把所有路线找出来然后进行比较,可想而知这样的算法直接导致强测cpu_time全爆了,为了修复这个bug需要将整体算法都全部推翻更改,并且重新选择适合自身算法的数据结构,工作量太大,最终并未来得及修复。

对规格撰写和理解上的心得体会

JML对于复杂工程的明确分工,代码的交接和维护都具有十分重要的意义,但是jml的编写同样是十分困难的,一个写得不好的jml哪怕写得东西的对的,对于收到规格要求的人员来说也很有可能看得一头雾水,所以就要求架构师对模块的划分要尽量细致,并且写出的jml要尽量简单明确来让阅读者能对此规格能有一个清晰的认识。

posted @ 2019-05-21 22:39  万秋驰  阅读(149)  评论(0)    收藏  举报