2019北航面向对象第四单元(UML类图)总结及期末总结

一、本单元两次作业架构设计

1.1 第一次作业的架构设计

1.1.1 UML类图

 

1.1.2 设计分析

本次作业的任务是实现一个UML类图解析器,可以通过输入各种指令来进行类图有关信息的查询。作业的程序主干逻辑和解析mdj格式文件这种最脏最累的活也由助教们帮我们完成了(辛苦!)。而我们只需要利用解析出的关键信息,并实现MyUmlInteraction这个官方接口即可。

这次作业的重点在于理清楚父类和子类之间通过继承带来的在属性、方法、关联、以及实现的接口上的规则。而根据老师在讨论区发的暖心贴,就可以确定这几个规则。我在本次作业中用了两个类:Node类和OperationState类。OperationState类表示一个方法的状态(有无参数、有无返回值),这是根据输入的UmlParameter确定的。Node类即为UML类图中的节点,包含了类和接口两种元素。其成员有类的属性、方法、关联以及子节点、父节点等。在构造方法中,根据传入的elements进行遍历,就能够建立众多的Node对象,又由于Node中包含了父节点和子节点,实质上是建立了一个继承关系的图。

在继承图的基础上,依据父类与子类在属性、方法、关联上面的联系,通过rejust()方法对图中节点的属性、方法等进行再次调整。先找到顶层的节点,然后从顶层的节点开始进行广度优先遍历并调整节点的属性、方法、关联等成员,就能够建成最终的图供指令查询所用。

 

1.2 第二次作业的架构设计

1.2.1 UML类图

 

1.2.2 设计分析

本次作业设计的类的数量,相比于上一次增加了不少。这次作业在上一次作业的基础上,增加了三部分的需求:对UML状态图的解析、对UML顺序图的解析、检查模型是否违背指定的几条UML规则。

(1)对UML状态图的解析

专门为UML状态图建立了一个类StateGraph,表示一个StateMachine。其本质也是一个有向图,其中的有向边即为UMLTransition。状态机模型中的状态数、迁移数可以在读取elements时统计直接得到。在查询一个状态的所有可到达后继状态时,从该状态出发,进行广度优先遍历,就能够得到所有的后继状态。

(2)对UML顺序图的解析

为顺序图建立了两个类:MyLifeLine和MyInteraction。前者用于管理顺序图中的UMLLifeline,包括其出消息和入消息以及相关属性信息。MyInteraction用来管理顺序图,包含了顺序图中的生命线和所有消息等信息。这部分的查询指令非常容易,在对输入数据做了限制之后,参与对象个数、交互信息个数、incoming消息直接调用相关对象的size()方法即可得到。

(3)模型有效性检查

有效性检查有三个部分:重名、循环继承和重复继承。

判断重名,只需要将类的属性和关联对端放在一起后进行判断即可。

在判断循环继承时,问题可以转化为在有向图中寻找所有的环。在对自环进行判断后,问题又可以转化为寻找有向图的强连通分量(tarjan算法),当强连通分量中的节点数超过1时,就可以将所有的节点加入Set中。

在判断重复继承时,问题便转化为在有向图中寻找一个点到达其他点是否有多条路径。当经过rule008的筛选后,该有向图是不具备环路的。因此可以采用DFS或者BFS对每个节点进行搜索,当访问另一个节点不止1次时,便可以判断重复继承。

由于在输入数据中,类只继承类,接口只继承接口,可以将类对接口的实现当做单向边加入图中,这不会对循环继承产生影响,因为从类到接口后,是不会有从接口到类的边的。而在rule009中,就可以检测出类重复实现接口的情况。

这里建立了GenerateGraph类,管理这个有向图,并且实现上述的算法。

 

二、四个单元中架构设计及OO方法理解的精进

2.1 第一单元作业

第一单元为表达式的求导。前两次作业都采用了面向过程的思维来写,第一次作业只有一个多项式类,第二次虽然加入了三角函数项,但我手算后发现每项求导后的结果都可以归为一种形式,因而还是只有一个多项式类。第三次作业是伤筋动骨的一次,因为每项的形式和组合过于复杂,已经没有了通项可求,于是我抽象出了一个表达式树的类以及相应的一些辅助类。在面对第三次作业时,前两次的代码几乎毫无扩展性可言,这也让我意识到合理的架构设计的重要性。而通过MetricsReloaded插件对类的复杂度进行分析的结果也显示各个方法的复杂度非常高。

也是从这一单元开始,我开始认识了工厂模式,直到后面认识了更多的设计模式。

2.2 第二单元作业

本单元为多线程程序的设计。三次作业在架构上并没有太大的变化,代码也有了一定的扩展性。第一次作业为傻瓜电梯,一个指令输入线程和电梯线程。由于调度方式极为简单,这里用不到调度器。而在后面两次作业中,一个是单部电梯的捎带调度,另一个是多部电梯的调度,我在原来架构的基础上,增加了调度器线程来实施调度策略,先后尝试了捎带策略和扫描算法,能够感受到通过调度器线程来修改策略是一件极为方便的事。通过这一单元的学习,我体会到降低各个类之间的耦合,将各个类的功能划分清楚所带来的便利。此外,Java多线程的入门也令我收获良多,我也通过这一次作业更加深入地理解了线程的协作、死锁、生产者-消费者模式等方面的知识。

2.3 第三单元作业

