OO第四单元总结

OO第四单元总结

一、作业架构设计

这一单元其实架构设计也较为简单,主要是要具有“层次化”的思想。在读入UmlElement时,由于不同的元素之间有相互依赖关系,所以读入的先后顺序是有要求的。举个例子来说,就是必须要先读入UmlClassUmlInterface,才能读入UmlGerneralizationUmlInterfaceRealization,因为后两者都是依赖于前两者的,必须要有前两者才能够正确地表示后两者。同时,“层次化“思想还体现在需要将不同的元素组织在一起,整合出一个更高层次元素,操作时都是直接对这一高层次元素进行操作,使数据化零为整。

具体来说,以本单元最后一次作业为例,我的代码结构主要包括如下这些部分

  • Main:主函数,无需多言

  • MyImplementation:实现UserApi接口的函数,也无需多言

  • classdiagram(package):处理类图

    • ClassProcessor

    • MyAssociation

    • MyAssociationEnd

    • MyClass

    • MyInterface

    • MyOperation

    • TypeChecker

  • collaboration(package):处理顺序图

    • MyCollaboration

    • MyInteraction

    • MyLifeline

  • statemachine(package):处理状态图

    • MyRegion

    • MyTransition

    • StateProcessor

  • checkers(package)

    • ClassChecker

    • NullChecker

 

二、思维及方法演进

2.1 架构设计思维演进

还记得在第一单元第一次作业时,我压根没有考虑过所谓的”架构“,还是按照过往的过程式编程方式,只考虑是否能把功能正确实现。由于第一次作业较为简单,且有training的提示,所以虽然我的代码写得相当丑陋,但是还是过关了。但是在第二次作业中,由于加入了自定义函数和三角函数,第一次作业的那种无脑循环解析的方式突然失效了。我花了很长时间来考虑究竟应该如何处理三角函数这个异类。其实现在想想,无论是变量因子、幂函数、自定义函数或者求和函数,他们都可以归结为factor我们所需要做的无非就是实现接口下的各个类,并赋予类特有的运算方式就可以了。这一单元的作用让我第一次理解了组合层次递归层次抽象层次这些”层次化“的思想。

在第二单元中,由于是多线程编程,所以架构设计主要需要考虑为了实现功能需要几个线程、几个共享队列,它们之间的关系又是什么。本单元第一次作业让我卡了很久,究其原因,还是在于我对每个线程自己需要完成的工作不够明确,相互之间耦合度太高,你中有我我中有你,导致实现起来较为复杂。因此我决定在第二次作业进行重构。我意识到了生产者-消费者模型或许是一个更好的选择,它可以减少线程之间的相互依赖,同时降低代码调试时的难度。我意识导这种架构的设计其实是在最开始就需要完成的,需要带着清晰的思路才能准确地完成代码。在第三次作业新增加了换乘的要求,由于我在第二次作业重构的过程中已经考虑到了潜在的换成需求,所以我仅仅添加了一个请求分配器就解决了问题。我认为这个单元让我很好地理解了迭代开发的含义,让我意识到代码需要考虑未来潜在的需求并预先留出需求实现的空间,这样在有新的需求到来时才不会需要大规模重构代码。

个人认为第三单元不是我们去设计架构,而是需要我们去理解架构,因为本单元的JML规格都已经提前写好,我们只需要去实现即可。但是由于需要考虑性能问题,所以我们就必须要在准确理解架构的基础上进行代码优化。

第四单元的架构设计其实也不难。但是由于Uml图中元素种类非常多,所以需要考虑哪些元素需要整合在一起,元素之间又该以怎样的顺序进行读入,整合到一起的一些元素或许又可以被整合为一个更高层级的元素,这就体现出了层次性,需要一定的架构设计。

 

2.2 面向对象方法理解演进

我认为通过一个学期的学习,我主要理解了两点

  1. 为什么要引入对象

  2. 什么是层次化

首先,关于为什么要引入对象,我认为各个单元是逐步递进的。对象强调了数据的封装,对外部屏蔽了细节,使逻辑上聚合的方法和数据在物理上也聚合。第一单元刚开始其实不用考虑对象的概念也能够完成任务。但是在第二单元中,由于有了不同的线程,电梯模块和输入模块有不同的任务,所以需要将它们整合成对象,各自内部继承好相应的功能。在第三单元,对象的概念更加明显,Person、Group、Network等等对象的非常明晰,再结合上Message就能构成一个完整的社交网络。在第四单元,Uml图中的元素非常多,为了将不同的元素组合到一起方便统一管理,我们就需要自己去设计一个上层的对象。可以说,每一单元都在加深我对于对象的理解。

其次,层次化就是要我们抽丝剥茧,不能只有扁平的一层结构,而是要通过一种包含与被包含关系来组织各个元素。层次化其实是架构设计里面非常重要的一部分,一个良好的层次结构可以让代码逻辑更加清晰,也有利于减少bug的出现。最典型的例子是第一单元和第四单元。在第一单元中,有”表达式--项--因子“的层次,而在第四单元中,有”类--方法--参数“的层次(仅举其中一个例子)。在第一单元,我直到第三次作业才真正领会了层次化的精妙之处,利用层次化的方法使用递归方法就可以进行表达式化简。而在第四单元,由于有了前三个单元的铺垫,我在最开始就注意对Uml图层次的理解,设计合理的元素读入顺序,解构整个Uml图。

 

