• 2020北航OO第三单无总结


    一、概述

    任务要求:根据jml给定的规格完成代码设计。主要难点在于jml语法理解、算法优化、和JML工具链(完全不会)。

    该单元坑点很多,然而每一个坑点我都中了,(因为我在摸鱼),在bugs部分详述。

     

    二、JML基础

    简介

    JML(Java Modeling Language)是用于对Java程序进行规格化设计、行为接口规格语言(Behavior Interface Specification Language,BISL)。其用处在于开展规格化设计,使得交给实现人员的不是较为模糊的自认语言,而是逻辑严格的规格。

    类型规格

    主要分为不变式限制(invariant)状态变化约束(constraint)。不变式(invariant)是要求在所有可见状态下都必须满足的特性。状态变化约束(constraint)用来来对前序可见状态和当前可见状态的关系进行约束。

    1 例如:
    2 /*@ invariant a != null;
    3    @ constraint count == old(counter) + 1;
    4    @*/

    方法规格

    方法规格的核心内容包括三个方面:前置条件后置条件副作用约定。

    • 前置条件 : 对方法输入参数的限制,不满足则不能保证正确性。(requires)
    • 后置条件 : 对方法执行结果的限制,执行后如果满足则执行正确。(ensures)
    • 副作用约定 : 指方法在执行过程中对输入对象或 this 对象进行了修改(对其成员变量进行了赋值,或者调用其修改方法)。(assignable)

    此外还有正常行为规格(normal_behavior)和异常行为规格(expcetional_behavior)。分别用关键字normal_behavier和exception_behavior。

     1 例如:
     2 /*@ normal_behavior
     3    @ requires z >=0 && z <= 100;
     4    @ assignable 
    othing;
     5    @ ensures 
    esult == z + 1;
     6    @ also
     7    @ exceptional_behavior
     8    @ requires z < 0;
     9    @ assignable 
    othing;
    10    @ signals_only IllegalArgumentException;
    11    @*/

    工具链

    常用的JML工具主要有OpenJML(对JML进行语法检查、配合Solver进行简单的静态验证、以及运行时验证)、JMLUnitNG(自动化单元测试生成工具)和JMLUnit(对JML进行静态检查)等。

    二、JMLUnitNG测试

    这部分暂时搞不出来,环境配不出来运行不了。回头能改出来再补吧。

    (据说这个自动生成数据只会测试边界数据)。

    三、作业架构

    我是属于对着jml直接写的,没有考虑类继承关系以及类之间的架构,只用了MyPerson,MyGroup, MyNetwork几个类。主要属于自己设计的就是数据的实现和每个方法的算法设计。

    对于数据结构设计的基本原则是查找用hashmap,遍历用arraylist。

    第一次作业

    没太多可说的,由于方法没有性能要求,容器全都选用arraylist存放。在Network中查询两人是否连通选择使用bfs。

    第二次作业

    这次作业主要增加了Group类,因为测试数据量会比较大,并且加入了查询Group中Person年龄平均、方差、关系和等方法,于是我再用缓存中间变量的方式,在每一次向Goup添加人的时候修改相应中间变量(和acquintance有关的量在addRelation方法中更新)。这样减少了每次查询年龄方差、关系和等量时的重复遍历。

    并且在此次作业中,考虑到容器的应用可大体抽象为遍历查找两种,于是为每一个数据规格实现了两个容器,一个是arraylist用于成员遍历,一个是hashmap用于成员查找。

    第三次作业

    对于第二次作业而言,主要是两个方面的迭代,一个是可以从组中删人,network中一些Person关系图的查询。

    支持从组中删人,对于大部分求Group内变量的方法没有影响,比如求年龄平均,只需减去这个人的年龄即可。但是仍有方法受到影响,比如求年龄方差,很难从现有的方差和要删去的Person的年龄求得结果方差。而基于xor(异或)的求conflict的方法,更是不可能回退,于是不使用缓存中间变量,而是每次都进行遍历。

    Person关系图的新方法主要有3:求最短路,求是否强连通,求连通块数。求最短路直接使用的迪杰特斯拉;连通块数只在addPerson方法调用的时候进行更新,调用getBlockSum方法时直接返还缓存变量,更新使用并查集;强连通算法为:找到一条路径,每次删去其中一个节点,再找路径,若每次都能找到,则强连通,记录路径使用dfs。

    四、BUGS

    第一次作业

    对JML规格理解有误导致的bug:isLinked方法中自己和自己返回的是true,理解不全面。

    第二次作业

    没有好好看数据的限制,最开始全都使用arraylist进行遍历和查找,使得查找的效率很慢。并且对于Group里的getAgeVar等一系列方法,都是每次调用都重新求一次,导致强测不少点CTLE。

    第三次作业

    本以为自己测试充分,但还是大意失荆州:第二次作业几乎没有用到需要遍历某个Person对象的acquintance的情况,但第三次作业新加的算法很多都要遍历acquintance(这相当于是图的邻接关系的表示)。但acquintance只用了hashmap进行存储,每次遍历hashmap.getKey()非常的慢。后专门加入了arraylist存acquintance,CTLE修复。

    四、心得体会

    JML的重点在于契约性,是一种需求的交流,从它的语法来看,非常符合契约设计的理念:requires 描述先验条件,由调用者进行保证,即调用者的义务;ensures 描述后验条件,由开发者进行保证,这也是调用者享受的权利。这种契约性使得设计和实现可以很好的分离,同时,形式化的规格也便于进行严格的形式化验证。

    在完成作业的过程中,我意识到,对于JML不能简单的将其理解为从JML翻译代码,而是应该理解其需求后进行自己设计。在写程序前需要完全的理解规格编写者的意图,而不是机械地进行实现。

    JML的编写过程十分复杂,很容易出错,是一种为了描述需求需要花费很多精力、甚至大于开发精力的工作。虽然说我了解到了契约式编程和规划化设计的好处,但是单就JML这门语言来说,我今后是不愿意使用的。

  • 相关阅读:
    [转]在WEB下的客户端控件的开发应用
    [转]C#将文件保存到数据库中或者从数据库中读取文件
    [转]如何组织一个高效的开发团队
    [转]使用C#调用金诚信71x系列读卡器的DLL
    [转]统一建模语言UML轻松入门之综合实例
    [转]Web application 的压力测试 MS Web Application Stress Tool (was)
    [转]使用NUnit在.Net编程中进行单元测试
    国外著名人脸识别介绍文章
    js与as通信
    php访问mysql 封装
  • 原文地址:https://www.cnblogs.com/don-zhou/p/12934643.html
Copyright © 2020-2023  润新知