北航面向对象OO第三单元——JML
简介
- 本单元借助JML(Java Modeling Language),训练了我们关于的“规格(specification)”的意识和思想
- 本单元代码难度较低,简单来讲就是给你规定好明确要求来实现函数,因此自己不需要动脑子设计很多东西
- 在阅读本文时,我假设你已经了解了第三单元作业的内容
JML简介
- Java Modeling Language是一种对java程序的形式化描述。
- 形式化描述就是不借助自然语言,而是借助严谨的程序化语言,对方法的输入输出、对象的取值范围等等做出规定。相较于自然语言更加严谨,防止由于自然语言的模糊性造成团队合作的失误
设计
MPerson- 第一次作业时,考虑到拓展性,额外创建了
MRelationNet类,保存一个MPerson认识的人和关系,并创建了MRelation作为MRelationNet保存的基本单位,用来方便给“关系”拓展,比如“亲人”“同事”等等 - 第一次作业之后,发现本次作业是扣你性能的,因此把这些冗余的设计全部删除,采用
HashMap保存MPerson之间的关系。
- 第一次作业时,考虑到拓展性,额外创建了
MNetwork由于有一个
queryBlockSum()方法,要求返回图的连通分量个数。本单元还对性能要求较高,于是采用“并查集”的方式保存人与人之间的关系。但也基本上只针对于这一个方法提升了性能。关于“并查集”推荐一篇帖子,讲解的很好
第三次作业中,又增加了求最短路的方法,我觉得这就不属于OO的范畴了,大家就当成一个算法题随便写写好了
- 提一嘴:Java中对于排列顺序无要求的集合,完全可以用
HashSet或者HashMap保存,比如Dijstra算法中需要查看子节点已经计算出的最短路需不需要更新 - 在C中,我们可以用下标的方式访问,但是Java是一种更为高级的语言,再给节点们额外增加一个“下标”信息就十分协调
- 可以直接使用
HashMap<Person, Integer>记录每一个Person对应的最短路长度 - 再比如保存
MPerson的acquaintances时,直接用HashMap<Integer, Person>,将id与Person映射起来,查找就不需要遍历数组,大大提高了效率
- 提一嘴:Java中对于排列顺序无要求的集合,完全可以用
MGroup- 有一个比较恶心的方法
queryValueSum(),求解Group内保存的人与人之间关系值形成的二维矩阵的所有元素加和。正常求的化复杂度为O(N^2),如果不改就会被别人卡爆 - 想要优化,一般都是采用定义一个成员变量保持实时更新,调用
queryValueSum()的时候只需要返回他就行了。我们需要改三个地方:Group::addPerson, Group::delPerson, Network::addRelation,每一次调用这三个方法都更新该成员的值就可以了
- 有一个比较恶心的方法
异常类们:
- 我还是用一个静态的
HashMap<Intger, Integer>将id与id_count关联起来,每次调用构造函数时更新一下即可。总计数器就用一个静态的int count;。 - 所有异常类模板相同,复制粘贴稍微改一下就好了
- 我还是用一个静态的
测试
本单元另一个很大的收获就是测评。主要学习了
JUnit以及对拍机两种,下面介绍一下。JUnit贴一下安装和使用教程:
安装:https://www.cnblogs.com/wangmingshun/p/6411885.html
使用:https://blog.csdn.net/yitengtongweishi/article/details/80715569
简单来讲,
JUnit可以实现为你编写的每一个方法单独测试,这种测试一般是基于规格的。当然啦,测试代码也得你自己敲出来(啥时候能有自动编写测试代码的玩意嘞,可能这得等到JML这种形式化规格发展完善了才行)以JML为例,你应该保证你的测试样例覆盖所有
requires可能的情况,一般我们取几组中间值,几组边界值和几组越界值即可检查输出的时候也应该根据
ensures检查,尽可能保证全覆盖检查。我们在实际工作中,测试人员与编写人员试互相独立的,测试人员一丢丢都不能相信写代码的,尽量测全了。听上去很麻烦是吗哈哈哈哈,我也这么觉得。所以我们通常只对比较复杂的函数(比如求连通分量个数、最短路)进行测试,简单的小函数就不管了
优点:
- 是针对方法的单元测试,可能的情况相对较少,方便构造测试样例
- 不需要改变源代码,解决了
print调试的麻烦
缺点:
- 麻烦
- 对于我们这种小项目来说,不值得为了一个方法设计复杂的评测算法保证覆盖,性价比不高
- 仅能测试方法内实现是否正确,项目综合在一起是否正确无法保证
对拍机
- 前几单元我就写过一次评测机,原因是觉得自己写评测机无法保证我的“标准输出”就是正确的。第一单元可以有现成的Python库,第二第三单元都不好搞。所以对测评机一直比较消极
- 后来我“意识到”(早就知道了但是没有”意识到“),我可以写对拍机而不是评测机。
- 对拍机就是把好几个人的程序放在一起跑,比较大家的输出结果是否相同。这就基本解决了正确性的问题。3个人以上一起跑就很难会出错了
- 相信看到这里,你已经明白要怎么写了对吗( •̀ ω •́ )✧
- 思路(Python):
- 用随机数随机生成测试数据
- 用
subprocess.Popen跑一下每个人的程序,获得输出 - 比较输出,如果都一样就
ACCPTED!,如果不一样就WONG ANSWER!,输出一下不一样的内容
- 航天工程中会做“正交化设计”,也就是同样的功能用不同的设计实现,这样一个出了bug另一个能顶上。在测试的时候也可以用对拍机这种思路测评两个设计,测试人员就不需要再费尽心思造数据了
心得
关于“规格”与设计
- 编写本单元代码时,最大的体验就是“爽”,因为编写者不需要考虑额外的事情,不用考虑类之间的关系,不需要考虑如何组织整个项目(要求就是在完成了这些设计的情况下才能提出来的),只需要保证实现要求就行了,大大提高了代码效率
- bug减少了。编写代码时只需要关注当前方法是否符合要求,每一个方法都不复杂,bug率大大下降
- 最难的“设计”部分其实课程组都给我们做了,这也是我们未来最重要的难题。我一个软院的室友这学期做软工项目,他们小组设计项目、制定规则花费了大量的时间,一切准备就绪再开始写代码,工程进度就会变得飞快无比。
- 代码能力不会是未来道路上的主要阻碍,只要有要求总能干得出来,最为关键的就是“如何规划整个项目”。老师说“项目设计阶段犯的错误,在代码实现阶段要用10倍的代价弥补”,我深以为然。
一些吐槽:
- 本单元十分强调性能,我认为这与“面向对象”毫无关系,给同学们增加了很多压力,却没有增长“面向对象设计”的能力。
- 我非常不愿意在这样一门课上为了性能额外编写一些东西,我认为这“不面向对象”
- 另外课程组还要求在博客里“总结分析容器选择和使用的经验”,这是Java语言使用技巧,更与面向对象毫无关系
MPerson,MNetwork,MGroup这三个类应当是完全独立的,MNetwork中应该只需要用到Person接口即可。- 然而
Person接口却没有提供更改acquaintances的对外方法,导致MNetwork::addRelation时,必须提前在MPerson定义相应的方法,然后再MNetwork中将Person强行转为MPerson使用该方法,这也非常不”面向对象“ - 诚然,在
Person中规定用怎样的方法更改acquaintances会给实现该接口的人增加许多限制,也不是很”面向对象“。但我认为不规定的话有些弊大于利了
- 然而
关于Python
- 当你想干个什么事,先去搜搜有没有现成的库
- 比如想要随机选取列表中的一个元素,我们有
list.choice()方法,不要自己roll一个随机数,然后再取这个下标下的值啦
北航面向对象OO第三单元——JML的更多相关文章
- OO第三单元——JML规格化设计
OO第三单元--JML规格化设计 JML语言的理论基础以及应用工具链情况 理论基础 JML是对JAVA程序进行规格化设计的一种表示语言,是一种行为接口规格语言.JML整合了Java和JAVAdoc,并 ...
- 面向对象OO第三单元总结
第三单元OO总结博客 1 梳理JML语言的理论基础.应用工具链情况 由于篇幅原因,这里只梳理几个在本单元常用的 注释结构 行注释://@annotation 块注释:/* @ annotation @ ...
- OO第三单元——JML之破分大法
一.Jml总结及应用工具链 总的来说,jml就是对java程序进行规格化设计的一种表示语言,其中最核心的就是规格化,将代码要实现的功能和各项要求与约束不是通过自然语言,而是通过严密的逻辑语言来表达,这 ...
- OO第三单元JML总结
目录 目录一.JML语言的理论基础二.应用工具链三.部署SMT Solver四.部署JMLUnitNG/JMLUnit五.三次作业分析第一次作业第二次作业第三次作业六.总结与心得体会 一.JML语言的 ...
- OO第三单元
OO第三单元 JML语言理论基础,应用工具链 JML语言基础 JML简介 定义: JML 是一种形式化的. 面向 JAVA 的行为接口规格语言 作用: 开展规格化设计.这样交给代码实现人员的将不是可能 ...
- OO第三单元——基于JML的社交网络总结
OO第三单元--基于JML的社交网络总结 一.JML知识梳理 1)JML的语言基础以及基本语法 JML是用于java程序进行规格化设计的一种表示语言,是一种行为接口规格语言.其为严格的程序设计提供了一 ...
- 2020北航OO第三单元总结
2020北航OO第三单元总结 本单元要求是根据JML规格完善代码,初看是一个简单的代码照搬实现的东西,但最后才发现由于CPU时间的限制,还考察了大量优化策略及数据结构中关于图的知识,是一次非常注重细节 ...
- OO第三单元(地铁,JML)单元总结
OO第三单元(地铁,JML)单元总结 这是我们OO课程的第二个单元,这个单元的主要目的是让我们熟悉并了解JML来是我们具有规格化编程架构的思想.这个单元的主题一开始并不明了,从第一次作业的路径到第二次 ...
- 2020 OO 第三单元总结 JML语言
title: 2020 OO 第三单元总结 date: 2020-05-21 10:10:06 tags: OO categories: 学习 第三单元终于结束了,这是我目前为止最惨的一单元,第十次作 ...
随机推荐
- 巧用SpringBoot扩展点EnvironmentPostProcessor
我们的项目是单体项目,使用的是springboot的框架,随着对接的外部服务越来越多,配置文件越来越臃肿..我们将对接的外部服务的代码单独抽离出来形成service依赖,之后以jar包的形式引入,这时 ...
- SpringBoot | 1.4 数据库事务处理
前言 前面讲解了Sring的AOP,可以知道它是用来抽取公共代码,增强方法的.而在JDBC操作数据库进行数据处理时,有很多重复的公共代码:事务的提交与回滚跟AOP的约定流程很相似.因此,Spring数 ...
- WPF教程四:字段、属性、依赖项属性的演变过程
这个章节主要讲解属性是什么,为什么会演变出依赖项属性,依赖属性的优势是什么.以及如何更好的使用属性和依赖项属性. 一.属性 属性是什么. 翻了好几本C#的书和微软的文档,我觉得对属性讲解比较好理解的就 ...
- Spring常见异常说明
文章要点 Spring bean 的声明方式 Spring bean 的注入规则 Spring bean 的依赖查找规则 Spring bean 的名称定义方式和默认名称规则 XXX required ...
- MOS管开关电路笔记
1.MOS管开关电路是利用MOS管栅极(g)控制MOS管源极(s)和漏极(d)通断的原理构造的电路.MOS管分为N沟道与P沟道,所以开关电路也主要分为两种.P沟道或N沟道共四种类型,但实际应用的只有增 ...
- C语言:char[]操作
C语言中char[]的操作函数1.赋值操作在C语言中,char型数组是不可以直接赋值的.例如在如下的代码中,会得到错误: char c1[20] = "women";char c2 ...
- EXCEL:宏 考场考号打印
Sub addwork() Rem 当前宏是根据学生数量 .每考场人数计算工作表数Dim i As IntegerRem xx为每个考场的人数Rem yy为当前专业标记Rem mm为当前专业考生人数R ...
- [刘阳Java]_纯CSS代码实现内容过滤效果
继续我们技术专题课,我们今天给大家带来的是一个比较酷炫的"纯CSS代码实现内容过滤效果",没有加入任何JS的效果.全部都是应用CSS3的新增选择器来实现的.先看效果截图 实现思路 ...
- awk对某个字段分割处理
工作中遇到要根据文件中某个字段分割成多行文本的处理,想到用awk处理,这里记录下: 问题: 原文件:假设一共2个字段,用"|"分割,其中第二个字段用"#"分割, ...
- kubernetes/k8s CSI分析-容器存储接口分析
更多 k8s CSI 的分析,可以查看这篇博客kubernetes ceph-csi分析,以 ceph-csi 为例,做了详细的源码分析. 概述 kubernetes的设计初衷是支持可插拔架构,从而利 ...