Loading

OO Unit4 Summary

OO Unit4 Summary

本篇文章是BUAAOO2021最后一次博客作业中的第四单元作业的总结分析部分,经由ch大佬的启发,单独开一篇文章记录这一部分,本篇文章的链接放到最终总结中。

本单元是OO的最后一个单元,作业项目是实现一个UML解析器,支持解析UML类图,顺序图以及状态图,能够查询其中一些信息,能够简单地检查几种图之间的冲突。这个项目说起来不是很难,分层次组织起来数据之后查就好了,但是在完成本单元的任务时,我却感到了前所未有的困难,并奉献了给OO的第一个完整通宵。

架构设计

从三次作业的整体来看,我是将整个项目分了三个包,这三个包中分别是类图、顺序图以及状态图的解析逻辑。

类图部分

对于类图,最开始我费了很多时间才理解了类图中的元素之间的关系(真的很久),在理清之后,我的思路大概也是每种类型的元素管理其拥有的下一层元素的列表,不过我没有显式建立树形结构,由于开始代码编写的时候已经是周六晚上了,所以我采用了快糙猛的实现方式,仅仅是利用容器不加封装地作为数据结构来描述类图中各个元素的关系:

private Map<String, UmlElement> idMap;
private MyGraph<UmlClass> sonClass;
private Map<UmlClass, UmlClass> fatherClass;
private MyGraph<UmlInterface> interfaceGraph;
private MyGraph<UmlAssociationEnd> associationGraph;
private Map<String, Set<UmlAttribute>> classAttributeMap;
private Map<String, Set<UmlOperation>> classOperationMap;
private Map<String, Set<UmlParameter>> operationParameterMap;
private Map<String, List<UmlInterface>> classInterfaceMap;

在查询的时候一般就是先根据名字找到最“顶层”的关心的元素,然后按照从属关系来回映射。这样做的缺点就是MyInteraction类负责了所有的数据的管理以及所有查询的具体实现,再多套几层轻则爆checkstyle,重则难以维护更深层次的关系。第一单元的经验告诉我,如果我最初是把数据分层次由每个类自行管理的话,那么无论是代码编写还是debug,应该都比现在这样简单的多,一天的时间应该也可以搞定,反而是快糙猛导致我最后几个小时一直在激情debug。哈哈,太心急了。

顺序图和状态图部分

在有了第一次的教训之后(其实第一次确实是不得已而为之),在第二次作业对于顺序图和状态图的解析中,我的设计是根据StarUml、课件以及第四单元指导手册中的描述去组织信息,比如一个UmlCollaboration下面管理多个UmlInteraction,一个UmlInteraction下管理lifelinemessage等元素,而它们又分别管理那些parentId为自己的更加底层的元素,整体来看,其实是建立了一个层次化的树形结构来管理数据。由于官方包中提供的类并没有我们期望的一些方法,且没有管理其下一层的数据,所以我的做法是对每个Uml*,设计一个MyUml*类,MyUml*Uml*的代理。对于每个MyUml*类,在实现相应的查询方法的时候,只要负责这一层该做的事情,剩下的交给底层元素去做就好了,这里挺有第一单元表达式求导和化简的时候的味道的,只是这里的数据比第一单元要更复杂。由于最开始脑残忘记了第一次作业的讨论区里有一个UML指导手册,故在理解顺序图和状态图上我又走了很多弯路才理清楚关系,于是第一次的部分也就再次没来及重构(又有谁愿意吃屎呐/doge)

模型有效性检查部分

在第三次作业中,需要实现一定的非法检查,为了实现这个功能,我给每种视图都设计了一个Uml***Checker类,专门用来检查合法性。在Uml***Checker类中,我提供了一系列检查合法性的方法,只要各种视图把自己相应的数据传到checker中,checker就可以进行解析,这样就只需要让原来的三种视图的顶层类持有一个Uml***Checker对象即可。由于历史遗留问题,在写类图的检查的时候还是一如既往的恶心(屎山代码遗臭万年,债早晚要还的),而在写顺序图和状态图的检查时,由于每一层只需要负责自己这一层的检查,所以实现起来比较简单。但是,这次作业的难点在于很多特殊情况的处理指导书并没有说清楚,而有些特殊情况是否需要考虑,直接影响了容器的使用以及算法的选择,是可能带来局部重构的风险的,这也告诉了我一个道理:搞清楚需求非常重要,需求理解出现问题带来的危害远远大于在开发的时候因为疏忽写出的bug带来的危害。

本单元如果不去考虑UML的背景的话,感觉其在层次化设计这方面所带来的训练大概就是第一单元的数据管理的加强版(只考虑表达式层次化结构的组织而不考虑表达式的花式解析),我个人认为如果第一单元能够把递归下降去掉,只让考虑数据管理部分的话,解析UML是个很好的实践层次化设计载体。

测试

本单元由于我很久才理解好需求,所以在测试方面没下多大的工夫。

  • 第一次作业我的测试完全是交给coekjan帮忙搞的。然而我因为通宵太累,被测出了bug的时候已经睡着了,这导致我带着bug进了强测,但戏剧性地因为数据不强,所以没有被hack。本次作业的bug是重名的有问题的方法应该重复输出,但是我使用的是set,所以会自动去重。
  • 在第二次作业中,我终于比上一次更快地理解了需求,有功夫去研究官方包将mdj文件导出测试用例,然后做一些比较细节的边界情况的测试,找到了一定的bug,然后在和同学多人运动的时候,又找到了几处和重复情况的处理有关的bug,最终在强测中再次侥幸没有被hack。
  • 在第三次作业中,我自行构造了很多测试用例,找到了相当多除了理解错题意之外的bug,这些bug的出现多半是因为第一次作业的反OO的设计和实现方式导致的。如果能像第二次作业一样做好层次化,那么de每层的bug就会容易一点,并且写bug也不太容易了。

在本单元作业中的收获放到了Final总结博客中。

posted @ 2021-06-26 17:14  BUAA-Wander  阅读(253)  评论(0编辑  收藏  举报