关键词:
(一)梳理JML语言的理论基础、应用工具链情况
梳理JML语言的理论基础
在JML官网上,是这样定义JML的。
Java建模语言(JML)是一种行为接口规范语言,可用于指定Java模块的行为 。它结合了Eiffel的契约方法设计 和Larch系列接口规范语言的基于模型的规范方法 ,以及细化演算一些元素 。
基础语法梳理
https://blog.csdn.net/piaopu0120/article/details/89527175
链接为我根据预习资料和第一次上课内容进行的JML语法整理,内容较多,仍放在另一个博客里。
2.应用工具链
- Open JML:OpenJML是Java程序的程序验证工具,允许检查Java Modeling Language中注释的程序的规范;
- JML SMT Solver:OpenJML的主流SMT Solver;
- JML Unit:单元测试工具;
- JMLdoc:JML规范的javadoc(jmldoc)增强版本;
- jmlc:断言检查编译器。
(二)部署JMLUnitNG/JMLUnit,针对Graph接口的实现自动生成测试用例, 并结合规格对生成的测试用例和数据进行简要分析
(三)按照作业梳理自己的架构设计,并特别分析迭代中对架构的重构
1.第九次作业
没有做太多架构上的设计,仅完成了目标函数的补充。在细节方面的小优化是用hashset进行去重保存节点;用hashmap实现id和Path的双重查找。
2.第十次作业
依然没有做架构上的设计,新的图没有选择继承之前图,导致MyGraph很冗杂。主要实现了对于每一个Path的每一个小邻边的访存;修改了add和remove,完善功能;为求最短路,进行了floyd的初始化和实现。
3.第十一次作业
第三次作业因为有四个相似的图,所以进行了架构上的优化。
虽然之前有考虑过指导书推荐的组合模式+工厂模式的架构,但当时主观觉得组合模式的树形结构不太好运用到这次的题(实际上是我建模的主体不对)。所以考虑了建造者模式。
建造者模式(Builder Pattern)
使用多个简单的对象一步一步构建成一个复杂的对象。
主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
用大白话讲就是生成一个套餐。
我生成了一个floyd套餐builder和一个dij套餐builder,这两个builder可以生成各种各样的套餐。
分析:
①把问题分成由floyd算法求解更优和dijkstra算法求解更优的两类
②把floyd和dijkstra的初始化与实现拆分成小块。
③将小块进行重新组合,实现builder。
顶层组合实现举例:
1 public Dij lessTransfer() 2 if (transDij == null) 3 transDij = new Dij(); 4 transDij.addStratege(new InitLessTransfer()); 5 transDij.addStratege(new NoneTransfer()); 6 7 return transDij; 8 9 10 public Dij lessCost() 11 if (costDij == null) 12 costDij = new Dij(); 13 costDij.addStratege(new InitLessMoney()); 14 costDij.addStratege(new Transfer2()); 15 16 return costDij; 17 18 19 public Dij lessUnplefation() 20 if (unpleDij == null) 21 unpleDij = new Dij(); 22 unpleDij.addStratege(new InitUnstatisfication()); 23 unpleDij.addStratege(new Transfer32()); 24 25 return unpleDij; 26
调用builder实例:
1 if (unpleFlag) 2 // 省略初始化代码 3 // 如果没有缓存,调用builder1 4 unpleDij = DijBuilder.getBuilder().lessUnplefation(); 5 else 6 if (alreadyUnple.contains(fromNodeId)) 7 // 省略结果返回代码 8 9 // 如果有缓存,调用builder2 10 unpleDij = DijBuilder.getBuilder().noneunpleDij(); 11 12 // 省略更新缓存代码 13 // 启动builder,得到结果 14 unpleDij.runDij(fromNodeId, unpleGraph, unpleExist, distict, 15 unpleNodeSort, buddy, pidMap, pathInformation); 16
下面是builder的具体实现:
以不满意度为例
DijBuilder
1 public class DijBuilder 2 private Dij unpleDij = null; 3 private Dij noneunpleDij = null; 4 5 private static DijBuilder builder = new DijBuilder(); 6 7 private DijBuilder() 8 9 10 public static DijBuilder getBuilder() 11 return builder; 12 13 14 public Dij lessUnplefation() 15 if (unpleDij == null) 16 unpleDij = new Dij(); 17 unpleDij.addStratege(new InitUnstatisfication()); 18 unpleDij.addStratege(new Transfer32()); 19 20 return unpleDij; 21 22 23 public Dij noneunpleDij() 24 if (noneunpleDij == null) 25 noneunpleDij = new Dij(); 26 noneunpleDij.addStratege(new NoneInit()); 27 noneunpleDij.addStratege(new Transfer32()); 28 29 return noneunpleDij; 30 31 32
Dij
public class Dij private List<Strategy> strategies = new ArrayList<>(); public void addStratege(Strategy s) strategies.add(s); public void runDij(int v0, int[][] distanceGraph, boolean[][] exist, HashSet<Integer> distict, HashMap<Integer, Integer> nodeSort, HashMap<String, Integer> buddy, HashMap<Path, Integer> pidMap, PathMap[] pathInformation) Strategy initMethod = strategies.get(0); initMethod.process(0, distanceGraph, exist, distict, nodeSort, buddy, pidMap, pathInformation); Strategy calMethod = strategies.get(1); calMethod.process(nodeSort.get(v0), distanceGraph, exist, distict, nodeSort, buddy, pidMap, pathInformation);
Strategy接口
1 public interface Strategy 2 void process(int v0, int[][] distanceGraph, boolean[][] exist, 3 HashSet<Integer> distict, 4 HashMap<Integer, Integer> nodeSort, 5 HashMap<String, Integer> buddy, 6 HashMap<Path, Integer> pidMap, PathMap[] pathInformation); 7
GenerateWay抽象类实现Strategy接口,Initial抽象类类似
1 public abstract class GenerateWay implements Strategy 2 3 public abstract void process(int v0, int[][] distanceGraph, 4 boolean[][] exist, 5 HashSet<Integer> distict, 6 HashMap<Integer, Integer> nodeSort, 7 HashMap<String, Integer> buddy, 8 HashMap<Path, Integer> pidMap, 9 PathMap[] pathInformation); 10
Transfer32类继承抽象类GenerateWay
1 public class Transfer32 extends GenerateWay 2 3 public void process(int v0, int[][] distanceGraph, boolean[][] exist, 4 HashSet<Integer> distict, 5 HashMap<Integer, Integer> nodeSort, 6 HashMap<String, Integer> buddy, 7 HashMap<Path, Integer> pidMap, 8 PathMap[] pathInformation) 9 StaticFun.dij(v0, distict.size(), 32, distanceGraph, exist); 10 11
这样的方法使得在顶层实现不同的floyd或者dij的算法非常容易,可以实现n*m种任意的组合,并且不需要改动任何的底层代码。
但在实现的过程中也会遇到一些困难:
1. 统一接口导致传参过多;
2. 没有办法在顶层进一步封装,使得顶层代码重复变多。
(四)按照作业分析代码实现的bug和修复情况
1. 第九次作业
第九次作业被检测出来了一个bug,compareTO用了一种错误的方法,当时为了少些几行所以是通过差值判断的。这直接导致了溢出时判断错误。修复的时候把它修改成了大小比较。
2. 第十次作业
在判断最短路的时候忘记了两个相同点的情况,修复的时候把这个条件加上了。
3. 第十一次作业
感谢莫策同学的数据生成器,经过很多数据的互拍让bug数减到最小。
总结
这些bug很不值得,他、它们都是很基础很容易用测试用例覆盖的问题。但这两次作业我都没怎么用心测试程序,导致了这两个bug的出现。第十一次作业我汲取了之前的教训,进行了大量的测试使得最后一次作业在强测互测都没有发现bug。以后一定谨记,在每一次测试之前优先考虑边界问题和特殊数据。
(五)阐述对规格撰写和理解上的心得体会
- 这几次作业中,在课上我们有机会写规格,课下我们主要是通过阅读规格。但是实际上,我在课下补充一个方法时,会不根据规格来撰写代码,只是会根据规格来作为debug的一层手段。我记得在第一次作业我准备按照规格来写代码的时候,发现使用的架构和数据结构与规格表述的不太适配。
- 在后期阅读规格的时候,比如像计算容器类的不同节点个数或者最少换乘数路径这样的题目,用语言来描述很简单,但是它的逻辑用规格来书写就非常困难。写规格的感觉对于我来说特别像写离散数学证明题,需要用非常完备的逻辑来完善我们所想表达的。
- 一个正确的规格有助于减少歧义,规格对于方法目的的说明非常有效,因为它是贴合数据代码的,挺像伪代码对于一个问题的说明功效。
- 规格描述了数据的变与不变,忽略了中间过程的实现,是结果指向的。
面向对象第三单元总结(代码片段)
一、JML语言理论基础1.1 JML语言理论基础JML(Java Modeling Language)是用于对Java程序进行规格化设计的一种表示语言。JML是一种行为接口规格语言,基于Larch方法构建。BISL提供了对方法和类型的规格定义手段。所谓接口即一... 查看详情
面向对象第四单元总结(代码片段)
本文为面向对象课程第三单元“UML”作业以及整个课程的总结。架构设计本单元作业的架构设计主要分为两部分:将输入的UML模型数据用Java类和对象组织起来便于查询,以及设计实现查询接口的类。UML模型UML模型的组织在三次... 查看详情
面向对象第三单元(jml)总结体会(代码片段)
一.JML语言定义Java建模语言(JML)是一种行为接口规范语言,可用于指定Java模块的行为。它结合了Eiffel的契约方法设计和Larch系列接口规范语言的基于模型的规范方法。理论基础JML是契约式语言的一种具体表现形式。契约(Contact... 查看详情
面向对象设计与构造课程总结作业(代码片段)
BUAAOO2021THEFINAL面向对象设计与构造课程总结作业四个单元中的架构设计第一单元架构设计与实现相关总结,传送门在此第二单元架构设计与实现相关总结,传送门在此第三单元架构设计与实现相关总结,传送门在此第四单元架构... 查看详情
面向对象第三单元总结
面向对象第三单元总结目录分析在本单元自测过程中如何利用JML规格来准备测试数据梳理本单元的架构设计,分析自己的图模型构建和维护策略按照作业分析代码实现出现的性能问题和修复情况对Network进行扩展,以及相应的JML... 查看详情
2020面向对象设计与构造第三单元博客总结(代码片段)
面向对象设计与构造第三单元总结一、JML规格化设计JML,全称TheJavaModelingLanguage,是用于对Java程序进行规格化描述的注释性质语言。笔者在本文总结了常见的JML语法描述。1.注释结构在注释行或注释块中,以@开头的行被认作JML注... 查看详情
面向对象第三单元总结
面向对象第三单元总结一、JMLJML理论基础Java建模语言(JML)将注释添加到Java代码中,这样我们就可以确定方法所执行的内容,而不必说明它们如何做到这一点。有了JML,我们就可以描述方法预期的功能,无需考虑实现。JML为说... 查看详情
面向对象第三单元总结(代码片段)
目录单元内容JML语法规格变量常用表达式方法规格类型规格JML工具链概述部署OpenJML部署JMLUnitNG架构分析bug分析互测心得与体会单元内容本单元的内容是实现一个社交关系模拟系统,通过各类输入指令来进行数据的增删查改等交... 查看详情
oo第三单元总结(代码片段)
...而不用考虑他内部的实现,有利于我们构架时更好的完成面向对象设计。&n 查看详情
面向对象第三单元总结(代码片段)
一、JML语言1.理论基础1.规格化设计类是一个编程单位,类规格定义了类实现者和类使用者之间的契约:类实现者信任使用者能够确保所有前置条件都能被满足,类使用者信任设计者能够有效管理相应的数据和访问安全。通过这... 查看详情
面向对象第三单元博客(jml)(代码片段)
//demo/Graph.javapackagedemo;?importjava.util.ArrayList;?publicclassDemo/*@publicnormal_behaviour@ensures\\result==lhs-rhs;*/publicstaticintcompare(inti,intj)returni-j;?publicstaticvoidmain(String[ 查看详情
2020-buaaoo-面向对象设计与构造-第三单元总结(代码片段)
Part-1JML总结Section-1理论基础TheJavaModelingLanguage(JML)isabehavioralinterfacespecificationlanguagethatcanbeusedtospecifythebehaviorofJavamodules.JML是一种正则化的描述Java模块行为的描述语言。也就是说,JML的作用是对程序各模块和架构进行描述。利用JML... 查看详情
面向对象程序设计第四单元总结(代码片段)
目录面向对象程序设计第四单元总结UML类图类接口六大关系继承关系(Generalization)实现关系(Implementation)关联关系(Association)聚合关系(Aggregation)组合关系(Composition)依赖关系(Dependence)顺序图协同参与者(participant)... 查看详情
第三单元总结(代码片段)
...JML语言的理论基础、应用工具链情况JML是一种形式化的,面向JAVA的行为接口规格语言(behavioralinterfacespecificationlanguage)JML允许在规格中混合使用Java语法成分和JML引入的语法成分.JML主要是实现了设计与实现相分离,使得设计时不会陷... 查看详情
oop第三次总结(代码片段)
OO作业第7-9次总结一、前言 第三次作业总结,面向对象编程也接近了尾声,通过一个学期的不断学习,逐渐从只会语法到现在熟练运用设计模式、类图等,面向对象部分学到了很多,也体会到了“万事万物皆对象”的特点。7-... 查看详情
当代码遇到数理逻辑——面向对象设计与构造第三章总结(代码片段)
在面向对象课程中的第三章,我尝试了基于JML语言的规格化设计,按照AppRunner中的接口文件实现了Path类和PathContainer,Graph,RailWaySystem迭代类。JML语言是一种规格化语言,完全建立于数理逻辑上,既能够为开发者实现类与方法时提... 查看详情
oo第三单元总结——java建模语言(代码片段)
一、JML语言的理论基础 面向对象分析和设计的原则之一就是应当尽可能地把过程设想往后推。我们大多数人只在实现方法之前遵守这一规则。一旦确定了类及其接口并该开始实现方法时,我们就转向了过程设想。 Java建... 查看详情
面向对象第一单元总结(代码片段)
...心得体会第一单元通过三次迭代的表达式求导任务建立对面向对象程序的初步认识,并熟悉面向对象的思维和编程方法。一、任务需求三次作业的需求如下:第一次作业:求解简单多项式导函数第二次作业:求解包含简单幂函数... 查看详情