OO第三单元小结

一.JML语言理论基础以及应用工具链情况梳理

一句话来说,JML就是用于对JAVA程序设计逻辑的预先约定的一种语言,以便正确严格高效地完成程序以及展开测试,这在不能容忍细微错误的工程领域如航空航天领域有广泛应用。

1.1 JML语言理论基础

本单元我们学习了一些语言理论基础,梳理如下:

1.requires 该子句定义了方法的前置条件

2.assignable子句,列出方法修改的类成员属性。\nothing则表示方法不改变任何成员属性,是一个pure的方法

3.ensure子句,定义了后置条件,如返回的结果或者该方法运行后的逻辑结果等等

4.\result表达式,表示方法返回的逻辑上的正确的结果

5.\old(expr),表示执行相应方法前表达式expr的取值

6.public normal_behavior表示方法的正常功能

7.public exceptional_behavior表示方法的异常功能

8.signals 定义了抛出某异常以及抛出异常的条件语句expr,当expr为true时抛出异常

9.signals_only,强调满足前置条件时候抛出相应异常

10.invariant,定义了一个方法的不变的属性

以及一些量化表达式,集合逻辑表达式等等,在JML手册中有详细介绍,在此就不一一梳理了。

主要是要理解JML对于JAVA程序设计与实现的分离的作用以及其对于整个程序的架构设计以及正确性保证上的重要性。我个人的体会是,在我们的作业中读懂JML其实该次作业就完成了一半了。

1.2 工具链简介

与规格化设计相关的工具主要有:OpenJML,JUnit,JUnitNG等等,Openjml主要帮助我们检查规格化语言JML的语法以及基本逻辑正确性,Junit以及JunitUG则是对JML规格进行测试,前者主要用于单元测试以及一定的自动化测试,后者则主要测试一些边界情况。

二.JMLUnit部署以及其使用

根据zwc大佬在讨论区发的一篇博客上的步骤部署好JMLUnit后,编写测试类:

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class MyPathTest {
  private MyPath path1, path2, path3;

  @Before
  public void before() {
      path1 = new MyPath(1, 2, 3, 4);
      path2 = new MyPath(1, 2, 3, 4);
      path3 = new MyPath(1, 2, 3, 4, 5);
  }
   
  @Test
  public void testEquals() throws Exception {
      Assert.assertTrue(path1.equals(path1));
      Assert.assertTrue(path1.equals(path2));
      Assert.assertFalse(path1.equals(path3));
      Assert.assertTrue(path2.equals(path1));
      Assert.assertTrue(path2.equals(path2));
      Assert.assertFalse(path2.equals(path3));
      Assert.assertFalse(path3.equals(path1));
      Assert.assertFalse(path3.equals(path2));
      Assert.assertTrue(path3.equals(path3));
  }
}

运行后,结果如图,与预期结果一致:

三.作业架构设计梳理

第一次:

第二次

第三次

第三次作业数据结构层如图:

总地来说,三次作业我都运用了Floyd计算最短路以及第三次作业用dfs计算连通块。三次作业架构类似,主要还是在"MyPathContainer"上不断增加数据结构管理相关数据以及增加新的计算方法,实际上,将计算逻辑以及数据结构包装在另外的单独的类里面,我觉得会是更好的设计方式。

这三次作业关键在于数据结构的选择以及时间复杂度的控制,首先将节点编号做一个1-122的映射(Hashmap<real_Id,x_Id>),并采用节点回收机制,这样就可以进行静态数据的玩法了。实际上,无论是两点之间的最短路,还是最少换乘,最低票价亦或最低不满意度,都可以归结为最短路问题的求解,只不过后面三个需要有其他数据结构来支撑,以便构建起正确的边权。当构建好所有的图结构后,一个floyd算法,就可以解决一切。每次加路径以及去除路径的时候,计算好对应的数据,查询的时候就是O(1).

四.bug与修复情况

这次作业由于选择了比较好的数据结构以及求解相关查询的方法,所以本次我自己的作业公测与互测都没有bug。但是在完成作业的时候,仍然在本地测试的时候发现一些bug:

1.在第二次作业的时候,由于我在去边的时候,先删除点再去边,这样的逻辑错误会导致边集数组的访问会出现访问不存在的两点的边。

2.在第三次作业的时候,我采用最原始的dfs来进行连通块的查询,当时网上给出的算法是n个节点,而我定义的MAXNODE为122(大于等于120均可),这样当图中不同节点比较少的时候,我得到的答案是靠近120,当时我懵了好久,是网上写错了吗?思考下发现,由于我们已经加入的path的不同节点很可能是少于120的,所以每次从编号0-122遍历dfs的时候,要先查询该编号是否在映射表中(Hashmap<real_Id,x_Id>),如果存在并且节点没有被访问过才把答案加1,修改之后我连通块的计算就算是完成了。

3.在第三次作业的时候,我会出现查询最少票价的时候返回值是MaxLength=666666666,查看之后,是在增加路径的时候,把对票价数组的对称赋值写成了对相同节点的赋值,导致神必错误。

关于互测:

对拍器是很容易的,主要还是在于数据生成器的强弱。

三次作业我发现了也仅发现了一次别人的bug,就是最大值估计错误,当加入的每条path都不在已有path中存在,并且最大节点数为120的时候,会出现越界错误,这个bug要修起来可能不仅仅是把数组开大这么简单,要牺牲大部分性能或者甚至重构。

五.对规格撰写的心得体会

规格撰写对于像我这样的小白来说,上手难度其实不大,理解基本语法和关键语句,看着已有的例子,其实要写一份较为简单的规格描述比较容易。但是想要完整的针对一次作业,从零开始设计架构,编写规格,完成程序,我觉得还需要更多的学习。

