目录
- JML语言与工具链
- JUnit部署与使用
- 三次作业架构分析
- 代码实现中的bug和修复情况
- 心得体会
JML语言与工具链
- 什么是JML
The Java Modeling Language (JML) is a behavioral interface specification language that can be used to specify the behavior of Java modules. It combines the design by contract approach of Eiffel and the model-based specification approach of the Larch family of interface specification languages, with some elements of the refinement calculus.
- JML理论基础梳理
requires
该子句定义了方法的前置条件assignable
列出方法修改的类成员属性。\nothing
则表示方法不改变任何成员属性,是一个pure的方法modifiable
代表方法使用过程中的可修改副作用ensure
定义了后置条件,如返回的结果或者该方法运行后的逻辑结果等等\result
表达式,表示方法返回的逻辑上的正确的结果\old(expr)
表示执行相应方法前表达式expr的取值public normal_behavior
表示方法的正常功能public exceptional_behavior
表示方法的异常功能signals
定义了抛出某异常以及抛出异常的条件语句expr,当expr为true时抛出异常invariant
定义了一个方法的不变的属性
- JML应用工具链
- OpenJml,检查JML语法和进行规格静态检查。
- JMLUnitNG,自动生成测试样例动态检查程序是否符合规格。
- SMT Solver,z3的Solver程序,或者cvc4进行检查。
JUnit部署与使用
-
部署
- 附上作业中JUnit安装指南DEA Junit4配置
-
使用
- 第二次作业对几个复杂的函数进行了测试
- 通过三次作业,前两次的满分和第三次的翻车,已经感受到了JUnit测试的重要性
- 相比起大数据的黑盒测试,JUnit测试可以对代码进行全面而且可靠的模块测试,之后辅以压力测试,才是程序比较可靠的基础。
-
正常测试
@Test
public void testIsConnected() throws Exception {
//TODO: Test goes here...
Graph myGraph = new NeuroGraph();
int id1 = myGraph.addPath(new NeuroPath(1, 2, 3));
int id2 = myGraph.addPath(new NeuroPath(4, 5, 6));
int id3 = myGraph.addPath(new NeuroPath(7, 8, 9));
int id4 = myGraph.addPath(new NeuroPath(2, 5, 8));
int id5 = myGraph.addPath(new NeuroPath(10, 11));
Assert.assertTrue(myGraph.isConnected(1, 3));
Assert.assertTrue(myGraph.isConnected(9, 3));
Assert.assertFalse(myGraph.isConnected(10, 3));
Assert.assertTrue(myGraph.isConnected(1, 5));
Assert.assertTrue(myGraph.isConnected(4, 5));
Assert.assertTrue(myGraph.isConnected(2, 9));
myGraph.addPath(new NeuroPath(-1, 1));
Assert.assertTrue(myGraph.isConnected(-1, 9));
myGraph.removePathById(id4);
Assert.assertTrue(myGraph.isConnected(1, 3));
Assert.assertFalse(myGraph.isConnected(9, 3));
Assert.assertFalse(myGraph.isConnected(9, 5));
Assert.assertTrue(myGraph.isConnected(9, 7));
myGraph.addPath(new NeuroPath(3, 5, 7, 9, 11));
Assert.assertTrue(myGraph.isConnected(3, 11));
Assert.assertTrue(myGraph.isConnected(9, 3));
Assert.assertTrue(myGraph.isConnected(10, 5));
}
- 异常测试
@Test
public void testIsConnectedEx() throws Exception {
Graph myGraph = new NeuroGraph();
int id = myGraph.addPath(new NeuroPath(1, 2, 30));
try {
myGraph.isConnected(-8, 1);
fail("in is connected don't have from");
} catch (Exception e) {
Assert.assertTrue(e instanceof NodeIdNotFoundException);
}
try {
myGraph.isConnected(0, 1);
fail("in is connected don't have to");
} catch (Exception e) {
Assert.assertTrue(e instanceof NodeIdNotFoundException);
}
try {
myGraph.isConnected(0, 0);
fail("in is connected don't have to");
} catch (Exception e) {
Assert.assertTrue(e instanceof NodeIdNotFoundException);
}
}
/*@ normal_behavior
@ requires (\exists Path path; path.isValid() && containsPath(path); path.containsNode(fromNodeId)) &&
@ (\exists Path path; path.isValid() && containsPath(path); path.containsNode(toNodeId));
@ assignable \nothing;
@ ensures \result == (\exists int[] npath; npath.length >= 2 && npath[0] == fromNodeId && npath[npath.length - 1] == toNodeId;
@ (\forall int i; 0 <= i && (i < npath.length - 1); containsEdge(npath[i], npath[i + 1])));
@ also
@ exceptional_behavior
@ signals (NodeIdNotFoundException e) (\forall Path path; containsPath(path); !path.containsNode(fromNodeId));
@ signals (NodeIdNotFoundException e) (\forall Path path; containsPath(path); !path.containsNode(toNodeId));
@*/
public boolean isConnected(int fromNodeId, int toNodeId) throws NodeIdNotFoundException;
- 结合规格要求,对
isConnected
测试程序进行分析- 分为异常和正常情况的测试。
- 正常情况,正反面,加入连接,去边拆分的情况都覆盖了。
三次作业架构分析
- 第一次
- 第二次
- 第三次
- 三次作业的架构多是作业提供的,在写的过程中,对复杂问题的分解,学习了很多。
代码实现中的bug和修复情况
-
第一次作业
- 第一次作业相对简单,在写的过程中,在字典序部分,检查出了bug,后修复,强测100
- 没有发现对方的bug
-
第二次作业
- 采用BFS和并查集连通块涂色,采用JUnit测试,与随机生成的压力测试,强测100
- 没有发现对方的bug
-
第三次作业
- 采用Dijkstra's Algorithm、BSF和连通块,但是由于疲惫和懈怠,没有进行JUnit测试和压力测试,翻车未进入互测。
- 修复发现Dijkstra's Algorithm在写的过程中,出现了NullPointer的bug
心得体会
-
JML
- 由于助教、老师对JML的讲授帮助,掌握JML并不困难。
- 规格是采用相对于自然语言而言,没有二义性的方式来对程序进行架构。规格从逻辑层面的正确性,保证了只要按照规格实现就不会出现问题。
- 这意味着使用规格可以保证团队合作和较大规模的工程在保证正确性的同时更有效率。
-
架构的思考
- 先附上吴老师对中航总工老师讲解的记录关于今天研讨课的几个要点
- 对中航老师的观点,写一些我的看法:
- 架构设计不是一个阶段,而是一个持续的活动。这个观点我非常认同,我在项目和论文学习中,设计,是一个持续的过程,最初是想法到实践的一个蓝图,但是在实践学习反思的过程中,设计的更改是必须的,这也是编程工程中的家常便饭。
- 高校不应该做工程,而是应该做创新。这个观点,我更是非常认同。Nature杂志发过的一篇论文Large teams develop and small teams disrupt science and technology,学校的团队就是小团队,而且学校对学生的教育也是支持创新,支持独立思考,创新甚至革新是很多学校团队的追求。公司(并不太了解)体系庞大,需要体系化管理和工程化方法,创新有先天的不足,适合于工程。所以这是两个不同集体的不同科研倾向,学校应该发挥自身的优势。