OO_BLOG3_规格化设计(JML学习)

目录

  • JML语言学习笔记
    • 理论基础
    • 应用工具链情况
    • JMLUnit/JMLUnitNG
  • UNIT3 作业分析
    • 作业 3-1 实现两个容器类Path和PathContainer
    • 作业 3-2 实现容器类Path和数据结构类Graph
    • 作业 3-3 实现容器类Path,地铁系统类RailwaySystem
  • 规格撰写的心得与体会
  • 最后,衷心感谢为这门课程辛苦付出的老师和助教。???

JML语言学习笔记

理论基础

1. 注释结构

2. JML表达式

  • 原子表达式,量化表达式,集合表达式,操作符,etc.

3. 方法规格

  • 前置条件(pre-condition)
  • 后置条件(post-condition)
  • 副作用范围限定(side-effects)

4. 类型规格

  • 不变式(invariant)
  • 状态变化约束(constraint)

应用工具链情况

1. OpenJML & SMT Solver

  • 首先由OpenJML将JML规格转换乘SMT-LIB格式的代码,然后调用SMT solver进行检查。用于静态检查

2. JMLUnitNG

  • 根据规格自动生成测试文件。用于自动测试

3. JMLdoc

  • 可以快速生成JML文档的相关文件

4. Junit

  • Junit主要用于单元化测试与一定的自动化测试,配合JML食用效果极佳。

JMLUnit/JMLUnitNG

1. 前期准备

  • 简单代码示例与jar包配置
1615869-20190522120128637-1519398093.png1615869-20190522120152160-30847359.png

2. 命令行操作

