第三单元作业总结

  本单元的内容主要是规格设计,三次作业以方法的规格为基础,逐渐实现一个地铁路线系统。

一、梳理JML语言的理论基础、应用工具链情况

(1)JML语言的理论基础

  JML(Java Modeling Language)是Java的一种建模语言,用以规定类的各种方法需要实现的行为,但对行为的实现方法没有限制。JML以注释的形式存在于源码中,不会对程序本身产生任何影响。利用JML可以对代码进行测试,有利于程序的开发过程。

  一个可能的应用JML的Java源代码文件是这样的:

  代码中:

  requires:表示一个行为所需要的前置条件

  assignable:表示一个行为会对类的哪些数据域进行赋值

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

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

  \forall:全称量词修饰的表达式

  \exits:存在量词修饰的表达式

  \ensures:表示一个布尔值恒为真

(2)JML的应用工具链

  有OpenJML、JMLUnitNG等,来提供对JML的编译和检查和生成相应的测试代码。

二、部署JMLUnitNG/JMLUnit,针对Graph接口的实现自动生成测试用例

  这里选择自己实现的一个简单类。

  测试结果如下:

三、按照作业梳理自己的架构设计,并特别分析迭代中对架构的重构

(1)第一次作业

  由于Path是不可变对象,因此内部用了一个TreeMap对象来支持containsNode(int node)和getDistinctNodeCount()操作,而PathContainer也采用了TreeMap来对关于Path的操作进行支

(2)第二次作业

  第二次作业对于Path和已存在的PathContainer中的方法的实现没有任何改动,但由于需要进行图搜索因此引进了相当于邻接表的edgeMap和用于充当BFS队列元素的Element类。

  

(3)第三次作业

  第三次作业除了在MyPath类中增加了getUnpleasantValue(int)方法外,其余方法与前两次作业相同。对于第三次作业新增的方法,我采用了DFS的实现,因此出现了curPath,curResult等各种状态变量。但本次作业并不能简单地采用DFS实现,因此这次强测的结果不尽如人意。 

(4)迭代中对架构的重构

  本单元中其实我并没有多少重构,都是沿用上次已存在的代码实现。这种方式可能并不太好,因为实际应用中可能会根据需求的变化进行代码的修改,但我并没有对代码进行任何修改就拿来继续用了。

四、按照作业分析代码实现的bug和修复情况

(1)第一次作业

  第一次作业比较简单,我也没在强测和互测中出现过bug。

(2)第二次作业

  第二次作业中我采用了一个BFS算法,但在对队列的操作上用错了数据结构和方法。我的队列本意用LinkedBlockingQueue<Element>,但错误地写成了LinkedBlockingDeque<Element>。这个错误其实无伤大雅,但在后来的出队入队操作中我使用了queue.pop()和queue.push(new Element(fromNodeId))操作,导致数据结构从队列变成了一个栈,再加上自己测试不太充分,因此这个bug保留到了强测。

  不过这个bug的修复倒是很不难,把queue.pop()改成queue.removeLast()就行了。

(3)第三次作业

  第三次作业由于我用错了算法,DFS直接导致TLE,因此强测同样结果不佳。Bug修复我改用了Dijkstra算法,但截至目前还没有完全修复完成。

五、阐述对规格撰写和理解上的心得体会

  我认为JML是一个限制了程序的行为,但不限制程序行为的实现方式的规格。JML规格是设计者写给代码实现者看的,但它仅仅表示了程序的行为,并不能表示程序应有的性能。因此仅仅有JML规格还不够,还需要对性能需求和实现有足够的理解,不然就会出现像TLE这类的错误。

猜你喜欢

转载自www.cnblogs.com/awe23/p/10905574.html