• oo第三单元总结


    JML理论基础

    JML是用于对Java程序进行规格化设计的一种表示语言,用来约束java代码中类和方法编写的状态和行为,形成一种契约式编程。实现者根据JML的约束来编写程序,既可以使结构更加清晰,还可以帮助实现者对代码进行测试。

    注释结构

    JML以javadoc注释的方式来表示规格,有两种注释方式,行注释和块注释。行注释表示方式为//@annotation,块注释方式为/* @ annotation @*/。

    表达式

    JML表达式是对Java表达式的扩展,主要分为原子表达式、量化表达式、集合表达式、操作符几种。

    原子表达式包括 esult表达式,old表达式这些,主要表示对返回值或对象等的约束。

    量化表达式包括forall表达式,exists表达式这些,这两个表达式类似于离散数学中的任意和存在的意思。

    方法规格

    方法规格式的核心内容包含三部分,前置条件、后置条件和副作用约定。

    前置条件是对方法输入参数的限制,用requires子句来表示。后置条件是对方法执行结果的限制,用ensures子句来表示。副作用约定指方法在执行过程中对输入对象或this对象进行修改的限制,使用关键词assignable或modifiable来表示。

    根据前置条件的约束判断该进行何种操作,大致分为normal_behaviorexpcetional_behavior,不同的输入参数通过前置条件判断然后执行对应的处理操作。expcetional_behavior多用signals子句来抛出对应异常。

    类型规格

    对于课程而言,类型规格主要涉及不变式限制和约束限制。

    不变式(invariant)就是要求在所有可见状态下都必须满足的特性(就是对所有修改后的状态的约束)。状态变化约束(constraint)则是对前序可见状态和当前可见状态的关系进行约束(也就是修改后的状态相对于修改前状态的约束)。

    以上只是对JML语言的大体结构进行了描述,还有更多细节的东西就不赘述了。

    JML工具链应用

    OpenJML

    OpenJML主要用于JML的语法检查分析,通过运行java -jar openjml.jar -exec Solvers-windowsz3-4.7.1.exe -esc test*.java报错如下图。

    开始完全不知道是什么意思,通过求助同学及搜索引擎才知道原来是三目运算符的问题,将三目运算符修改一下就好了。

    JMLUnitNG

    JMLUnitNG主要基于JML对代码自动生成测试代码并测试。

    先通过java -jar jmlunitng-1_4.jar test/Group.java生成测试代码。

    再通过javac -cp jmlunitng-1_4.jar test/*.java

    java -jar openjml.jar -rac test/Group.java test/Person.java

    java -cp jmlunitng-1_4.jar test.Group_JML_Test开始测试。

    可以发现JMLUnitNG只是针对极端数据进行了测试,覆盖面不全(可以说是弱测),通过该测试很难保证程序就是正确的,所以感觉这个好像有点鸡肋,作用不大。

    架构分析

    整体架构官方接口已给出,要做的只是具体实现。MyPerson类中的容器主要选用的是ArrayList,MyNetWork则主要使用Hashmap,其余的除了少数几个需要优化的算法,基本上都是按照规格对应实现的,所以直接对某些方法使用的算法进行分析。

    第一次作业的isCircle直接使用bfs算法。

    第二次作业对于Group类中的getRelationSum、getValueSum等方法采用缓存机制(在组内新增Person时或组内两Person之间新增Relation时更新),避免超时。

    第三次作业将isCircle改为并查集方法;queryMinPath方法采用堆优化的dijkstra算法,通过容器PriorityQueue实现堆优化。queryStrongLinked则采用先bfs寻找一条路径,然后依次删除这条路径上的每一个点,再用bfs看是否能找到另一条路径,如果都能找到另一条路径就说明是点双连通分量。由于采用并查集方法,在addPerson,addRelation不断更新blockSum,queryBlockSum的复杂度变为O(1),直接返回blockSum即可。

    bug分析

    第一次作业就由于isCircle没有考虑到起点和终点是同一点的情况,导致强测炸裂。修复只需加上一句简单的判断即可。

    第二次作业由于getValueSum没有使用缓存机制导致超时,解决方案自然就是使用缓存机制。互测中也hack到别人getValueSum未使用缓存机制的超时bug,怪只怪自己强测前不充分测试有些方法是否会超时。

    第三次作业由于做好了算法优化,未出现bug,互测中也未发现bug。

    心得体会

    刚开始接触JML时其实是感觉这个用处不大,但开始自己写作业之后才发现有好的JML规格写起代码来是多么舒服。而且严格检查好每个细节,也很难出现bug。而且JML并不是我开始所认为的是一种束缚,JML只是给出了规格的约束,具体实现依然可以自由发挥,只要保证规格就可以了。

    多次作业下来,慢慢发现了JML的众多优点,每次写代码前先读一遍全部规格,就能很清晰的了解要实现的功能及代码架构等,然后再根据具体方法规格进行代码的编写,这样对于实现者而言任务量大大减少,而且JML还保证了实现者不会一时疏忽忽略了某些情况,只要按照规格来写,就能保证正确性。

    这三次作业除了对于JML有了一定程度的了解,也对算法把握进行了一定的复习,总而言之,这单元收获还是很多的。

  • 相关阅读:
    JQuery 介绍
    转载:World class Software
    how to get domain user info from AD in C#
    抽象类与接口的实际应用{百分百的重点}
    设计模式学习笔记
    百度前端笔试面试7个试题
    虚函数在C#中的用法
    设计模式学习MVC实践
    VMware 创建私有网络试验室
    设计模式学习单件模式
  • 原文地址:https://www.cnblogs.com/xianmei/p/12940093.html
Copyright © 2020-2023  润新知