BUAA_OO_2020_Unit4_总结

  2020年春季学期第十六周,OO第四单元即最终章落下帷幕,本单元是利用Java进行UML类图的解析,完成对类图、顺序图、状态图的内部查询操作与简单的规则判断操作,下做总结:

一、三次作业架构设计

  从总体上看,本单元的作业我更注重结构上的条理性,在每次作业之前会花一部分时间分析架构设计,在“高内聚,低耦合”的原则下尽力做到每个类作用清晰且不拖沓,总体而言体验较好,效果甚佳。

  1、第一次作业

  第一次作业是对类图的解析,在第一次拿官方包的时候,我用了一上午的时间查看了其中的源码(虽然看的有相当一部分迷迷糊糊),但最主干的model包里对应的元素还是摸清楚了。由于类图中的一些元素之间有着明显的依赖关系,所以我们不能仅仅依赖于系统给我们的基本元素来进行操作。并且由于输入的形式都是最基本的一条条JSON语句,其中需要抽丝剥茧提取最关键的内容,将StarUML所呈现出来的内容用Java代码内的关系表示出来。所以针对类图中的元素,我设计了我自己的三个类,以及一个额外的分类器。

  这个分类器的产生,是我对给定输入的一点担忧,如果一条一条指令的来顺序读取构建的是否,是否会存在一些诸如目标类还没有出现,但类中的其他操作已经出现这种问题。所以我首先将输入的元素进行分类,提取出最基础的框架,如类、接口先进行处理,再读取属性,操作,关联等操作,再基础之上进一步构建,再读取参数,建立在操作之上;最终再将操作回溯给类。

  而对于新设计的三个类MyUmlClass,MyUmlInterface,MyUmlOperation,每种类属性如下。

public class MyUmlClass {
private UmlClass selfClass;
private String selfClassId;
private MyUmlClass superClass; //null or only one (Java)
private ArrayList<MyUmlInterface> interfaces; //implements
private ArrayList<UmlAttribute> attributes; //own
private ArrayList<MyUmlOperation> operations; //own
private HashMap<String, MyUmlClass> associations; //associated class
private int associationNum; //associated sum(class & interface)

MyUmlClass属性

public class MyUmlInterface {
private UmlInterface selfIntf;
private String selfIntfID;
private HashMap<String, MyUmlInterface> superIntfs; //interface extends interfaces
……

MyUmlInterface属性

public class MyUmlOperation {
private UmlOperation selfOp;
private String selfOpID;
private boolean hasParam;
private boolean hasReturn;
……

MyUmlOperation属性

