OO第三单元(地铁,JML)单元总结

OO第三单元(地铁,JML)单元总结

  这是我们OO课程的第二个单元,这个单元的主要目的是让我们熟悉并了解JML来是我们具有规格化编程架构的思想。这个单元的主题一开始并不明了,从第一次作业的路径到第二次作业的图再到第三次作业的地铁系统,需求一步步提升,整个架构也变得复杂。这三次作业为我们模拟了一个需求不断进化的过程,也考验了我们在规格之下的架构能力。

一、JML语言的理论基础及应用工具链

  1. 理论基础

    JML(Java Modeling Language)是用于对Java程序进行规格化设计的一种表示语言。JML是一种行为接口规格语言 (Behavior Interface Specification Language,BISL),基于Larch方法构建。BISL提供了对方法和类型的规格定义 手段。所谓接口即一个方法或类型外部可见的内容。JML注释始终位于Java注解(comment)内部,因此它们不会对进行正常的编译代码产生影响。

    注释结构       JML以javadoc注释的方式来表示规格,每行都以@起头。有两种注释方式,行注释和块注释。其中行注释的表示方式 为 //@annotation ,块注释的方式为 /* @ annotation @*/ 。

    JML表达式(常用) \result表达式:表示一个非 void 类型的方法执行所获得的结果,即方法执行后的返回值。

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

              \not_assigned(x,y,...)表达式:用来表示括号中的变量是否在方法执行过程中被赋值。

              \forall表达式:全称量词修饰的表达式,表示对于给定范围内的元素,每个元素都满足相应的约束。

              \exists表达式:存在量词修饰的表达式,表示对于给定范围内的元素,存在某个元素满足相应的约束。

              集合构造表达式:可以在JML规格中构造一个局部的集合(容器),明确集合中可以包含的元素。例如 new JMLObjectSet {Integer i | s.contains(i) && 0 < i.intValue() } 表示构造一个JMLObjectSet对象。

    操作符       子类型关系操作符: E1<:E2 ,如果类型E1是类型E2的子类型(sub type),则该表达式的结果为真,否则为假。

              等价关系操作符: b_expr1<==>b_expr2 或者 b_expr1<=!=>b_expr2 ,其中b_expr1和b_expr2都是布尔表达 式,这两个表达式的意思是 b_expr1==b_expr2 或者 b_expr1!=b_expr2 。

              推理操作符: b_expr1==>b_expr2 或者 b_expr2<==b_expr1 。对于表达式 b_expr1==>b_expr2 而言,当 b_expr1==false ,或者 b_expr1==true 且 b_expr2==true 时,整个表达式的值为 true 。

    方法规格      前置条件(pre-condition):前置条件通过requires子句来表示: requires P; 。其中requires是JML关键词,表达的意思是“要求调用者确保P为 真”。

              后置条件(post-condition):后置条件通过ensures子句来表示: ensures P; 。其中ensures是JML关键词,表达的意思是“方法实现者确保方法执 行返回结果一定满足谓词P的要求,即确保P为真”。

              副作用范围限定(side-effects):副作用指方法在执行过程中会修改对象的属性数据或者类的静态成员数据,从而给后续方法的执行带来影响。JML提供了副作用约束子句,使用关键词 assignable 或者 modifiable 。

  2.应用工具链  

    OpenJML      在IDEA中安装OpenJML插件以调用SMT solver进行规格检查

JMLUnit         在IDEA中安装JMLUnit插件以自动生成测试样例检查规格正确性

二、JMLUnitNG/JMLUnit

  此次测试的类为我自己写的一个比较简易的Path类,类的具体内容如下:

  

  生成的测试文件

  

  测试结果

  

  从结果上来看,自动生成的测试数据主要是0和正负的Integer型最大数这样的极限数据,其中add和containsNode的方法通过了测试而getNode方法并没有通过测试,但是对于getNode方法而言,它的JML规格中requires是要求传入的index要大于等于0,小于size的,所以其实生成的数据有些并不符合规格,需要自行对输入的数据进行规范。但另一方面这也是由于规格中没有规定对异常行为的处理才导致的问题,从侧面反映出JML不好用。

  

  改进之后,getNode方法也通过了测试。

