第三次博客作业

第三单元博客作业

一:JML基础梳理、工具链

1.注释结构

//@annotation

/*@ annotation @*/

2.JML表达式
  • 原子表达式

    • \result 表示一个非void 类型的方法执行所获得的结果,即方法执行后的返回值。

    • \old(expr) 用来表示一个表达式expr 在相应方法执行前的取值。

    • \not_assigned(x,y,...) 用来表示括号中的变量是否在方法执行过程中被赋值。

    • \not_modified(x,y,...) 限制括号中的变量在方法执行期间的取值未发生变化。

    • \nonnullelements( container ) 表示container 对象中存储的对象不会有null ,等价于

      container != null && (\forall int i; 0 <= i && i < container.length; container[i] != null)

    • \type(type) 返回类型type对应的类型(Class)

    • \typeof(expr) 返回expr对应的准确类型。

  • 量化表达式

    • \forall 全称量词 (\forall int i,j; 0 <= i && i < j && j < 10; a[i] < a[j])
    • \exists 存在量词 (\exists int i; 0 <= i && i < 10; a[i] < 0)
    • \sum 连加求和 (\sum int i; 0 <= i && i < 5; i*i)
    • \product 连乘求积 (\product int i; 0 < i && i < 5; i)
    • \max 返回给定范围内最大值 (\max int i; 0 <= i && i < 5; i)
    • \min 返回给定范围内最小值 (\min int i; 0 <= i && i < 5; i)
    • \num_of 返回指定变量中满足相应条件的取值个数 (\num_of int x; 0<x && x<=20;x%2==0)
  • 集合表达式

    • 可以在JML规格中构造一个局部的集合(容器),明确集合中可以包含的元素。

      new JMLObjectSet {Integer i | s.contains(i) && 0 < i.intValue() }

  • 操作符

    • E1<:E2 子类型关系操作符
    • b_expr1<==>b_expr2 等价关系操作符
    • b_expr1==>b_expr2 推理操作符
    • \nothing \everything 变量引用操作符
3.方法规格
  • 前置条件(pre-condition) 前置条件是对方法输入参数的限制,如果不满足前置条件,方法
    执行结果不可预测 requires P;
  • 后置条件(post-condition) 后置条件是对方法执行结果的限制,如果执行结果满足后
    置条件,则表示方法执行正确,否则执行错误。ensures P;
  • 副作用范围限定(side-effects) 副作用指方法在执行过程中对输入对象或this 对象进行了修改(对
    其成员变量进行了赋值,或者调用其修改方法)。
    • assignable \nothing;
    • modifiable \everthing;
  • signals子句 满足b_expr时抛出异常 signals (***Exception e) b_expr
4. 类型规格
  • 不变式invariant
  • 状态变化约束constraint
5. 工具链
  • openJML

  • JMLUuitNG

二:JMLUnitNG

根据讨论区教程对Demo.java中compare方法进行测试。

结果如下图,
1590906-20190521135546491-677750408.png

可见自动生成样例中数据均为边界条件(如Integer.MAX/Integer.MIN/0等)。

三:架构设计与重构分析

第一次作业

第一次作业较为简单,只涉及到根据JML进行方法编写。类图如下:

1590906-20190521140623636-114837375.png

整体设计,为了使得getDistinctNodeCount()方法复杂度为o(1),维护了两个hash表,并将维护过程放置于增删操作函数中,分散复杂度。

复杂度分析如下:

1590906-20190521140630557-502124254.png
1590906-20190521140638475-1641134910.png

可见整体复杂度与依赖度处于合理范围。

第二次作业

第二次作业MyPath类完全继承上一次设计,MyGraph类在MyPathContainer类基础上实现了新的接口,作业中直接把代码copy到了MyGraph类中,更好的方式应当是继承。

第二次作业由于设计无向无权图的最短路径问题,选择了BFS算法解决。在图类的设计上,将图与算法分离开,图类单独继承Algorithm接口,实现算法和图的分离。

类图如下:
1590906-20190521141546757-106090191.png

复杂度与依赖度如下:
1590906-20190521141551877-900903280.png
1590906-20190521141555045-628572149.png

可见最短路相关方法复杂度较高。

第三次作业

同第二次作业,进行了代码复制,第三次作业涉及到3个不同图的构建与最短路计算以及连通块数目的计算,分别使用BFS,Dijkstra,并查集解决。

类图如下:
1590906-20190521142259152-122651981.png
复杂度如下:
1590906-20190521142306422-1544802195.png
1590906-20190521142313861-456133081.png
可见图工厂的依赖度以及各个新方法的复杂度较高。

四:作业代码实现中的bug和修复情况

第一次作业无bug,

第二次作业因BFS将路径算出以及遍历策略的原因超时,修改后满分。

第三次作业不满意度计算方法出错,且复杂度过高,准备根据标程进行修改。

五:规格撰写相关心得

JML通过离散数学中的逻辑关系对方法与类进行严谨描述,可靠的JML可以使得开发人员对方法的理解更深,不会因为自然语言的二义性导致问题。

实际体验下来,在方法较为简单的情况下,JML确实是优雅且有效的。但在方法复杂度上升时,编写和阅读JML都成为了困难。

转载于:https://www.cnblogs.com/pandapan-buaa/p/10899421.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值