  类中包含了自身UmlClass,ClassID,自身的父类Class(由于本次数据限制符合Java8,所以可以保证类只有单继承);继承的接口类,包含的属性类,操作类ArrayList;还有一个关联类的HashMap以及存储关联数量的属性(由于可能存在类与接口的关联,在计算时需要利用这个属性递增来获取正确结果,而不能简简单单利用关联类的HashMap大小进行查询。

  接口中包含自身UmlInterface,ID,与继承的父类接口ArrayList,由于本次功能查询未包含关于Interface的,所以不需要其他设计。操作中包含自身UmlOperation,ID,与是否含参,是否有返回值的boolean型变量。

  在Interaction中,实例化一个类图graph,传入一个分类器,由分类器中分类的指令进行graph内新建三个类的ArrayList的构建。构建顺序如下。

public MyUmlGraph(MyUmlClassification c) {      //remember to add proper op at last!
classf = c;
for (UmlClass umlClass: classf.getClasses()) {
classes.add(new MyUmlClass(umlClass));
}
for (UmlInterface umlInterface: classf.getInterfaces()) {
interfaces.add(new MyUmlInterface(umlInterface));
}
for (UmlOperation umlOperation: classf.getOperations()) {
operations.add(new MyUmlOperation(umlOperation));
}
addParams(classf.getParameters()); //change operations
addOps(); //add operations to classes
addAttrs(classf.getAttributes()); //add attributes to classes
addAssEnds(classf.getAssociationEnds());//add associationend to classes
addGenes(classf.getGeneralizations()); //add generalizations to classes/intfs
addIntfrs(classf.getInterfaceRealizations());//add intfrs to classes
//addgenes should locate before addintfrs
//addparams should locate before addops, others have random order
}

  之后的查询操作便是对这个构建好的图进行一些简单的查询操作了,涉及到了BFS算法,其中对于访问过的点需要进行标记;由于考虑失当,Java8允许接口重复继承,所以在强测数据点中出现了一个菱形继承的接口关系,导致没有对访问过的点进行标记会使复杂度直接炸掉,在吸取这个教训之后,以后遇到BFS都需要标记,用空间换时间。

  UML图如下

  2、第二次作业

  第二次作业新增了状态图与顺序图的查询,由于类图的逻辑与上次相同,并且三种图没有存在耦合的行为,所以这次作业架构我采用了三种图分三个包的形式,其中状态图重新设计了UmlState,以及StateMachine;顺序图重新设计了LifeLine与Interaction,架构设计UML类图如下

  3、第三次作业

  第三次作业引入了三种图相关UMLRule的检查操作,由于GeneralInteraction内部执行方法过于冗余的考量,以及本次引入的规则检查操作。所以在本次作业中我新增了查询器和检查器两个类:查询器内部将前两次作业的查询逻辑进行移植,通过传入参数的形式获取数据;检查器通过构造器直接将构造好的三种图传进去,再进行8中规则的检查,总体的UML图如下:

  对于本次Rule的查询,有许多小的细节需要注意:Rule001中的name为null时要跳过处理;Rule002循环继承的查询方式;Rule005查询类图中元素是否有名字每种元素需要考虑等等。在细节处理上需要尤其注意,由于三次作业数据限制都不是很为难大家,所以在算法选择上可以自由度更高一些,不用刻意追求性能。比如002的接口的循环继承,为了避免dfs出错,我采用了循环遍历每个点,每个点用bfs,只要出现了这个重复点就加入。这种方法实测也比CPU时间限制少了许多。

  三次作业架构的逐步完善让本单元的迭代作业体验甚佳,迭代更新的过程是第一次的良好基础奠定下来的,也算为一个学期的OO训练交上一次较为满意的答卷。

二、四个单元OO架构设计与理解方法演进

  “面向对象核心概念和层次设计结构,对象的运行时行为状态与并发控制,规格化的面向对象设计,模型化设计与模型管理”是四个单元的内容概括。OO课程结束之后回顾第一次课程上的课程介绍,体会课程介绍之中对于我们数据结构设计与应用能力,基于约束的需求分析能力,基于需求的规格化设计能力,线程安全设计能力,关注性能的实现与测试能力,模型化设计与数据管理能力,算法与工程优化能力,微型团队协同能力。

  数据结构设计与应用能力体现在每一单元作业ArrayList,HashMap,HashSet,LinkedList等等形形色色,各有特点各有千秋的Java内置数据结构之中。

  基于约束的需求分析能力体现在每一单元作业根据指导书进行分析,分析未来可能出现的迭代场景与应对方式。

  基于需求的规格化设计能力体现在第三单元作业JML语言的理解之中,体会契约式编程的不同特点。

  线程安全设计能力体现在第二单元之中,每一次电梯的设计,电梯与调度器之间的同步与互斥,线程不安全导致的致命后果。

  关注性能的实现与测试能力体现在一二单元之中,多项式求导的化简,电梯调度的最佳性能,都是在对算法的不同评估,测试,以及不断的结合,改进之中一点点的积累与收获。

  模型化设计与数据管理能力体现在第四单元之中,利用UML模型进行项目的层层建模,层层解析,从而减少编程难度,使项目层次更为清晰。

  算法与工程优化能力体现在每一次作业的算法设计与应用之中,堆优化的Dijstra,DFS,BFS等等经典的算法在OO课上得以学习与巩固,为算法课打下一定基础

  微型团队协同能力体现在每次作业的讨论之中,体现在每一次对拍测试之中,也体现在构造测试用例的分享之中;微型团队可以初步锻炼沟通协作能力,也是为软件工程的团队协同打下基础。

  这些方法概括了这门课的收获,也见证了一路走来的成长。

  关于前三单元作业的架构设计与分析,请回顾我前三次的总结博客:)第一次博客第二次博客第三次博客

三、四个单元测试理解与实践的演进

  得益于OO课程测试设置的中测+强测+互测的模式,程序的正确性、鲁棒性等各方面性能都要得到保证。简单的构造一两个测试用例或者仅仅依赖于指导书给出的样例是远远不够的。如何在有限时间的测试中尽可能的覆盖所有的测试情况是OO课程为我们设置的思考题。有关测试用例的设置也在讨论课之中被提及。在此对OO课程中我使用过的测试方法进行总结。

  1、构造简单的测试用例(样例)进行测试

  适用于在程序初步实现时,用于检测是否能实现最基本的功能,从而保证程序外部框架的正确性,也避免了关注细节问题产生的本末倒置的弊端,缺点是覆盖性差,无法获取程序更加细节问题的处理情况。

  2、构造复杂情况的测试用例进行测试

