BUAA_OO_2022_Unit_4_and_Final_Summary
一、本单元架构设计
第一次作业
-
需求简述:
实现一个简单的 UML 类图元素分析器,满足对应查询功能。
-
代码架构:
为了实现 UML 元素关系的模拟,设计了 MyInterface、MyClass、MyOperation 类作为树结构的非叶节点。其他元素因为作为叶节点,不需要在其内部储存关系链。因此,为简化代码实现,沿用官方包自带的 UmlXXXX 类。
类图树结构如下:
├─ Class │ ├─ Operation │ │ └─ Parameter │ ├─ Attribute │ ├─ child Class (Generalization) │ └─ realized Interface (InterfaceRealization) └─ Interface ├─ child Class (Generalization) ├─ child Interface (Generalization) └─ realized Interface (InterfaceRealization)
可见,上述元素共可以划分为3个层次。又因为 Element 的输入不保证顺序,所以 Element 的遍历必须做2次
- 第一次:分类别存放所有种类的元素(MyImplement 暂存)
- 第二次:按层次由高到低的顺序构建起元素之间的关系
第二次作业
-
需求简述:
实现一个简单的 UML 类图、时序图、状态图元素分析器,满足对应查询功能。
-
代码架构:
为了实现 UML 时序图元素关系的模拟,设计了 MyInteraction、MyLifeLine 类作为树结构的非叶节点。
时序图树结构如下:
└─ Interaction └─ Lifeline └─ Message
为了实现 UML 状态图元素关系的模拟,设计了 MyStateMachine、MyState、MyTransition 类作为树结构的非叶节点。
状态图树结构如下:
└─ StateMachine └─ State (==Region) └─ Transition └─ Event
第三次作业
-
需求简述:
实现一个简单的UML类图、时序图、状态图元素分析器,支持模型有效性检查(部分),并满足对应查询功能。
-
代码架构:
为了实现有效性检查的要求,对三类图的元素结构做出微调,总体树结构如下:
├─ Model │ ├─ Class │ │ ├─ Operation │ │ │ └─ Parameter │ │ ├─ Attribute │ │ ├─ child Class (Generalization) │ │ ├─ realized Interface (InterfaceRealization) │ │ └─ AssociationEnd (& Association) │ └─ Interface │ ├─ Attribute │ ├─ child Class (Generalization) │ ├─ child Interface (Generalization) │ ├─ realized Interface (InterfaceRealization) │ └─ AssociationEnd (& Association) └─ Collaboration ├─ Attribute ├─ Interaction | └─ Lifeline | └─ Message └─ StateMachine └─ State (==Region) └─ Transition └─ Event
二、课程总结
(壹)架构设计思维及OO方法理解演进
作为一个 OO 纯小白,Pre 发布之时我正在挣扎着想要看懂一份项目源代码。那份项目代码给了我一些些面向对象的朦胧感觉,于是 Pre 中结构更简单、用法更清晰的例子似乎一下让我从迷雾中觅得一幕清明,初步了解了 OO 的封装、继承、多态特性。接下来,确是照猫画虎靠模仿为生的一个阶段,积累了不少面向对象的模式方法和各自的特点。
第一单元的层次化设计实践中,我最大的收获是递归下降的思路。在这种思路下,一个表达式被解析成了表达式、项、因子层次,每一层次只需要完成该层次的任务,无需涉及由顶至底的所有环节,体现了类封装的优势。在实际的多次作业迭代过程中,这样的封装体现出了极强的可扩展性。另外,这一单元初次接触到了设计模式——采用工厂模式集成数种因子,为我后续理解 OO 提供了很好的应用范本。
第二单元的多线程设计实践中,我为了弥补第一单元OO方法不熟练导致代码不够精炼的遗憾,花了一番功夫设计架构和保证可拓展性。增加横向电梯的需求后,我果断采用抽象类继承的方法,将原一种电梯的代码复用到极致,用最小的代码量孵化了两种电梯。
第三单元的规格化实践中,架构没有什么可以发挥的空间。但在并查集算法的实现过程中,泛型的应用让我如获至宝。严格来说,泛型还是我从 C++ 课上习得的技能,能在另一门课另一种语言中获得实践练习,融会贯通,确是一大幸事。
第四单元的模型化实践虽然以具体的 UML 为大背景,但系一个综合运用设计思维的考验,又一次强调了层次解析的重要性,同时要求我们满足指导书提出的查询需求。这很像是一份甲方的项目书(x),还是很贴心很专业的甲方,能用这么技术化的语言表述需求。
(贰)测试理解与实践演进
在第一单元的研讨课中,我争取到了主题为测试策略的研讨课分享机会。很巧的是,第一单元的大起大落让我难得兴致勃勃地总结出了一套经验,将测试分为随机测试和边界测试两个阶段(详情可参看 Unit1 和 Unit3 两篇博客的测试部分)。加之分享前期褚老师的指导和点拨,让我更坚定地在接下来的几个单元里都贯彻落实自己的测试策略。
-
随机测试:覆盖绝大多数情况,验证程序功能完整
由于指导书的逻辑语言化,构造随机测试数据实际上并不需要花很多心思,只是需要细心和耐心将所有要求罗列出来,并体现在数据生成器中。这个部分的工作是一个很好的第二次加深对指导书理解的工作。
-
边界测试:保证程序在规定范围的每一个角落都能稳定运行,严格把控运行时间
这一部分的思考量显然与上一部分不可相提并论。瞪眼法构造边界数据是不现实的,因为能够“瞪眼”发现的边界一定已经在自己编程时被加以防范。因此,这个部分可以说是第三次吃透指导书。
(叁)课程收获
-
Java 程序设计
上课总是有一种很神奇的魔力,能让我快速地学会一门编程语言。寒假初期我也不是没有尝试过自学 Java,但是进度很慢,学到的东西也仅仅是皮毛中的皮毛。而经过这一个学期的训练,我已经挖掘到一些 Java 的跟其他语言不类同的特性,也可以用 Java 完成一些小型的项目了。语言++!
-
面向对象思维
第一单元对 OO 还不熟练,面向过程思维的残余还有很多。但在后续的练习中,我越来越能灵活运用面向对象的思维方法编写程序。这份收获直接影响了我在课外项目上的实践,让我在今后的编程中打开思路,不局限于面向过程。尤其是团队合作过程中,仅对外实现接口而内部设计自由,此时面向对象的思维能给自己、给同伴都减少相当一部分工作量。
-
自动化测试
上学期的《计算机组成》实验课,我由于各种原因从没有搭建过自己的测评机。到了这学期,测评机之门终于被我推开,从此发现新大陆。
除了测试策略的建立和精进,我在自动化测试的实践中还学会了增加程序运行结果的可读性。如何在成千上万次测试后快速把握测试结果、出错共同点等,在我看来和构造数据同样重要。
-
checkstyle
这是一点很有意思的收获。由于大家的测评机大多采用 Python 编写,所以我在和小伙伴们交流测评逻辑时,也不免看到他们的测评机源码。又因为 Python 的语言特性,大家的风格差异之大让我恍惚觉得这是很多种语言。相反,我们的 java 作业程序风格大同小异。我想,这应该是 checkstyle 的功劳,也理解到团队合作中代码风格的重要性。如果合作代码里是大家迥然不同的测评机,那么将会有大量的时间精力花费在本不必要的“理解同事代码”这件事情上。
(肆)课程改进建议
-
电梯单元
虽然不知道去年的原题是怎么描述的,但是从往届的博客中看,调度器的存在还是非常重要的。可今年实在是太多人采用 LOOK + 自由竞争 的策略了——在研讨课上,尤其是在讲设计特色和性能优化的时候,非自由竞争的同学甚至说不上什么话,或是说到一半自知仍有缺陷。这导致有部分非自由竞争的同学在二三次作业重构时都投向了自由竞争的怀抱。失去了调度器的设计训练,我们对多线程的理解和应用是有缺陷的——这一点在该单元的两次上机实验中有所体现。
因此,希望课程组能给这一单元作业的实现加多一些限制,使得自由竞争在某些场景不适用,让同学们能更加重视调度器的设计,也能玩出更多花样。
-
JML单元
这个单元的作业考察知识点有些扁平化,每次作业的要求基本上是在同一层次上的内容。理论课的讲解都有层层递进,但作业似乎没有。以后的作业也许可以设计一些继承、多态的规格,这样也能帮助同学们更好的理解 OOP,而不是绞尽脑汁只为优化算法防止 TLE。
-
课程平台功能
- 提交评测的页面,希望能显示当前提交的 commit 信息。时常因不确定自己交了哪一版而需要浪费一次提交机会或疯狂担惊受怕。
- 从第一单元的情况看,讨论区其实是一个很有意义很有帮助的空间。但现在的讨论区发帖制过分重视题主的初帖内容,分享意义远大于讨论意义,导致发帖门槛高、讨论空间小。建议能将讨论区设计得更加适合自由讨论,比如盖楼、评论回复等。分享帖也应该设置修改和删除功能。
- 建议统一讨论区的入口,否则从第x次作业的讨论区爬到第x+1次讨论区所需的页面点击数有些多。