java -jar jmlunitng.jar src/Demo.java 
javac -cp jmlunitng.jar src/*.java

3. 测试结果

1615869-20190522120135812-2074808793.png1615869-20190522120144850-322293277.png

4. 结果分析

  • 我们可以看出,自动生成的测试样例对各种极端情况进行了测试,具有较好的覆盖性。
  • 但是,在试验过程中,JML测试的局限性也被暴露出来了。

UNIT3 作业分析

作业 3-1 实现两个容器类Path和PathContainer

1. 架构设计

1)度量分析
1615869-20190522120201178-1202747953.png
2)结构分析
1615869-20190522120739470-1906886274.png
3)算法分析
  • MyPath

    • // path的存储结构,用来顺序存储结点
      private ArrayList<Integer> arrayNodes; 
      // 用来存储一条path中的node的个数(无重复)。key:结点名称;value:该结点出现的次数
      private HashMap<Integer, Integer> hashNodes; 
    • ADD:
      1)读入一个结点数组
      2)将结点顺序存入arrayNodes
      3)遍历结点数组,对于任一结点node,若node不在hashNodes中,即存入(node, 1);若已存在,即存入(node, value + 1)。
  • MyPathContainer

    • private int id = 0; // pathID
      private HashMap<Path, Integer> hashPaths; // Path --> PathID
      private HashMap<Integer, Path> hashIds; // PathID --> Path
      private HashMap<Integer, Integer> nodes; // Node --> frequentNumber
    • ADD:
      原理与path相同REMOVE:
      1)hashIds.remove(pathID),hashPaths.remove(path)
      2)对于path中的每一个node,(设node的出现次数为frequentNumber),若frequentNumber=1,则将node从nodes中移除;若frequentNumber>1,则 nodes.replace(node, frequentNumber-1)。

2. BUG分析

1)bug情况
  • 由于测试数据量的限制,程序在评测与互测环节没有出现错误。
2)修复情况
  • 该程序存在一些不优美的地方,如MyPath中,利用HashMap来存储不同结点是复杂的,可以说是自己造了个轮子,改正方法为使用HashSet进行存储,通过容器的特性来减少手动判断。

作业 3-2 实现容器类Path和数据结构类Graph

1. 架构设计

1)度量分析
1615869-20190522120214819-888796446.png1615869-20190522120220143-2140036106.png
2)结构分析
1615869-20190522120748711-1822232574.png
3)算法分析
  • AlGraph

    • // alGraph: node1 --> (node2 -> node2_frequentNumber)
      private HashMap<Integer, HashMap<Integer, Integer>> alGraph; 
      // edges: node1 --> (node2 -> shortestPathLength_From_Node1_To_Node2)
      private HashMap<Integer, HashMap<Integer, Integer>> edges; 
    • // 由原始图(alGraph)生成距离图(edges)的算法 ———— Floyd算法
      for (k = 0; k< MAX; k++) for (i = 0; i < MAX; i++) for (j = 0; j < MAX; j++) if (Graph[i][j] > Graph[i][k] + Graph[k][j]) Graph[i][j] = Graph[i][k] + Graph[k][j];
      
    • public boolean containsEdge(int node1, int node2) {return alGraph.get(node1).containsKey(node2);
      }
      public boolean isConnected(int node1, int node2) {if (node1 == node2) return true;else                return edges.get(node1).containsKey(node2);
      }
      public int getShortestPathLength(int node1, int node2) {if (node1 == node2) return 0;else                return edges.get(node1).get(node2);
      }
4)迭代中对架构的重构
  • AlGraph继承了上一次作业中的PathContainer,并进行了适当的扩充(具体扩充见如上算法分析)。

2. BUG分析

1)bug情况
  • 测试数据量增大时,程序出现 CPU_TIME_LIMIT_EXCEED 的错误。
  • 原因(据我分析):在Floyd算法中加入的大量的判断,当数据量增大时,造成CPU的负担过大,运算超时。
2)修复情况
  • 重构后UML图
1615869-20190522120754021-238182921.png
  • 算法分析

    • private final int biggest = 999999999; // 极大数(自由定义,小于2^31即可)
      private int id = 0; // PathID(同上一次作业)
      private HashMap<Path, Integer> pathToId; // Path --> PathID(同上一次作业)
      private HashMap<Integer, Path> idToPath; // PathID --> Path(同上一次作业)
      private HashMap<Integer, Integer> nodeToSum; // Node --> Node_Sum(同上一次作业)
      private HashMap<Integer, Integer> nodeToIndex; // Node --> Node_index_in_matrix
      private HashSet<Integer>[] adjVexSets; // 临界表:Node--Set{node1, node2, ...}
      private int[][] disMatrix; // Graph生成的存储各点之间距离的距离矩阵
      private Stack<Integer> indexStack; // 用来维护node<->index的映射的栈
    • '映射关系建立机制,搭建点与数组下标的关系
      if      put_New_Node_Into_Graph then bond_NewNode_to_IndexStack.pop() 
      else if remove_Node_From_Graph  then indexStack.push(oldNode.index)
3)前后对比
  • // 原程序,floyd部分代码
    for (int k : tempEdges.keySet()) for (int i : tempEdges.keySet()) for (int j : tempEdges.keySet()) if (tempEdges.get(i).containsKey(k) && tempEdges.get(k).containsKey(j)) { int via = tempEdges.get(i).get(k) + tempEdges.get(k).get(j);if (tempEdges.get(i).containsKey(j)) {if (tempEdges.get(i).get(j) > via) {tempEdges.get(i).replace(j, via);}} else {tempEdges.get(i).put(j, via);}}
  • // 重构后,floyd部分代码
    for (int k = 0; k < 255; k++) for (int i = 0; i < 255; i++) for (int j = 0; j < 255; j++) if (disMatrix[i][j] > (newDis = disMatrix[i][k] + disMatrix[k][j])) disMatrix[i][j] = newDis;

作业 3-3 实现容器类Path,地铁系统类RailwaySystem

1. 架构设计

1)度量分析
1615869-20190522120225784-579982037.png1615869-20190522120230939-364199165.png
2)结构分析
1615869-20190522120800108-1985593861.png
3)算法分析
  • MyRailwaySystem

    • private int cbCount = 0; // 连通块个数
      private int[][] disMatrix; // 距离矩阵 
      private int[][] transferMatrix; // 最小换乘矩阵
      private int[][] priceMatrix; // 价格矩阵
      private int[][] happyMatrix; // 最低不满意度矩阵
    • // 下面是算法的伪代码,以价格矩阵的更新为例,其它类似
      private void updatePriceMatrix() {priceMatrix = initMatrix(2);for (Each path : paths) {maxSize = path.size();priceArray = ((MyPath)path).getPriceArray();nodeMap = ((MyPath)path).getNodeMap();for (Each node1, node2 : nodeMap)if (priceArray[tempId1][tempId2] + 2 < priceMatrix[index1][index2]) priceMatrix[index1][index2] = priceMatrix[index2][index1] = priceArray[tempId2][tempId1] + 2;}floyd(priceMatrix, 125);
      }
4)迭代中对架构的重构
  • MyPath

    • MyPath添加了两个距离矩阵,用来存储一个Path(地铁线路)内部的(加权)距离信息。
    • 首先,将Path构建成两个加权无向图(权值分别为价格和满意度);然后,通过Floyd算法生成各自的距离矩阵,存储下来。

    • private int[][] priceArray; // 加权(价钱)距离矩阵
      private int[][] happyArray; // 加权(满意度)距离矩阵
      // 以下是算法的伪代码
      private void updateMatrix() {setNodeMap(); // 重新建立映射关系priceArray = initMatrix(nodeCount, 2); // 距离矩阵初始化happyArray = initMatrix(nodeCount, 32); // 距离矩阵初始化for (Each node1, node2 :nodes) { // 建图赋权priceArray[node1.index][node2.index] = priceArray[node2.index][node1.index] = 1;happyArray[node1.index][node2.index] = happyArray[node2.index][node1.index] = = CalculatePleasure();}floyd(priceArray); floyd(happyArray); // 计算各点之间距离
      }

2. BUG分析

1)bug情况
  • 这种算法在测试数据(最多结点数以及最多图变动指令数)有所约束时,展现出非常出色的性能。在强测与互测中均未出现错误。
  • 但是,我的代码结构有着较为严重的问题:几乎完全面向过程的写法严重违反了OOP的原则;多个相似结构重复计算等。
2)修复情况
  • 尚未进行代码重构,仅对课程组给出的标程进行了研究,并进行了简单的算法优化尝试。

规格撰写的心得与体会

  • 规格化设计和契约式编程,让人如沐清风,受益匪浅。 其实这次的代码工程量很大,但是由于课程组给出的JML的引导以及课程组已经将我们需要填写的代码抽象成了接口,这使得我们在写代码时会产生一种错觉——“这是面向对象课程吗?”、“这是数据结构补习课吧!”…… 这正是规格化设计和契约式编程 的巨大作用。
  • JML语言——好用不好写。 JML语言书写的困难度过高(从课程组编写JML出现的各种状况可以看出),给我的感觉是“可远观而不可亵玩”。而且,由于DDL过多加上学习资料不足(网上、课程资料都几乎为零),我缺乏自己动手写JML的动力。
  • 没有指引,路程变成了痛苦的过程。也许,是因为JML这一课还在探索阶段,课程对JML编写、检测、使用的工具的讲解和介绍颇少,基本全靠讨论区和大佬们的指点,自己摸索着完成任务。固然,可以说这是对我们自主学习能力的养成,但是,有必要吗?我相信JML单元会一步步从碎片化走向体系化,更加容易上手。
  • 在路上 ……

最后,衷心感谢为这门课程辛苦付出的老师和助教。???

转载于:https://www.cnblogs.com/FUJI-Mount/p/10905195.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/386757.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CMU Database Systems - Sorting,Aggregation,Join

Sorting 排序如果可在内存里面排&#xff0c;用经典的排序算法就ok&#xff0c;比如快排 问题在于&#xff0c;数据表中的的数据是很多的&#xff0c;没法一下都放到内存里面进行排序 所以就需要用到&#xff0c;外排&#xff0c;多路并归排序 看下最简单的&#xff0c;2路并归…

springboot线程池的使用和扩展

实战环境 windowns10&#xff1b;jdk1.8&#xff1b;springboot 1.5.9.RELEASE&#xff1b;开发工具&#xff1a;IntelliJ IDEA&#xff1b; 实战源码 本次实战的源码可以在我的GitHub下载&#xff0c;地址&#xff1a;gitgithub.com:zq2599/blog_demos.git&#xff0c;项目主…

通过Rancher安装K8s

说明 我们用kubernetes去管理Docker集群&#xff0c;即可以将Docker看成Kubernetes内部使用的低级别组件。另外&#xff0c;kubernetes不仅仅支持Docker&#xff0c;还支持Rocket&#xff0c;这是另一种容器技术。希望我这篇文章中简单的描述能让你对两者有所理解和认识。 机…

35. 搜索插入位置-LeetCode

心得&#xff1a;这个题也是二分查找&#xff0c;但是有个小技巧&#xff1a;当left>right的时候 left就是要插入的位置。 代码&#xff1a; 1 class Solution {2 public int searchInsert(int[] nums, int target) {3 if(numsnull||nums.length0)4 …

Kubectl指令集

1 Kubectl指令集 1.1 Master查询节点信息 [rootmaster1 kubernetes-1.10]# kubectl get nodes 1.2 查询所有Pod信息 [rootmaster1 ~]# kubectl get pods --namespacekube-system 1.3 查询故障的Pod信息 [rootmaster1 ~]# kubectl get pods -n kube-sys…

实验五报告

一、实验结论&#xff1a; 1. 二分查找&#xff1a;补足程序ex1_1.cpp// 练习&#xff1a;使用二分查找&#xff0c;在一组有序元素中查找数据项 // 形参是数组&#xff0c;实参是数组名 #include <stdio.h> const int N5; int binarySearch(int x[], int n, int item…

实验五 网络编程与安全-----实验报告

一、实验五 网络编程与安全-1 1.实验要求&#xff1a; 两人一组结对编程&#xff1a; &#xff08;1&#xff09;参考http://www.cnblogs.com/rocedu/p/6766748.html#SECDSA &#xff1b; &#xff08;2&#xff09;结对实现中缀表达式转后缀表达式的功能 MyBC.java&#xff1b…

Docker版本Jenkins的使用

Docker版本Jenkins的使用 低调的微胖关注赞赏支持 Docker版本Jenkins的使用 12018.05.15 18:21:50字数 1202阅读 22588 一. 什么是Jenkins Jenkins是当前非常流行的一款持续集成工具&#xff0c;可以帮助大家把更新后的代码自动部署到服务器上运行。 二. 为什么用docker版…

小程序 setData 中的坑,其实好像...

最近这段时间在写微信小程序&#xff0c;有一个页面需要动态修改 data 中的数据&#xff0c;而这里似乎是个坑。 1、正常修改 正常修改很简单&#xff0c;当触发 change 事件时&#xff0c;数据和页面都会同时发生改变。这个也不用多说&#xff0c;很简单的例子。 2、如何修改对…

CentOS HarBor安装与配置

HarBor 安装与配置 Prerequisites for the target host ResourceCapacityDescriptionCPUminimal 2 CPU4 CPU is preferredMemminimal 4GB8GB is preferredDiskminimal 40GB160GB is preferred 环境 centos7harbor v1.6.3python v2.7及以上docker v1.10及以上docker-compose …

phpstudy如何安装景安ssl证书 window下apache服务器网站https访问

1. 下载景安免费证书 https://www.zzidc.com/help/helpDetail?id555 2.文件解压上传至服务器&#xff0c;位置自己决定 3. 调整apache配置 景安原文链接&#xff1a;https://www.zzidc.com/help/helpDetail?id555 ① 确保你的apache编译了ssl模块&#xff0c;这是支持ssl证书…

docker下gitlab安装配置使用(完整版)

docker下gitlab安装配置使用(完整版) 22018.12.16 00:07:57字数 737阅读 17595 docker 安装gitlab以及使用 一、安装及配置 1.gitlab镜像拉取 # gitlab-ce为稳定版本&#xff0c;后面不填写版本则默认pull最新latest版本 $ docker pull gitlab/gitlab-ce拉取镜像 2.运行g…

企业级应用,如何实现服务化一(项目架构演化)

1.企业级应用架构演化 1.1.架构演化图 1.2.文字描述 #单一应用架构当网站流量很小时&#xff0c;只需一个应用&#xff0c;将所有功能都部署在一起&#xff0c;以减少部署节点和成本#垂直应用架构当访问量逐渐增大&#xff0c;单一应用增加机器带来的加速度越来越小&#xff0c…

readonly的用法

转载于:https://www.cnblogs.com/w123w/p/10958567.html

Jenkins发布spring boot到hub.Docker 方法

在生成的目录下&#xff0c;建立个文件&#xff0c;文件名称为&#xff1a;Dockerfile FROM java:8 VOLUME /tmp ADD target/assignment-0.0.1-SNAPSHOT.jar /dalaoyang.jar ENTRYPOINT ["java","-Djava.security.egdfile:/dev/./urandom","-jar&q…

网页视频直播、微信视频直播技术解决方案:EasyNVR与EasyDSS流媒体服务器组合之区分不同场景下的直播接入需求...

背景分析 熟悉EasyNVR产品的朋友们都知道&#xff0c;EasyNVR不仅可以独成体系&#xff0c;而且还可以跟其他系列产品相配合&#xff0c;形成各种不同类型的解决方案&#xff0c;满足各种不同应用场景的实际需求。针对很多设备现场没有固定公网IP&#xff0c;但是又想实现公网、…

如何解决VMware Workstation 10.0.0 build-1295980马赛克现象

VMware Workstation 10.0.0 build-1295980偶尔出现客户机马赛克现象&#xff0c;可切换至其它选项卡&#xff0c;再切换回去即可。 还有一种方式是关闭加速3D图形。 转载于:https://www.cnblogs.com/rms365/p/10961499.html

不同账号间的云资源授权方法

阿里云的访问控制RAM产品可以实现资源的分配和授权,在一个特殊的业务背景下,资源也可以实现跨账号的授权使用. 背景: 1.A公司,作为甲方Party A,出资购买云资源,对云资源具有所有权,但不实际管理,需要乙方配合. 2.B公司,作为乙方Party B,要管理A公司的云资源,需要A公司授权云资…

知乎上已获千赞,持续更新中

前言 不知不觉自己已经做了几年开发了&#xff0c;由记得刚出来工作的时候感觉自己能牛逼&#xff0c;现在回想起来感觉好无知。懂的越多的时候你才会发现懂的越少。 如果你的知识是一个圆&#xff0c;当你的圆越大时&#xff0c;圆外面的世界也就越大。 最近看到很多Androi…

centos下搭建Jenkins持续集成环境(安装jenkins)

centos下搭建Jenkins持续集成环境(安装jenkins) 1、安装JDK yum install -y java 2、安装jenkins 添加Jenkins库到yum库&#xff0c;Jenkins将从这里下载安装。 1 wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo 2 rpm --import h…