JML理论基础与工具链
JML是基于java的规格设计语言,架构设计者将类中数据、方法想要达到的目的通过形式化的语言加以叙述,实现者根据无二义性的形式语言完成算法实现,实现方法与规格叙述可以完全不同,只需满足所需结果即可。JML的核心即在于“抽象”,不同于具体化的java代码实现。
JML有两种主要的用法:
(1)开展规格化设计。这样交给代码实现人员的将不是可能带有内在模糊性的自然语言描述,而是逻辑严格的规格。
(2)针对已有的代码实现,书写其对应的规格,从而提高代码的可维护性。这在遗留代码的维护方面具有特别重要的意义。
JML工具链有Openjml、SMT Solver、JUMLUnitNG等,可用于生成测试用例、检查JML是否规范等。
JMLUnitNG生成测试用例
配置过程中遇到了各种诡异的报错,一直没有跑通例如
org.jmlspecs.openjml.JmlInternalError: The operation symbol ++ for type java.lang.Object could not be resolved
尝试其他方法后又出现了以下报错
/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home/lib/ct.sym(META-INF/sym/rt.jar/java/lang/annotation/Retention.class): 警告: 无法找到类型 'Profile+Annotation' 的注释方法 'value()'
(此前已经把jdk降到1.8并修改了package了,依然是这个报错)
如果其他同学遇到过类似问题的话求指点一下
三次作业架构设计与bug情况
第一次作业
第一次作业架构简单,没有涉及复杂算法(唯一麻烦的就是iscircle的BFS/DFS了),以学习JML规格为主
UML类图
三次作业架构设计与bug情况
第一次作业
第一次作业架构简单,没有涉及复杂算法(唯一麻烦的就是iscircle的BFS/DFS了),以学习JML规格为主
UML类图
设计
由于复杂度不高,全部采用Arraylist存储,iscircle采用非递归DFS
bug
使用对拍程序与同学拍了几百轮,没有发现bug;公测全部通过,互测全屋0hack
然而,这只是暴风雨前的宁静,悲剧的序幕……
第二次作业
第二次作业增加了Group接口,涉及到了遍历的复杂度的问题,在算法上有所要求。
UML类图
设计
对于Group内各种query的方法,本来设计了以dirty域为核心的缓存机制,然而本地测试发现优化前后性能差别不大,又由于时间问题没有充分测试优化后正确性,因而不敢提交优化版本,提交了无脑O(n2)算法
此外对于group内和person内均采用了hashmap和arraylist双重存储的方式,前者负责查找,后者负责遍历,效果不错。有同学全程arraylist导致大量CTLE,实属悲剧,可见不能完全依赖JML的描述进行实现
bug
使用对拍程序与同学拍了几百轮,没有发现bug,然而强侧爆了四个点……其中三个点是因为addtogroup的人数1111限制与异常处理写反了顺序,而对拍没有构造一组内如此多人的数据,可见随机生成的数据针对性不够强
另一个点就是O(n2)超时,之前本地测试时间差距不大可能还是数据不够强的原因,改成修复阶段改成dirty后就顺利通过了
互测大开杀戒,全屋10次成功hack9次归我,属实带恶人
第三次作业
第三次作业在Network类增加了一些方法,考察了一些数据结构算法,难度稍高,不仅仅局限于功能实现,还必须小于等于标程的复杂度,同学们在算法性能上花费了很长的时间
UML类图
设计
blocksum采取的方法是设置field存储,add person时+1,add relationship如果两个人原本不连通就-1,简单有效;minpath采用dijkstra,使用java内置优先队列(基于堆),复杂度为Onlogn;stronglink首先一次dfs找到第一条通路,然后依次删去路径上所有点,若删去某个点后不连通则返回false,全部连通则返回true。
bug
强测出现了CTLE,主要是minpath采用dijkstra实现时没有break并且paths存的不是id而是索引,前者增加了常数项,后者增加了On的查找复杂度。互测中再次hack出了其他人8个bug,均是功能性的问题
心得体会
规格设计是软件开发中的重要内容,本单元中我们通过学习JML理解了契约式编程的理念,即用户保证调用时符合前置条件,实现者保证符合后置条件,通过规格作为桥梁。这种设计者与实现者交互的模式对我们有很大启发。
此外本单元虽然没有性能分,却仍然没有摆脱优化的厄运,我们花了大量时间来设计算法,优化时间复杂度,复习数据结构,老师的本意可能是告诉我们不要完全照着规格写代码,但从大家花费的时间和学习效果来看难免有本末倒置之嫌,希望以后课程会有所改进。