我个人认为,由于Openjml环境比较苛刻,所以想要写出一份语法完全正确的规格描述其实很困难或者说是要花的时间远远比完成程序多。所以,规格撰写在初级阶段,关键要在于逻辑的严密性和正确性,这是保证完整规格化设计后的程序正确性的重要前提。这三次作业的体验明显好于第1、2单元,原因在于每次作业新增需求都不需要重构,只需要在已有的程序上加入一些新的用于管理数据的数据结构和相应的方法罢了,第三单元的每次作业的可拓展性都远远好于之前两个单元我完成的每次作业。可以看见,架构设计对JAVA程序可拓展性和可维护性的重要性。

最后,摆个队形,祝愿OO越来越好,可以让更多的同学和学弟学妹学到更多更多的知识,提升更多更多的能力。

OO博客作业-《JML之卷》的更多相关文章

  1. OO博客作业1:第1-3周作业总结

    (1)基于度量来分析自己的程序结构 注:UML图中每个划分了的圆角矩形代表一个类或接口,箭头可代表创建.访问数据等行为.类的图形内部分为3个部分,从上到下依次是类的名称.类包含的实例变量(属性).类实 ...

  2. OO博客作业3:第9-11周作业总结

    一.总结介绍规格化设计的大致发展历史和为什么得到了人们的重视 1.规格化设计的大致发展历史 规格化设计,又称契约式设计,最早由Bertrand Meyer于1986年提出,出自于<面向对象软件构 ...

  3. BUAA_OO第三单元总结性博客作业——JML

    一.JML 在第三单元的面向对象课程中我们第一次接触了JML语言以及基于JML规范的规格化设计.在之前一系列关于面向对象思想的学习认识中,我们知道了Java是一种面向对象的语言,面向对象思想的一个重要 ...

  4. 第四次oo博客作业

    (1)本单元是撰写UML数据分析器,架构大致如下,在指导书要求的函数外,对于UmlClass类,Umlinterface类,以及状态机,顺序图这四个类重现构造一个类,这个类里有他们所需要的全部信息,另 ...

  5. OO博客作业4:第13-14周作业总结

    一.论述测试与正确性论证的效果差异,比较其优缺点 测试是设计若干组测试用例,运行程序并检验其是否完成预期功能.测试是一种直接发现BUG的方法,可以准确断定什么样的BUG会发生,并通过辅助调试进一步确定 ...

  6. OO博客作业2:第5-7周作业总结

    (1)从多线程的协同和同步控制方面,分析和总结自己三次作业来的设计策略及其变化. 第5次作业:多线程电梯 基本照搬了课件上“生产者-消费者”模型的设计策略,将InputHandler设计为生产者线程, ...

  7. 第二次oo博客作业--多线程电梯

    这次的系列作业是写一个电梯调度,主要目的是让我们熟悉多线程. 第一次作业是一个傻瓜电梯的调度问题,要求也很简单,即每次接一个人就行了.我只用了两个线程,一个是输入线程,一个是电梯线程,输入线程负责从标 ...

  8. 第一次oo博客作业--表达式求导

    (1)说实话我这部分真的不知道写些什么,因为我只有第三次作业写了两个类,前两次都是一个类,一个类的好处可能也就是写起来比较方便(不用抽象什么共性了,直接c语言莽过去),缺点很多,架构不清晰,可读性不高 ...

  9. OO博客作业

    第一次多项式的作业感觉还行,同时用c和java写的话也算是一个从c到java的过渡,也算是有了对 java的初步认识,之后的电梯作业出血了一些小BUG,比如有些情况考虑不完善之类的,也算是对面向对象有 ...

随机推荐

  1. javaWeb快速入门+——初体验-HelloWorld

    文章转载自 https://www.cnblogs.com/1906859953Lucas/p/10821840.html 练习成品下载 https://www.lanzous.com/i9fljkj ...

  2. 小I选宾馆

    小 I 选宾馆 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 小 I 去天津玩啦,一路上,他跟他的同学发生了许多有趣的 ...

  3. centos python版本升级到3.x

    Linux(CentOS)下将Python的版本升级为3.6.2的方法 1.检查确认系统的相关信息 查看内核版本[root@zstest1 ~]# cat /etc/redhat-release Ce ...

  4. CF div2 E. Water Balance

    给你n个数,你可以这样操作:使区间[l,r]的数变成 他们的平均数,求字典序最小的序列. 做法:从左往右逐个比较,比较完之后会形成一个区间,一开始是区间为1的数进行比较,到后来会 变成区间较大的进行比 ...

  5. ubuntu中安装和卸载apache2

    1. 安装apache2 安装命令: sudo apt-get install apache2 启动/停止/重启apache2: service apache2 start/stop/restart ...

  6. Paper: A Novel Time Series Forecasting Method Based on Fuzzy Visibility Graph

    Problem define a fuzzy visibility graph (undirected weighted graph), then give a new similarity meas ...

  7. 220. 存在重复元素 III

    题目: 给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 ķ. 示例 1: ...

  8. vue -- v-model 表单绑定

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. 用navicate 连接本地数据库提示用户名/口令无效

    1.在用navicate连接本地的oracle数据库时,试了oracle几个默认的用户名和密码,但是当我输入时,却提示用户名/口令无效.所以按照网上的办法,cmd,输入了以下命令,修改了几个用户的用户 ...

  10. EF database first

    https://www.cnblogs.com/net064/p/8024150.html 1.EF简介ADO.NET Entity Framework 是微软以 ADO.NET 为基础所发展出来的对 ...