BUAA-OO-2022 Unit-4 博客总结

BUAA-OO-2022 Unit-4 博客总结

第四单元架构分析

第一次作业

数据预处理

第一次作业是实现一个仅包含类图元素的UML解析器,代码框架已经给出,我们需要实现接口定义的八个方法。由于数据传入顺序随机,可能会出现子元素出现在父元素之前的情况,因此我们不能在一轮遍历中对所有数据进行整理,这样可能会RE,而要多轮遍历,每次遍历处理不同层次的元素。

具体来说,第一轮遍历处理UMLClassUMLInterface,因为这类元素的Parent ID与其他元素没有关联,可以看作是顶层元素;第二轮遍历处理UmlGeneralizationUmlInterfaceRealizationUmlOperationUmlAttribute,这是因为它们的Parent ID需要对应UMLClassUMLInterface,而我们已经对这两种元素处理完毕,可以进行索引;最后一轮处理UmlParameter,这样我们通过三轮遍历就对所有元素完成预处理操作,可以供后续查询使用。

元素存储

其实在预处理的部分还有一个问题,就是我们应当如何对元素进行预处理呢?笔者是为每一个UMLElement种类都设计了一个类,用来存储它们对应的信息,并将每一种UMLElement通过HashMap组织起来。

方法实现

这需要实现的八个方法中,其实较为困难的只有两个,涉及方法和属性的耦合度计算;其他方法只是对预处理后的元素进行简单的遍历和属性查询。

耦合度计算

该方法需要注意如果ReferenceType引用的类或接口是当前查询的对象,那么耦合度不增加,否则耦合度加1,另外可以考虑在每次通过HashMap获取元素后,可以考虑先判断获得的元素是否为null,再调用其方法,这样可以在一定程度上增加程序鲁棒性,减少后续因为自测数据违法造成的错误。

第二次作业

第二次作业增加了顺序图状态图的内容。由于方法增加,我原先在MyImplementation类实现全部方法的思想肯定是不可行了,因为这样会超出Check Style的限制,因此我们在考虑可拓展性的基础上,对代码重新组织。笔者的思路如下:为每种图实现一个类,其中存储着对应方法的实现,并设置为static,在MyImplementation类中,我们只需要调用的对应的static方法。同时,我们通过多轮遍历的方法仍然可行,但是随着每一轮要处理的元素增多,可能会导致一轮处理的代码行数继续超过Check Style的限制,并且增加不同图处理的耦合图,因此我选择牺牲部分性能,逐一对各图元素进行预处理,而对于每类图而言,我们需要进行多轮遍历。

该次作业最困难的地方在于关键节点判断,由于性能要求很低,笔者使用DFS算法,这样需要仔细对关键节点的概念进行判断:如果最开始对于起点而言,所有终点任意一个都到达不了,那么所有状态均不是关键状态;如果不满足前种条件,且我们删除某个状态后,对于起点而言,所有终点任意一个都到达不了,那么该状态是关键状态。

第三次作业

第三次作业是有效性检查,性能要求同样很低,我们更需要关注实现的正确性。在本次作业中,笔者认为最困难的地方对于R002的理解,其他的需要注意如果通过DFS来判断循环继承重复继承,中间过程存在细微差异,循环继承DFS的终止条件是判断我们遍历到的元素是否起始元素相同;重复继承DFS的终止条件是判断我们是否重复遍历了同一个元素。特别地,对于R001,我们还需要注意UMLAttributeParent ID并非只对应UMLClass

关于架构设计与面向对象

通过荣老师在课上一遍又一遍的嘱咐,笔者从第一单元起就格外重视架构的设计。笔者认为在四次单元中,对架构设计与层次化设计思想要求最高的是第一单元,这也导致笔者在第一次作业中花费了大量时间去思考。在设计的过程中,我认为核心思想是自底向上,不同层次之间通过接口联系,而一个模块不需要考虑另一个模块的内部实现,只需要关注其能够提供给自己的信息。在后面的单元中,虽然第四单元的UML解析本身就代表着一种层次化设计,但由于几乎只有输入层方法实现层底层元素,这几个层次,要求并不高。而其他单元涉及到的类较少,笔者也没有在其中体会到层次化设计思想,但是每单元作业都需要充分地对架构进行设计,特别是前两个单元,这样可以减少重构次数,笔者在一学期的OO中,几乎没有重构体验,略感遗憾。

那什么是面向对象呢,笔者通过一个学期对这个概念建立起了一定的认识,面向对象的三个特征是:封装、继承、多态。封装在上文介绍过,我认为其体现了层次化思想,不同层级之间只需要考虑接口;继承是指子类自动拥有父类的全部方法与属性,在必要的时候还可以Override;多态是指一个父类或者接口,可以代表其底下的全部元素。

就笔者而言,笔者在第一单元第一次作业中,尤其想通过面向过程的思想尽快完成作业,这是由于笔者最熟悉这种思路,并且笔者认为也不困难,但笔者没有这样做,而且通过第一周,笔者深刻认识到面向对象相较于面向过程更不容易出现程序bug,这是因为在层次化思想的指导下,每个模块的实现都变得较为简单,也更加容易通过单元测试对程序进行debug,还有就是功能拓展也更简单,只需要新增类去实现,然后在原有部分调用即可。

关于测试

测试只能证明程序可能存在bug,不能说明程序没有bug。在第一单元中,笔者了解到的是黑盒测试,通过提供输入,获取唯一可能的输出,bug必然可以复现;在第二单元中,由于多线程的缘故,bug复现难度提高,评测机原理也变得比第一单元更为复杂,这单元更多的是需要进行白盒测试,特别是这单元代码量一般,我们可以花更多时间来分析自己的代码。后两个单元主要是熟悉单元测试,通过对底层模块的测试,保证其正确性,我们降低在顶层的调试难度。

课程收获

通过OO课程,笔者最大的收获是与朋友们分享架构、讨论、对拍测试时获得的满足感,即使只有这一点,笔者也认为这一学期OO的学习是值得的。对于其他的,可能就是面向对象的入门,笔者深知在未来碰到相应应用时,肯定大部分知识也需要重新去理解,但是OO课程已经让我在一定程度上体会到了面向对象的优势所在。

改进建议

最后笔者提出三个建议:

  1. 对于第三单元,笔者认为其过于注重了对于算法的考察,而由于Java已经对很多数据结构进行了封装,比如Stack,这大大减小了我们在编写图算法时的难度,因此锻炼效果一般,同学更多出问题的地方往往是忘记优化,或者没有优化,导致最终在互测出锅。

  2. 对于第四单元,不知道是否课程组是在让同学感受奇怪的用户需求,笔者认为其过于注重对阅读理解能力的考察,而我认为其原本的目的应该是让同学了解UML,就像第三单元让同学了解JML一样,后续可以考虑对这部分指导书的完成。

  3. 笔者认为对于JMLUML的要求可以降低,比如放在一个单元,同时加强对于多线程编程的要求,我认为这在未来是一个很重要的能力,而目前通过完成作业,我们只能够学习最基本的加锁操作,对于理论课上学习到的轻量锁并没有相应的实践来进行锻炼。

posted @ 2022-06-29 10:41  yufu06  阅读(30)  评论(0编辑  收藏  举报