本单元为JML规格相关。JML是用于对Java程序进行规格化设计的一种语言。在本单元中,我体会了Java的契约式设计思想和JML规格的重要意义。通过JML开展规格化设计,这样交给开发人员的不是带有内在模糊性的自然语言描述,而是逻辑严密的规格,另外,也能够提高代码的可读性和可维护性。第一次作业没有太多灵活性和难度,都是根据给出的方法规格来实现相应的方法,只要注意利用平摊的思想降低时间复杂度即可。第二次作业有了自由发挥的空间,除了官方指定实现的MyGraph类以外,我建立了一个GraphManager类,用于进行图的相关维护。第三次作业中,自由发挥的空间更大了。考虑到不满意度、票价、换乘次数等可以转化为同一个问题,我在GraphManager类中增加了相应的建图和搜索方法,相比于第二次没有太多变动。每次用Dijkstra算法后的结果都通过距离矩阵和标记矩阵缓存起来。这一单元最大的收获在于对契约式设计的理解,对JML规格的理解和撰写。

2.4 第四单元作业

最后一单元是对UML相关内容的学习。UML是统一建模语言,通过对UML类图中关联、继承、实现等关系、顺序图中各参与对象的交互信息以及状态图中类的状态迁移的学习,我对类与类之间的关系有了更深入的认识。UML类图应该是设计人员和开发人员需要共同关注的核心,类是面向对象系统中最重要的构造块,而类图所表示的类、接口和相互协作的关系更是重中之重。

 

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

3.1 第一单元作业

第一单元由于刚开始接触面向对象和Java语言,因此在构造测试用例时,先测试指导书提供的简单测试用例,然后对简单测试用例进行不同的组合,从而构造更全面的测试用例。我所尝试的另一种构造方法是,根据自己的代码逻辑,构造测试用例判断代码对相应特殊情况的Wrong Format是否判出。

3.2 第二单元作业

在对电梯程序进行测试时,首先根据输入,记录各层的用户及目标楼层,在电梯线程中,每将一个用户开门送出后,记录该用户的位置。当电梯线程退出后,将所有用户的位置和目标楼层进行比对。也可以另写一个电梯状态模拟器,根据每次的输入和输出模拟电梯状态,最后判断是否所有用户都到达指定目的地。遗憾的是我由于观察了代码后,坚信自己的电梯不会出现超载,选择了测试强度较低的前者,只做了用户到达的比对,结果出电梯和进电梯的次序问题恰恰出现了超载……

3.3 第三单元作业

经历了前两个单元的经历,我开始意识到测试的重要性,bug似乎总是在我自以为最正确的地方出现。在JML规格上,我采用了两种测试。第一种基于JML相关的测试工具,如SMT Solver,遗憾的是实用性不强,只能测试一些很简单的方法。使用Junit进行测试时,对于较复杂的方法,比如求最短路径这种,人工构造样例就显得不实际了。于是我采用了第二种测试,对拍。我另写了一个Python程序与作业程序进行对拍,主要的测试在于测试连通性和最短路径长度上,而Networkx库恰好提供了相关的函数。在本单元的第三次作业中,加入缓存系统后,为了防止缓存出错,我将耗时较短的缓存版本与正确的可能性更高的非缓存版本进行对拍,也保持了结果的一致性和正确性。

3.4 第四单元作业

这一单元的测试又回到了最初。需要自己精心构造mdj文件的测试样例,而不能随机生成一堆样例。遵循的准则是:先分析自己的思路有没有遗漏、然后测试每一种情况的代码是否完成了指定的功能。为此我读了好几遍指导书,首先对于每一种违背UML规则的情况都做了考虑,然后按照类图、顺序图、状态图三种图分开进行构造测试样例。在没有构造大量c在ddl的前一晚,我还发现了直接求强连通分量会遗漏自环这一违反规则的情况。

 

四、课程收获

首先要感谢辛苦的老师和助教们,这门课程带给我的收获是巨大的。

在代码量上,平均下来每周的代码量没有一千行,也有七八百,这锻炼了我理解需求、架构设计、写代码以及debug的能力。这门课更重要的是教会了我面向对象的思想。从一开始用面向过程的思维写Java程序,到后来经过每次增量式扩展作业的磨炼,我逐渐学会了怎么用面向对象的思维来设计我的架构,努力做到各类的功能独立、降低类间的耦合和类内的复杂度,并尽力提高代码的可维护性和扩展性。面向对象意识的提高,使得我在设计之初就能够考虑到各个类的功能独立性。

通过JML规格和UML类图的学习,我也对面向对象的编程思想有了进一步的理解。这也是课程让我感到惊喜的地方。如果只是写了一个学期的代码,那么除了锻炼码代码的能力,意义是不大的。在经历了第一单元的魔鬼表达式、第二单元的多线程后,我已经对OO有了一定的体会。在这样的情况下,介绍了JML规格和其所实现的契约式设计,让我意识到规格在面向对象程序设计中的的重要性。最后一单元所介绍的统一建模语言UML,在软件需求分析中具有重要的意义。在这样的安排下,写代码并不是目的,而是一种理解面向对象思想的手段。

 

五、课程改进建议

1. 作为高工的同学没有研讨课和相应的指导,每次作业完成后的交流有限,希望可以增加研讨课这种形式来交流经验。

2. 希望在上机实验结束后,能够有对上机实验内容的讲解和指导。

3. 希望在每次理论课中,加入对上一次作业的多种架构设计的讲解。

转载于:https://www.cnblogs.com/zzhnobug/p/11067063.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值