OO第三单元总结
理论基础
JML(Java Modeling Language)是用于对Java程序进行规格化设计的一种表示语言。
本章通过给出JML规格让我们来实现以学习这种规格化的语言,同样的也学习了怎样根据代码补充规格,在学习JML的过程中,能感受到规格化设计带来的逻辑的严谨性。
JML表达式中主要有原子表达式和量化表达式,本章学习过程中主要遇到的原子表达式有用来表示返回值的 esult和方法执行前取值的old(expr),量化表达式主要有表示全称、存在、求和的,分别为forall、exists、sum,主要存在于方法规格的书写中。
方法规格通过前置条件、后置条件、副作用范围限定来约束一个方法,同时还能抛出异常,完成方法的规格化表示。类型规格中主要应用了不变式invariant,表示所声明类必须满足的条件。
工具链
JML工具链中,OpenJML用于检查JML语法,JMLUnitNG根据规格自动化生成测试样例,Junit进行单元测试。
JMLUnitNG/JMLUnit
多次报错把我NG了...
架构设计
第一次作业尝试性地完全按照JML规格,使用了静态数组作容器,导致询问权值时非常麻烦,在第二次作业中改成了使用HashMap和ArrayList,并且人员等部分数据用两种容器存了两次,使得部分方法更容易写。
在第二次作业中起初按照JML规格写,导致计算和与方差等数据时复杂度高,故之后采用缓存的写法,每次添加关系都更新状态,调用方法时根据状态返回缓存或者重新计算。
第三次作业中最短路径计算采用Dijkstra算法,点双连通分量采用dfs两次,写了一个新的搜索方法,满足找到两条不同路径且只有首尾相同则返回true。查找连通块数目采用了并查集的方法,新建了一个Set类存有在一个块内的人员。
bug和修复情况
中测等于没测,第一次作业由于容器使用了静态数组,很多方法写起来十分僵硬,dfs也写出问题,由于第一次作业比较简单,bug修复时根据样例输出重写部分方法即可。
第二次作业最初由于没写缓存导致CTLE,互测时也因为这个狠狠被刀,增加了缓存的机制后便修复了。
第三次作业连通块数按照规格写时间复杂度太高了,还有最短路径算法写得不熟练,还出现了方法调用时传入null此类导致超时的bug,修复时改为使用并查集计算连通块数,最短路径未优化被卡,最后终于把所有RuntimeError变成了CTLE和WA,WA的测试点都是输出相差1,令我摸不着头脑,最后结果就是多正确了几个点,这几天再静下心来de一de。
心得体会
第三单元总体来看不是很难,规格化的语言让我避免了许多审题导致的神秘bug,学到了怎样根据JML规格写代码,但是反过来就不太彳亍了。
规格给与我们的是出题者的需求,在性能上需要我们自己去把握。
死板地按照规格写肯定会出大问题,读懂规格而不是去执行它。