  适用于在程序初步检查没有问题时,对程序可能没有实现的细节问题(或者你认为实现了,但实现出现错误)进行检查,这种检查可以从单个复杂情况开始,逐步过渡到多个复杂情况的组合;这样递进的过程可以使程序避免出现多处漏洞需要修复从而提高修复难度,样例的回归测试需要在修复之后进行,以保证不引入新的问题。  

  3、构造异常情况的测试用例进行测试

  适用于任何情况下的测试,对于程序需要满足的异常情况处理,我们需要逐一进行排查(由于异常情况处理虽多但是分类较为清晰),构造时注意是否全覆盖。

  4、构造随机的测试用例进行测试

  适用于前面的测试已经通过的情况之下。对程序进行伪覆盖性测试,这里的伪覆盖性体现在构造随机测试用例的实现方法。在OO作业之中的一二单元我使用了随机生成的测试用例对作业进行测试,用例生成,数据输入,读取输出采用Python语言,输出解析采用Java语言。体验了构造随机测试数据(评测机)的整体流程与魅力。

  5、与同学的代码进行对拍进行测试

  在经过一定的自我测试之后,程序经过与同学代码进行对拍测试可能会发现程序没被侦测的bug。

  6、压力测试

  这个环节是我前面测试欠缺的,由于强测数据有梯度,如果不进行压力测试,可能会导致强测数据出现TLE行为,虽然正确性可以保证,但是超时会使程序提前结束导致程序运行错误,所以压力测试可以保证自己程序能够在数据限制的上限时仍能保证程序正常运行。

  测试工具除了Python等自动测试之外,在第三、四单元我们也使用了JUnit,JUnitNG,OpenJML等工具进行了测试,对于这些工具的介绍详见第三次博客作业

四、课程收获

  课程本身收获的知识,在之前的能力以及测试总结之中已提及,除此之外,Java语言的掌握,git仓库的使用,博客园的初体验等等,都是OO课程的馈赠。然而我认为OO课程赠与我们最珍贵的,应该是程序编写过程时的一些体验。

  这种体验包含满心期待自己的程序获得强测高分然而却因一些小失误炸了强测没有进入互测的那种懊恼,包含每一次互测既希望发现别人程序的bug,又不太想因为发现别人程序bug让别人扣分的那种纠结的心绪,包含遇到问题时向讨论区求助向微信群求助向同学向助教求助的期待感,包含bug修复如何绞尽脑汁让自己的修复尽可能扣更少的分,包含实验课最后无法提交的心急如焚……

  课程的结果本身只是一个数字,随着时间的推移会慢慢褪色;然而这些难忘的点滴会成为你大二下最光辉的记忆,因为你在每一个瞬间似乎都在成长,而成长的历程,才是人生最宝贵的财富。

五、课程改进建议

  • 通过上面的分析,可能OO的单元顺序安排可以进行优化,个人建议:三、四、一、二,(前面没有互测,后面加互测不是更爽么)
  • 每次实验课不知道自己有多惨,不知道以后的实验成绩可不可以公布出来
  • 课程的设计往往是自学了相关内容之后,完成了本次作业,在下周的课程之中会学习(不知道这是不是有意为之,要是可以将需要学习内容提到本周课进行讲解是否会更好)

六、线上学习OO体会

  线上OO的学习感受应该是这学期所有课程里面体验最佳的一门了,依托于网站进行评测,实验,较OS的艰难实验环境相比,IDEA的友好编辑器环境与调试环境时常引起我的舒适(讲了OS的坏话)。线上录播课程的保留也可以帮助我们在相关知识忘记之时及时回顾。每周的研讨课呈现形式也更为轻松,对于主讲者不用面对全班同学,在主讲时可以降低自己的紧张情绪,更好的呈现自己的内容。总体而言,OO课程设计全面,对于能力的培养细致到位,对同学的体验保留也很好,难度设置也较为合理,要是分高一点就好了,是一门能学到东西的好课。

  最后感谢老师团队的一学期指导,感谢助教团队的一学期陪伴付出,感谢大佬们对我的帮助,也感谢自己这一学期的学习,Just go on fighting!

BUAA_OO_2020_Unit4_总结博客的更多相关文章

  1. Android请求网络共通类——Hi_博客 Android App 开发笔记

    今天 ,来分享一下 ,一个博客App的开发过程,以前也没开发过这种类型App 的经验,求大神们轻点喷. 首先我们要创建一个Andriod 项目 因为要从网络请求数据所以我们先来一个请求网络的共通类. ...

  2. 一步步开发自己的博客 .NET版(11、Web.config文件的读取和修改)