三、作业分析

  第一次作业

    第一次作业要求实现的是一个路径类和路径存储类,JML要求的方法也只是简单的存取查询方法,是JML入门级的理解和代码实现。

    

    这次作业十分的简单,基本是用来让我们熟悉JML和这个单元作业的实现形式的。虽然只是此简单的作业,但就是个两个简单的类为之后的两次作业打了基础,算法和数据结构在这个单元中的重要性也在这次作业中初现端倪。这次作业的实现我基本按照常规思路让我在什么方法实现什么我就在这个方法里想办法实现,Path类由于需要按顺序存储我采用ArrayList进行存储。而PathContainer类由于有许多查询操作所以采用Map类进行存储会比较合适,考虑到我比较懒不想写HashCode,因此我采用了TreeMap作为存储的容器。这次偷懒明显导致了架构的延展性变差,为之后的作业造成了很大的麻烦,但我做这次作业的时候并没有这个认识,还以为这个单元的作业都非常的水,因此掉以轻心,并没有思考很多架构上的问题。而应付了事带来的另一个结果就是没有考虑算法上面的问题,在PathContainer类的distincNodeCount方法中采取for循环遍历的方式进行统计,使得时间复杂度非常高导致了在之后的强测中超时。这个bug其实还是可以归类到架构延展性的问题上,因为在这次作业中不解决这个问题,在下次作业中还是不得不面对。解决方法也并不复杂,就是再加一个TreeMap用以储存节点和节点被存入的次数,并且在每次add和remove方法被调用时更新。

    

    

    由于这次作业我的态度很明显就是赶紧做完敷衍了事,所以并没有什么突出的优点,可以说做的和很多人一样甚至还要差。而这次作业的缺点则十分地明显,那就是偷懒用来TreeMap和没考虑distincNodeCount的时间复杂度,使得架构的延展性变差,为之后的作业造成了麻烦。

    程序出现的bug:distincNodeCount导致的超时

    查别人bug采用的策略:用大量的distincNodeCount来测别人有没有跟我一样没考虑时间复杂度导致超时。

  第二次作业

    这次作业在第一次作业的基础上将PathContainer类改进成了Graph类,属于一次架构上的延展。这次作业的规格要求相对上次作业也变得更为复杂,属于JML的进阶理解,考验了我们的架构能力。

    

    在这次作业中Path类和上次作业的Path类没有任何区别可以直接套用,Graph类相比上次的PathContainer类多了图结构的一些方法,比如说边的查询、节点之间是否相连和最短路径。要存储图就意味着需要一个邻接表,我的邻接表实现采用的时嵌套TreeMap,也就是第一个TreeMap的key是前一个节点,value是第二个TreeMap,第二个TreeMap的key是后一个节点,value是一个整型数据,用于存储前后两个节点之间是否存在一条边。之所以只记录是否存在边而不记录边的权值是因为这次作业的图比较特殊,所有边的权值都是1。而对于计算最短路问题,我吸取了上次,没有考虑时间复杂度的教训,采用了BFS算法来进行计算。然而,从我的类图中不难看出,我这次依然没有考虑架构上的问题,只是在兵来将挡水来土掩,这次作业最好的架构应当是将图单开一个类用来存储,而我依然将图和查询接口写在一起,这给最后作业带来了麻烦。

    

    

    这次作业的优点就是用了BFS算法去计算最短路,有较好的时间复杂度。缺点就是没有思考架构的延展性。

    这次作业出现的bug:没有出现bug

    查别人bug采用的方法:用自己的测试集去测

  第三次作业

    这次作业是这个单元最后一次作业,这次作业将Graph再次升级成了RailwaySystem,要求实现一些地铁相关的方法,十分考验架构和对数据结构的掌握。

       

    可以看到这次作业的类比较上次作业明显的变多了,相应的,这次作业的难度相对上次作业也有明显的提升。这次要在一个基础图的基础上生成不同的三张带权图并且计算各自的最短路。由于对于不同的存入的path存在地铁转乘的问题会导致不同的路径边的权值发生改变,因此我采用的是分点的方法,即将同一个点按所在路径不同分成不同的点,并且这些分出来的点之间都相连。其结果就是将所有边分成了两类,同一路径上不同点之间的边和不同路径同一个点之间的边,即一个点有两个属性——节点编号和节点所属的路径编号。因此我专门创建了一个DevideNode类用于存储分点。同时我开了一个新的类PriceGraph用于存储由基础图生成的图。由于规格要求的三种生成图其本质都是按照分点分出来的两类边赋上不同的权值产生的,所以其实是一张图不同的权值。而另一个要求实现的方法求连通块则可以由上次作业的BFS及其结果来进行计算。正因为要求实现的方法非常的多,再加之我第二次作业的时候没有将图单开一个类,导致这次架构崩盘,在RailwaySystem里存了一张图实现了BFS求最短路,又在PriceGraph里存了几张图实现了dijkstra求最短路算法,可以说是写了一坨屎。雪上加霜的是写出来的架构还存在超时的问题,其中最突出的就是得把所有TreeMap改成HashMap,另一方面,单纯的dijkstra显然是不满足作业对时间复杂度的要求的,因此还需要将起改为栈优化的dijkstra方法。再加上周末比较摸所以时间十分紧张最后写出来的架构不堪入目,至少我是不会去看第二遍的。

    

    

    这次作业毫无优点可言,几乎就是一个拆了东墙补西墙强行拼凑起来的混合物。缺点则非常明显,那就是架构混乱。

    本次作业的bug:会出现超时

    查别人bug的方法:有边界数据测别人会不会超时

