OO第三单元作业总结

OO第三单元博客作业

一、JML语言梳理

(1)理论基础

Java建模语言(Java Modeling Language,JML)在Java代码中增加了一些符号,这些符号用来标识一个方法是干什么的,却并不关心它的实现。如果使用JML的话,我们就能够描述一个方法的预期的功能而不管他如何实现。通过这种方式,JML把过程性的思考延迟到方法设计中,从而扩展了面向对象设计的这个原则。

JML引入了大量用于描述行为的结构,比如有模型域、量词、断言可视范围、预处理、后处理、条件继承以及正常行为(与异常行为相对)规范等等。

(2)应用工具链

openJML检查JML是否符合规格。

JMLUnit可以生成测试样例。

二、SMT SOLVER

通过安装OpenJML,部署了SMT SOLVER。

检查JML语法(这里是用cmder缩写了调用jar包的命令,下同):


可以看出JML通过了检查。

使用-rac,-esc会由于OpenJML自身问题导致玄学空指针错误。

但检查稍微简单的JML还是没问题的。例如:

检查出了存在的溢出问题。

三、JMLUnitNG/JMLUnit

要检查的方法如下:

配置好JMLUnit后,使用openjml编译源代码,并使用jmlunit生成测试用例。

可以看到,在当前目录下生成了众多java文件。

编译后目录如下:

之后使用javac编译测试用例,就可以进行测试了。结果如下:

可以看到,检查出了溢出问题。

四、架构设计梳理

第一次作业:

​ Mypath中使用HashSet+ArrayList,MyPathContainer中使用三HashMap降低复杂度。

第二次作业:

​ 朴素地复制代码实现继承。

​ 新增GraphManager类,以邻接矩阵+离散化方式存储图,在MyGraph中实例化。

​ 新增Graphs类,内部设图相关的公共静态方法,包括bfs,folyd等。

第三次作业:

​ 新增RailwayManager类继承自GraphManager,在其基础上实现了最小不满意度、最小换乘、最小票价等方法。

​ 新增UnionFindSets类,实现了一个简单的并查集,是计算连通块的基础。

​ 新增PathMatrix类,用以管理最小票价、最低不满意度等需求。即朴素的不拆点做法。内部存储结果,防止重复计算,提供查询接口和初始化接口,防止违法操作。

​ Graphs类中新增dijkstra方法(考虑到边数复杂度,未用到)。

​ 思考:不拆点做法拥有比拆点做法更高的效率:不拆点最坏情况为:50 *80^3 *4 *120^3(使用floyd算法),这个代价是相对较小的,在强测中,我的cpu时间平均不到4s。对于拆点算法,若不进行优化,则在重复点较多时,复杂度可能超出想象。进行优化后,效率也相对较好。

​ 不拆点算法的正确性其实不难验证。

五、bug修复

​ 比较幸运,这三次作业中没有被找出bug。

六、心得体会

​ 在第一次和第二次作业中,确实体会到了JML带来的规格化的优点,但是在第三次作业中,反而没有了这种感觉。我觉得可能是下面两个原因:

​ 一、JML的规格依赖于底层的逻辑语句,在描述复杂方法的功能时,经常会不得不引入很多中间变量/方法,使人不知所云。也就是为了编写JML增加的数十个辅助方法,不仅增加了理解难度,override也会导致编译错误。

​ 二、第三次作业的问题描述已经包含了绝大部分方法逻辑和功能,只是缺少一些特殊情况,这种情形下,再去耗费大量时间去验证JML规格是没有必要的。

​ 但总的来说,JML还是有其独特的优势的,在描述中小型方法时,可以给出一个简洁而明确的规范,降低了出错的可能性。但是,并不意味着只需要JML就可以了,一份规范的指导书+规范的JML规格,才能获得双倍的可靠性。

posted @ 2019-05-22 11:17  不很稳定的大时钟  阅读(219)  评论(0编辑  收藏  举报