三、对测试的理解

通过四个单元的练习,我已经能够独立写出数据生成器和评测机了。在第一单元中,我使用的是非常原始的办法——手搓数据。事实证明手搓数据的覆盖度并不足够,很多时候会有所遗漏。因此在第二单元,我自己写了一个数据生成的脚本,同时使用了一位大佬写的正确性评判代码,联合形成了一个完整的评测机。在第三单元中,我独立完成了数据生成+对拍比较的评测机,算是一大里程碑式的时刻。在第四单元,由于忙于复习,我没有自己完成评测机,而是抱紧了大佬们的大腿,直接与他们进行对拍。

可以说,整个过程让我收获颇丰。首先,我深刻认识到了测试对于代码的重要性。就像王旭老师在课堂上讲的那样,测试是整个软件开发流程中非常重要的一环。如何生成足够强度、足够覆盖度的代码其实是一门学问。我在第一单元就是因为测试不足导致了一些无谓的强测失分。其次,我也对如何进行测试有了更多的实践经验。个人认为针对OO课程,最简单的办法就是“随机+构造”的模式。也就是使用脚本随机生成大量代码去轰炸程序,但是考虑到随机代码可能无法覆盖到某些边界情况,需要再针对边界情况进行相应的人工数据构造。这种方法适用于全部四个单元的作业测试。但是同时,有了数据之后如何评价结果是否正确又是另外一个问题。总结起来不外乎就是“绝对正确性” + “对拍正确性”。像第二单元多线程编程中,由于JVM调度的不确定性以及各个人代码实现的不同,采用对拍的方式比较困难。但是判定正确性的规则却是简单的:不能超载,每名乘客都要到达目的地。因此可以写出一个不依赖于其他结果的评测机,根据上述规则进行正确性判定。而像第四单元,对于同样的数据运行结果应该是唯一的,但是构造一个“绝对评测机”无异于重新再写一遍程序。因此我们可以采用对拍的方式,使用多个同学的代码运行同样的数据并比较结果。

 

四、课程收获

本博客的第二、第三点其实已经属于是个人收获,在这里就不再赘述了。我认为自己有如下一些收获:

1、面向对象编程的能力

这是很显然的,十二次代码作业极大地提升了我面向对象的编程能力,使我能较为熟练地使用JAVA语言,同时让我在阅读其他面向对象代码时能够理解它们所讲述的内容。

2、分析问题、解决问题的能力

OO课程作业一个很大的特点就是从来不会手把手教,而是需要我们自行分析指导书内容。代码需要实现的功能很简单,但是应该如何实现该功能,应该设计哪些层次,每个层次下面需要安排哪些类都是我们需要自行分析的。同时作业的迭代开发也要求我们在设计架构时必须要为未来实现更多功能留下冗余。如何将设计转变为代码实现其实也是一个难点,因为其中需要考虑数据的存储形式、算法的复杂度等等内容。所以可以说,十二次作业就是十二次对我分析问题、解决问题的锤炼。

3、心态调整能力与时间规划能力

我认为这其实很关键。因为每周都有OO作业,而每次作业都有一定的挑战,这些挑战会带来许多的压力。最开始的几周我会把OO看得很重,总是很担心自己会无法通过中测,导致一到周四周五就开始压力倍增。但是后面我意识到OO作为一个每周常客,其实更需要我做的是规划好一周的时间分配,提前预估本周作业量,然后分配相应的时间去完成,而不应该在其他时候进行进行无谓的焦虑。

 

五、课程建议

1、预习作业覆盖内容可以更全面

个人认为在预习作业中应该加入对多线程的讲解,题目并不要求难,但是应该让同学们对线程安全、设计模式等概念有所了解,这样在第二单元才能更好地上手。其次,预习作业中可以加入一些语法知识的考察(比如选择填空题),通过这种方式让同学们更快地上手java语言。

2、每单元第一次作业难度适当降低,第三次作业难度适当提高,形成更好的梯度性

经过四个单元的历练,我认为每个单元的第一次作业是最难的,因为我们才刚刚接触这一单元,对于整个单元的内容还不是很熟悉,但是第一次作业又往往需要一个良好的架构设计,否则就会涉及到后面的大规模重构,因此将会花费大量的时间。而第三次作业因为有了前两次作业的铺垫,迭代开发所花费的时间其实并不多,因此可以考虑适当增加难度?当然,为了学弟学妹们着想,难度不提升是最好的哈哈哈哈

3、增加测试相关教程

其实对于像我这种菜鸟来说,要独立完成一个评测机是很困难的,而要手搓测试又不知道从何下手,因此或许可以像计组一样出一期专门的教程,教大家如何来构造覆盖度尽可能高的测试数据。

 

写在最后

不知道为什么,我突然想起了丹尼尔·克雷格饰演的最后一部007,电影No Time To Die中的一段对话

Madeleine: "So this is it?"
Bond: "This is it."

写完这篇总结博客后,我意识到这个学期投入了海量时间的OO课在对我说

“This is it.”



posted @ 2022-06-27 22:19  乔治爱OO  阅读(26)  评论(1编辑  收藏  举报