四、总结与感悟

    这次作业又一次让我切身体会到了做一个好的架构的重要性,虽说这个单元的主要目的是了解和掌握JML,但架构和数据结构也和作业内容息息相关。

    首先说一下对规格的感受,一开始我对规格的理解就是一个规范的注释,在切身体验了之后我发现规格确实可以作为一个规范的注释来帮助我看懂代码,理解我该做什么,该实现什么。但规格除了注释的作用还起到了规范和引导的作用,规格会告诉你你要实现什么但不会告诉你你该怎么实现,我作为一个程序员要做的就是在规格为我划定的范围内完成自己的架构。

    再说一下对这次作业架构和数据结构的感受,首先不得不承认这次作业我轻敌了,这也导致了我第三次作业的失败,我一直以为这单元作业是一组很轻松的作业,所以并没有考虑很多架构上的事。另一方面,数据结构对这一单元的重要性如此之高我也是始料未及的,我对数据结构的掌握一直不是很熟练,所以第三次作业对我造成了不小的压力。

    总而言之,做好架构才是OO的硬道理。

  

posted on 2019-05-22 17:41 17373253 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/huangxianhao/p/10891442.html

OO第三单元(地铁,JML)单元总结相关推荐

  1. OO第三单元——规格化设计与地铁系统——总结

    OO第三单元--JML的使用与地铁系统 梳理JML语言的理论基础.应用工具链情况 JML The Java Modeling Language (JML) is a specification lan ...

  2. OO第三单元JML规格总结分析

    OO 第三单元博客作业 1. JML语言概述 1.1 理论基础 综述 Java建模语言(Java Modeling Language,JML)是一种进行详细设计的符号语言,使人们用一种全新的方式来看待 ...

  3. java契约式编程_第三单元总结——JML契约式编程

    OO第三单元博客作业--JML与契约式编程 OO第三单元的三次作业都是在课程组的JML规格下完成.完成作业的过程是契约式编程的过程:设计者完成规格设计,实现者按照规格具体实现.作业正确性的检查同样围绕 ...

  4. OO第三单元单元总结

    OO第三单元单元总结 测试过程 黑箱操作和白箱操作 黑箱操作我认为就是通过随机构造合法数据对代码进行测试,在测试过程中应当着重对边界条件.前置条件.结果正确性等方面进行判断.不需要具体到代码的逻辑,通 ...

  5. OO第三单元总结性博客

    OO第三单元总结性博客 JML理论基础与工具链 JML理论基础 JML是一种将java程序规格化表达的一种语言,其描述的是行为的规格,而非具体的代码实现. 通过对程序开展规格化设计,当然前提是使用JM ...

  6. OO第三单元作业总结

    OO第三次作业总结 一.JML (一)JML语言理论基础 (1)JML表达式: JML表达式包括以下几种: 原子表达式如\result(方法执行后的返回值).\old(表达式在相应方法执行前的取值): ...

  7. java jml_面向对象第三单元总结 - JML(Java Modeling Language) - 简体版本

    面向对象第三单元总结 - JML(Java Modeling Language) - 简体版本 一.JML 理论基础 与 应用工具链 1.1 JML 理论基础 JML(Java Modeling La ...

  8. 「BUAA OO Unit 1 HW4」第一单元总结

    「BUAA OO Unit 1 HW4」单元总结 Part 0 写在开头 对我来说,特别是第二次开始,每到一次作业互测截止之时,出强测结果之时,if(强测<90) 心率平稳->心跳加快-& ...

  9. 「BUAA OO Unit 1 HW4」第一单元总结 —— 递归下降思想处理表达式

    「BUAA OO Unit 1 HW4」第一单元总结 目录 Part0 前言 0.1 文章简介 0.2 阅读本文后将有的收获 0.3 阅读本文需要的前置知识 Part1 第一次作业 1.1 程序框架 ...

  10. 国开1253c语言程序设计,人教版三年级数学下册单元测试题全套

    人教版三年级数学下册单元测试题全套 最新人教版三年级数学下册单元测试题全套1 第1单元过关检测卷 一.认真读题,专心填写.(每空1分,共18分) 1.地图通常是按照"( )北,( )南,( ...

最新文章

  1. 分段函数是不是一定初等函数_查漏补缺问题64:一个含多参数分段函数的连续性与可导性讨论...
  2. python基础练习(七)
  3. log4cplus的内存泄露问题
  4. 智能合约重构社会契约 (3)智能合约的自动触发
  5. 前端能读取压缩包内容吗?_解决前端多环境部署的痛点
  6. [云炬创业学笔记]第一章创业是什么测试12
  7. 后台开发人员面试内容——操作系统(一)
  8. 2.30mongodb创建集合,数据管理2.31PHP的mongdb扩展
  9. vue 时区转换_vue---时间戳转换
  10. python 函数中所有print保存csv_python for循环print怎样才能输出csv呢
  11. linux中安装mysql5.1.73_linux安装mysql(5.1.73)
  12. keras分类器模型
  13. MATLAB2016b安装教程
  14. 如何用Carbon Copy Cloner把macOS系统旧硬盘备份到新硬盘上?
  15. Android 知识点 250 —— screencap截屏指令
  16. Android 自定义表格(第一行及第一列固定,其他列可滑动)
  17. 有趣的23000词根
  18. com.google.inject.ProvisionException: Guice provision errors问题解决
  19. 一文读懂 Apache Pulsar详细解析和实战运用
  20. 手机号码归属地查询(php+redis)

热门文章

  1. Springboot 项目打包 Compilation failure: Compilation failure:
  2. Linux部署采集小说源码教程,杰奇linux下远程采集,最新思路及方法
  3. 8.声卡驱动03-自己实现alsa驱动-虚拟声卡-缓存
  4. 设计模式-工厂模式-3种-以手机制造工厂为例
  5. 从游击队到正规军:马蜂窝旅游网的IM系统架构演进之路
  6. 互联网晚报 | 7月10日 星期天 | 快手官宣:7月18日周杰伦独家直播;​400亿额度,秒光!7月总票房破10亿...
  7. Microsoft .NET Framework 4 安装 1603错误的解决
  8. DevExpress TreeList GridView 样式设置
  9. 有关session安全的那些事儿
  10. Unity导入中文文本的解决方法