OO第四单元总结
OO第四单元总结
1. 本单元作业架构设计
1.1 整体架构
本单元所有的方法都在UserApi
接口中,而如果真的都在MyImplementation
类中实现所有的方法,必然会导致类的复杂度过高。因此,在设计的过程中,MyImplementation
类只会直接调用MyUmlStateMachine
等类中实现好的方法,MyImplementation
类只负责实例化4个具体处理输入的类。
1.2 具体分工
-
MyUmlClass
主要负责类图的建模,其中需要三个辅助建模的类MyClass
,MyInterface
, 和MyOp
,分别对应类,接口,方法三个层次。(为什么只建立了这三个类呢?因为复杂的查询方法只涉及这些。其它的不涉及复杂查询,没必要实现)- 类图建模的层次: 由于输入并不保证某种特定的顺序,因此在建模时采取了分层次的处理方法。这样保证每一个元素被解析时,它的
parent
对应的东西都已经实现(如果有的话).- 第一层:解析其中的类和接口,实现建模并存储
- 第二层:解析
UML_ATTRIBUTE
和UML_OPERATION
,存储UML_ASSOCIATION
的id - 第三层:解析
UML_PARAMETER
和UML_ASSOCIATION_END
- 第四层:记录类/接口的继承和实现。
- 在check之后,查询之前自顶向下递归的进行继承与实现。由于最后一步本人递归实现继承的方法,需要保证无循环,无重复的前置条件。所以,在
MyUmlClass
类中,所有查询方法都检查当前是否更新的标记,如果未更新,就递归实现继承,如果已更新,直接正常查询即可。
- 类图建模的层次: 由于输入并不保证某种特定的顺序,因此在建模时采取了分层次的处理方法。这样保证每一个元素被解析时,它的
-
MyUmlInteraction
实现了顺序图的相关功能和建模 -
MyUmlStateMachine
实现了状态图的相关功能和建模 -
MyGraph
仅仅用来检查循环继承和重复继承。这个类中,仅仅找出类和接口,把他们作为节点;继承关系作为有向边,从而构建一张图。然后对每个节点进行dfs,判断是否出现了相应的错误。之所以独立写一个类,是因为这样可以提取关键信息,MyUmlClass
中很多建模信息是不需要的,可以使得逻辑更加清晰。
2. 架构设计思维及OO方法理解的演进
2.1 第一单元
第一单元需要对表达式进行层次化的建模,然而第一单元的层次确实循环嵌套的,着实给人不小的压力。这一单元的收获主要有一下三点:
- 学习到了递归下降解析这一处理表达式的方法
- 对于Java中常用类和容器,以及相关语法更加的熟悉
- 学习到如何实现更加容易进行扩展的架构,避免大规模重构。第一单元作业重构了一次,主要是把解析方法改成了递归下降。幸运的是之后的作业再也没大规模重构过。
2.2 第二单元
第二单元主要是学习多线程的架构设计。第二单元是我认为最难的一个单元,因为这确实是我第一次学习多线程的程序中间是如何具体实现调度的,对于线程之间的等待与唤醒花费了很多时间去理解。真正学明白wait和notify等等线程同步的语句还是在学习完OS的相关内容之后,如果现在再写一次的话肯定会避免一些循环等待之类的错误。
这一单元的收获主要就是如何互斥访问资源,如何利用共享对象实现线程之间的通信,如何避免”忙等待“,如何调试并发现”忙等待“之类的线程错误等等,可以说收获非常大。唯一的遗憾就是没弄清楚关于电梯调度的算法到底如何设计,因为自己写的时候感觉很难调度,于是就摆烂采取了自由竞争的策略。
2.3 第三单元
第三单元应该是最简的一个单元,JML规格话的语言读明白之后很难出现正确性相关的BUG,不过如果自己写JML的话还是很让人头疼的。这一单元的收获主要有三点:
- 图论相关算法的复习:并查集,最小生成树等等
- 提升程序性能的方式:我自己的总结在第三单元博客种写过,简单来讲就是:”非必要不计算,应缓存尽缓存,应更新尽更新“。在数据量较大时,和其他同学对拍测试确实性能更加优越。另一点就是尽量多用HashMap构造映射去减少查找的复杂度。
- 关于java中抛出异常的学习。
2.4 第四单元
第四单元的收获主要来自于理解UML图,但我觉得作业写起来很奇怪。最复杂的点既不在层次设计,又不在多线程交互,也不在算法优化,而是读明白指导书和讨论区。经过前三个单元的学习,第四单元在架构设计上确实没什么新的东西,感觉读懂题意之后轻车熟路的写完了。
3.测试的理解与实践的演进
测试部分主要是自己写评测机进行随机测试。
- 第一单元:第一单元自动化测试做的并不好,因为光是完成基本任务就已经消耗了大量的精力。第一单元利用正则表达式随机生成了数据,利用了
sumpy
库进行验证。然而自己并没有想出随机生成函数并进行测试的方法,而且第一单元也没有办法直接和同学对拍,因此出过2次BUG。 - 第二单元:第二单元数据生成部分写的比较成功,并且设计了自测和hack两种不同的生成逻辑。然而我本地却无法发现输出线程不安全的问题,导致互测被疯狂hack。第二单元的正确性检测难度比较大。我采取的办法是又用python实现了电梯和乘客两个类,然后用类似于有限状态机的方式去检测正确性,感觉工作量几乎double。
- 第三单元:第三单元指导书中推荐了JUnit这种测试方法。然而JUnit和普通的黑盒测试相比几乎没什么优势。理由有二:1. 第三单元读明白JML后一般都不会出现什么错误。2. 没有办法和多人对拍,没有办法互测hack。测试中,生成数据设计了几种不同的策略。分别能够高强度的针对易错指令进行hack。另外就是随机模式,可以覆盖测试函数之间可能存在的相互影响的问题。
- 第四单元:第四单元用的是别人实现好的生成UML图拼接上自己写的随机生成指令。第四单元说实话想实现自动化测试难度很大,一方面是生成数据格式麻烦,另一方面要保证数据的某些字段必须对应另一些数据的id等等。而由于没有互测,这一单元采取手动画图构造的方式应该也可以,而且中测的强度也不错。
4. 课程收获
学习到了面向对象的思维,学到了java相关的语法和设计方法。自己做分享的时候也去学习了一些java的新特性比如lambda函数,对其他课程比如cpp也有很大的帮助。具体收获上文都已经说的差不多,总之这门课学习到了很多新东西,整体质量很高,课程组也很用心。
5. 改进建议
重构第四单元。第四单元的用到的内容和方法相对于前三个单元完全没有新东西。第一单元是最基本的层次化设计,第二次作业新加了多线程,第三次作业有异常处理和规格化设计,第四单元就非常无聊折腾一个UML。课程组是对UML有什么执念吗?- 第四单元的重构,至少要用到一些前三个单元没用过的东西,比如一些之前没用过的类,实现一些新的功能。如果这样改动增大了作业难度难度的话,大不了就砍掉一次作业。
- 关于测试。自动化测试建议给出一些指导,因为单纯自己去做的话,耗时耗力,基本上最终都会是和其它人一起写评测机或者共享数据测试。第三单元提到的JUnit,如果真的希望去使用这个方法就应该讲的详细一点。
- 关于理论课。开颁奖典礼的时候好像有个同学说过”理论课好像什么都讲了,也好像什么都没讲“。我觉的可以大胆点把前半句去掉。理论课中有的内容就非常的迷惑,比如说每一单元做完了之后会有一个总结,我认为那玩意就纯浪费时间。
- 一个建议是可以加入对本单元优秀作业代码的讲解,或者直接让同学去分享。