    Web.config的读取 对于Web.config的读取大家都很属性了.平时我们用得比较多的就是appSettings节点下配置.如: 我们对应的代码是: = ConfigurationManage ...

  3. 一步步开发自己的博客 .NET版(10、前端对话框和消息框的实现)

    关于前端对话框.消息框的优秀插件多不胜数.造轮子是为了更好的使用轮子,并不是说自己造的轮子肯定好.所以,这个博客系统基本上都是自己实现的,包括日志记录.响应式布局.评论功能等等一些本可以使用插件的.好 ...

  4. 【原】Github+Hexo+NextT搭建个人博客

    摘要 GitHub 是一个开源项目的托管网站,相信很多人都听过.在上面有很多高质量的项目代码,我们也可以把自己的项目代码托管到GitHub,与朋友们共享交流.GitHub Pages 是Github为 ...

  5. 我为什么要写LeetCode的博客?

    # 增强学习成果 有一个研究成果,在学习中传授他人知识和讨论是最高效的做法,而看书则是最低效的做法(具体研究成果没找到地址).我写LeetCode博客主要目的是增强学习成果.当然,我也想出名,然而不知 ...

  6. 博客使用BOS上传图片

    1.博客平台的选定 从大学开始做个人主页算起,最开始是使用html,CSSS写简单的页面,后面大学毕业之后接触到了WordPress,就开始用WordPress搭建网站.现在还维护着一个农村网站.ht ...

  7. 在jekyll模板博客中添加网易云模块

    最近使用GitHub Pages + Jekyll 搭建了个人博客,作为一名重度音乐患者,博客里面可以不配图,但是不能不配音乐啊. 遂在博客里面引入了网易云模块,这里要感谢网易云的分享机制,对开发者非 ...

  8. iOS controller解耦探究实现——第一次写博客

    大学时曾经做过android的开发,目前的工作是iOS的开发.之前自己记录东西都是通过自己比较喜欢的笔记类的应用记录下了.直到前段时一个哥们拉着我注册了一个博客.现在终于想明白了,博客这个东西受众会稍 ...

  9. 中文 iOS/Mac 开发博客列表

    中文 iOS/Mac 开发博客列表 博客地址 RSS地址 OneV's Den http://onevcat.com/atom.xml 一只魔法师的工坊 http://blog.ibireme.com ...

随机推荐

  1. Kubernetes Ingress简单入门

    作者:Nick Ramirez 原文链接:https://thenewstack.io/kubernetes-ingress-for-beginners/ 本文转载自Rancher Labs 不知道你 ...

  2. Mac下搭建atx2环境

    Git-atx2官网地址,默认已有python3环境 1.安装rethinkdb 安装db:mac上安装很简单,执行brew install rethinkdb 启动db:nohup rethinkd ...

  3. css变量的使用

    css变量的使用 1.介绍:我们也可以在css中定义变量,和less.sass一样,通过--来定义变量 div { /* 开始定义变量 */ --color: red; /* 通过var()函数来使用 ...

  4. SD.Team颜色代码大全

    EEEEEE FFCCFF FF66FF FF00FF DDDDDD FFCCCC FF66CC FF00CC CCCCCC FFCC99 FF6699 FF0099 BBBBBB FFCC66 FF ...

  5. python winreg总结

    注册表 结构 注册表由键(key,或称“项”).子键(subkey,子项)和值项(value)构成.一个键就是树状数据结构中的一个节点,而子键就是这个节点的子节点,子键也是键.一个值项则是一个键的一条 ...

  6. 04 . Python入门之条件语句

    一. Python条件语句 Python条件语句是通过一条或多条语句执行结果(True或False)来决定执行的代码块. 可以通过下图简单了解语句的执行过程 Python程序语言指定任何非0和非空(n ...

  7. thymeleaf怎么在页面上面格式化时间

    th:value="${#dates.format(后端传递的时间,‘yyyy-MM-dd HH:mm:ss’)}"

  8. Java-接口的本质

    https://mp.weixin.qq.com/s/tEVw0j18rX2hxt-guXQJ-w 大道至简,本质往往是很朴素的. 本质: 类是主体,接口是主体之间交流沟通的规约. 位置:1. 主体站 ...

  9. 【HBase】 常用命令

    创建表 hbase(main):006:0> create 'goods_zc','type' 0 row(s) in 1.3090 seconds => Hbase::Table - g ...

  10. 多线程与RunLoop

    iOS开发中的多线程 一个iOS程序,默认开启1条线程--主线程orUI线程 主线程主要作用:         显示/刷新UI界面         处理UI事件(点击.滚动.拖拽事件等) 主线程使用注 ...