规格化设计——OO第三单元总结
规格化设计——OO第三单元总结
一、JML语言理论基础、应用工具链
1.1 JML语言
JML(java modeling language)是一种描述代码行为的语言,包括前置条件、副作用等等。JML是一种行为接口规格语言 (Behavior Interface Specification Language,BISL),基于Larch方法构建。
通过使用JML,我们可以忽略一个类、一个方法内部的具体实现,专注于描述方法的预期功能,从而把过程性的思考延迟到方法设计中,扩展了面向对象设计的原则。
1.2 应用工具链
OpenJML:根据JML语言描述对模块的功能实现进行验证,逻辑证明其正确性。
JMLUnitNG:基于JML规格的自动化单元测试工具。
二、部署JMLUnitNG
public class Sub {
/*@ public normal_behaviour
@ requires a > 0 && b > 0;
@ ensures \result == a - b;
@*/
public static int sub(int a, int b) {
return a - b;
}
public static void main(String[] args) {
sub(1, 1);
}
}
在修改代码规格描述,使用OpenJML检验无误后可以生成和编译测试代码:
java -jar ../openjml/openjml.jar -check Sub.java > re.txt
java -jar jmlunitng-1_4.jar Sub.java
javac -cp jmlunitng-1_4.jar *.java
java -jar ../openjml/openjml.jar -rac Sub.java
java -cp jmlunitng-1_4.jar sub_JML_Test
之后即可测试代码,部分结果如下:
[TestNG] Running:
Command line suite
Running:
Command line suite
Passed: racEnabled()
Passed: constructor sub()
Failed: static sub(-5464846548, -5464698148)
Passed: static sub(0, -9632483648)
Passed: static sub(2269875647, -2112489738)
Passed: static sub(-5963483648, 0)
Passed: static sub(0, 0)
Passed: static sub(5967483647, 0)
Passed: static sub(0, 2687483647)
Passed: static main(null)
Passed: static main({})
===============================================
Command line suite
Total tests run: 10, Failures: 1, Skips: 0
===============================================
三、作业架构分析
3.1 容器
第一次作业,只需要实现path和pathcontainer两个类。为了减少方法的时间复杂度,我选择了特定的数据结构,同时尽量把出现频率高的方法(查询)复杂度分担到出现较少的方法(增删)中:我实现了path的hashcode方法并使用了两个hashmap存储path和对应的id,保证查询path的复杂度接近o(n)。同时使用一个hashmap存储每个节点及其出现次数,计算node_count时直接返回size,复杂度小。Path中则采用ArrayList存储路径上的全部点。
3.2 扩展-图
第二次作业需要在PathContainer的基础上增加连通性判断、最短路径等图相关的方法,等同于要求扩展图的数据结构。
我使用了嵌套hashmap存储(节点-(相连的节点-连接次数))来记录图,每次增删路径时修改图。使用floyd算法求解两点最短路径:邻接矩阵original记录点之间的连接关系,每次增删时对应修改original并将新的original复制到二维矩阵routes,在routes中应用弗洛伊德算法可得到点与点之间的最短路径,最短路径不为MAX(代表点之间不连通)即是连通的,可求最短路径。
此外,为了将编号各异的点使用邻接矩阵管理起来,利用“同一时刻不超过250个点”这条数据限制,我将点的编号映射到0-249,代表在矩阵中的偏移。我使用了一个hashmap记录映射关系,使用了一个空闲点的堆栈来记录哪些点仍然可以提供映射。。
3.3 扩展-地铁换乘
由于低估了第三次作业的难度,这次作业的完成情况较为粗糙,设计和编码非常仓促:采用了同学之间普遍认同的算法计算最少换乘次数和最少票价;为了减少出错的可能,把上次作业中与图相关的部分全部封装到了一个类里。综上所述,并无多少自己深入的思考和独特的设计。
第三次作业的要求是扩展求联通块数量的功能和最小带权路径的功能(权值需要自己定义并计算)。
求联通块数量可以利用第二次作业中的图结构,采用单元点出发bfs搜索遍历所有到达点+依次将所有未标记节点作为起点的方式实现。
为了实现计算最少换乘、最小不满意度和最小票价,需要定义新的权。在设置好权值后,应用第二次作业的floyd算法即可,所以本次作业的关键是扩展新的数据结构存储权值。
求最少换乘时,应当把一条path上任意两点之间的边权值设为1;求最小票价时,应该把权值设置为两点之间的最短路径+2;求最小不满意度时则应该把权值设为最小不满意度+32。三种求解最后要相应地减去1, 2, 32以算出正确答案。归纳出三种方法的共性之后可以进行封装归类。
考虑到删除路径时对地铁结构影响较大,每次增删线路时,我都会重新扫描所有path建立新的邻接矩阵存储权值。
在扫描一条path计算权值时,我用到了spfa算法计算最短带权路径。
四、作业中的bug
第二次作业中修改邻接矩阵中自环的时机不对:自环应该在点被去除时消失,而不是在边被去除时消失。
第三次作业中,由于在上次作业中映射path中节点时没有判断该节点是否在图中存在,这个问题严重影响了第三次作业的评测:在强测中大量被包含“不存在于图中的节点”的样例攻击,出现大量nullpointer exception。归根结底,是在封装图的时候把规格和自认为冗余的代码删去了,导致出现了大量异常。(以惨痛的教训学习到规格和考虑重构后果的重要性)
五、单元心得体会
本单元的学习是一个较为完整的体会规格化设计和设计迭代的过程,虽说到了最后一次作业几乎已经无暇顾及阅读繁复的规格,但还是更深入地体会了继承的思想,学到了很多规格化设计的相关思想。
规格化设计一方面可以延迟过程性的思考,专注于描述算法的抽象实现和功能,从而方便了程序设计人员;另一方面,可以做到设计与实现分离,从而被广泛应用于对安全追求较高的大型软件开发中,在保证程序逻辑正确性的前提下分而治之,让不同的人根据规格编写不同的代码,并可以很方便地验证代码的正确性(JML工具链)。
规格化设计——OO第三单元总结的更多相关文章
- OO第三单元——JML规格化设计
OO第三单元--JML规格化设计 JML语言的理论基础以及应用工具链情况 理论基础 JML是对JAVA程序进行规格化设计的一种表示语言,是一种行为接口规格语言.JML整合了Java和JAVAdoc,并 ...
- 【OO学习】OO第三单元作业总结
[OO学习]OO第三单元作业总结 第三单元,我们学习了JML语言,用来进行形式化设计.本单元包括三次作业,通过给定的JML来实行了一个对路径的管理系统,最后完成了一个地铁系统,来管理不同的线路,求得关 ...
- OO第三单元(地铁,JML)单元总结
OO第三单元(地铁,JML)单元总结 这是我们OO课程的第二个单元,这个单元的主要目的是让我们熟悉并了解JML来是我们具有规格化编程架构的思想.这个单元的主题一开始并不明了,从第一次作业的路径到第二次 ...
- OO第三单元——基于JML的社交网络总结
OO第三单元--基于JML的社交网络总结 一.JML知识梳理 1)JML的语言基础以及基本语法 JML是用于java程序进行规格化设计的一种表示语言,是一种行为接口规格语言.其为严格的程序设计提供了一 ...
- 2020 OO 第三单元总结 JML语言
title: 2020 OO 第三单元总结 date: 2020-05-21 10:10:06 tags: OO categories: 学习 第三单元终于结束了,这是我目前为止最惨的一单元,第十次作 ...
- 2020北航OO第三单元总结
2020北航OO第三单元总结 本单元要求是根据JML规格完善代码,初看是一个简单的代码照搬实现的东西,但最后才发现由于CPU时间的限制,还考察了大量优化策略及数据结构中关于图的知识,是一次非常注重细节 ...
- OO第三单元作业(JML)总结
OO第三单元作业(JML)总结 目录 OO第三单元作业(JML)总结 JML语言知识梳理 使用jml的目的 jml注释结构 jml表达式 方法规格 类型规格 SMT Solver 部署JMLUnitN ...
- OO第三单元
OO第三单元 JML语言理论基础,应用工具链 JML语言基础 JML简介 定义: JML 是一种形式化的. 面向 JAVA 的行为接口规格语言 作用: 开展规格化设计.这样交给代码实现人员的将不是可能 ...
- OO第三单元作业总结
OO第三单元作业总结--JML 第三单元的主题是JML规格的学习,其中的三次作业也是围绕JML规格的实现所展开的(虽然感觉作业中最难的还是如何正确适用数据结构以及如何正确地对于时间复杂度进行优化). ...
随机推荐
- es6学习4:async和await
async async函数返回一个 Promise 对象,可以使用then方法添加回调函数.当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句. funct ...
- go 指南学习笔记
1 If for 后面没有小括号.后面的花括号,要在当前行,并且中间有内容,右花括号要单独一行. 因为go会格式化代码,自动插入分号. 2 函数和方法的区别: 方法需要有一个接受者(select ...
- Hadoop综合大作业1
本次作业来源于:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE1/homework/3363 一.课程评分标准: 分数组成: 考勤 10 平时作业 30 爬 ...
- NoSql数据库Redis系列(5)——Redis主从复制
前面介绍Redis,我们都在一台服务器上进行操作的,也就是说读和写以及备份操作都是在一台Redis服务器上进行的,那么随着项目访问量的增加,对Redis服务器的操作也越加频繁,虽然Redis读写速度都 ...
- LC 968. Binary Tree Cameras
Given a binary tree, we install cameras on the nodes of the tree. Each camera at a node can monitor ...
- [译]如何取消本地的git commit提交?
git reset HEAD~1 原文来源:https://stackoverflow.com/questions/4850717/how-to-cancel-a-local-git-commit
- Shell流程控制语句case
case语法格式: case 变量或表达式 in 变量或表达式1) 命令1 ;; 变量或表达式2) 命令2 ;; ...... *) 默认命令 esac case语句流程控制图: 实例: [root ...
- Kubernetes 配置管理 Dashboard(十三)
目录 一.安装配置 1.1 下载 镜像 1.2.安装 1.3.修改 NodePort 二.配置授权 Kubernetes 所有的操作我们都是通过命令行工具 kubectl 完成的.为了提供更丰富的用户 ...
- spring security实现记住我下次自动登录功能
目录 spring security实现记住我下次自动登录功能 一.原理分析 二.实现方式 2.1 简单实现方式 2.2 数据库实现方式 三.区分是密码登录还是rememberme登录 spring ...
- React路由传参的三种方式
方式 一: 通过params 1.路由表中 <Route path=' /sort/:id ' component= ...