一、作业架构分析
本单元是OO课程的最后一个单元,通过学习UML图的相关知识掌握模型化设计的思维方法,主要进行了对UML对象化语义表达方式的理解、对UML格式进行解析和语义提取相分离,了解常用的架构设计方法,并对模型图进行结构化的搜索,提取相关对象进行规则检查。
1.1、第一次作业
UML图
第一次作业只要求我们对UML类图实现一个 UmlInteraction 解析器。本次作业,包括之后的两次作业采用的数据存储结构都是一样的,采用Arraylist
1.2、第二次作业
UML图
第二次作业在第一次的基础之上增加了对顺序图、状态图的解析,总体上来说数据存储方式及代码架构基本上没有变化。因为一个java文件代码行数不能超过500行,而如果所有的解析代码都在一个MyUmlGeneralInteracttion类中则一定会超出,因此我将解析器中的数据存储部分全部放到了一个名叫graph的类中,这个类就相当于一个大的数据容器,其中还包含getClass、getElement等方法,解析器就直接调用graph的相关方法直接获得所需数据。
1.3、第三次作业
UML图
第三次作业增加了对部分UML规则的检查,数据存储方式及代码架构和第三次作业完全一致。规则检查其实并不是特别难,只不过因为要遍历图中所有的元素需要考虑用何种遍历方法,此外我觉得R002相对而言是比较复杂的,R002是在图中寻找环路,一开始想用第三单元最后一次作业使用的tarjan算法,或者对点进行dfs深度遍历,但是最后还算选择了bfs,一方面是tarjan和dfs这种递归算法不易写对,在中间出栈、标记等地方很容易出问题,另一方面是因为本次作业CPU时间上限为10s,因此如果用bfs的话是不会超时的。因此为了保证正确率我选择了bfs。
二、OO课程各个单元架构设计及OO方法理解的演进
第一单元主要训练的是我们面向对象核心概念对象和类,以及层次设计结构和面向对象编程方式,在此基础上完成对多项式的求导。我采用的架构是用Factor作为所有因子的父类,常数因子、三角因子等都继承于Factor,以此来体现面向对象的层次化(然而这是第三次作业的架构,第一第二次作业并不是这样,导致我第三次作业直接悲惨地重构),同时另外一个类来进行求导。在第一单元作业的迭代中,我完成了从一开始面向过程式编程逐渐面向对象式编程的思想转换,同时了解并在代码实现中使用了工厂模式。
第二单元是多部电梯的多线程作业,着重训练我们对多线程对象的理解。本单元作业的结构设计均是采用的一种生产者-消费者模式,输入类Input(生产者)不断向调度器Contorller(托盘)中的请求队列里投入电梯请求,而电梯Elevator(消费者)发现有请求投入调度器里后开始工作,从第二次作业有了多部电梯之后,托盘controller中对每个电梯都设有一个请求队列,受到请求之后根据电梯运行状态将该请求投入到特定电梯的等待队列中去。
第三单元通过构造一个社交网络完成对JML规格的理解,按照给定的JML规格进行对应代码的实现。代码架构方面采用Arraylist存储person和对应的acquaintance,没有什么特别的地方,主要是着重于对JML规格的理解,同时让我们复习了一下图相关的遍历和查询操作。
第四单元就是构造一个UML解析器,通过实现MyInteraction类实现对图中所有UMLElement的存储管理,本单元作业采用的数据存储结构都是一样的,均是采用Arraylist
三、OO课程各个单元测试理解与实践的演进
第一单元的时候,由于我还年幼无知,不懂得如何自己写一个自动评测姬,于是就自己手动构造数据,从一般数据再到极端数据,测试的效果还算是不错的,也自己测出来一些bug,但是并不能保证完全没有问题,还是会有情况没有考虑到,之后我嫖用了同学写的评测姬,发现了亿点点问题。从那时候起我就明白了黑箱测试的重要性。由于课程组给了正确性判定,因此如果让我现在写一个评测姬的话是完全没问题的(可惜我就是懒)
在第二单元来到了多线程,这个单元就会产生一些因为线程并行发生数据竞争,产生的不可复现的bug,不过很幸运的是我的架构并没有让我困扰于这种问题。在这个单元的测试我采用的是手动构造数据并和同学对拍来进行测试。
第三单元和JML相关,我们又接触到了OpenJML,JUnit单元测试等一众测试工具和测试数据生成工具,我也尝试着用了一下,可是效果并不好,光是安装插件就废了好大劲,而且又遇到部分JML语言无法识别的问题,因此放弃了这些对我来说比较鸡肋的工具。后来我在同学的帮助下自己写了一个数据生成器+对拍器进行黑盒测试,正确性得到了保证,但是我忽略了时间问题,导致第三单元第二次作业强测基本都是CTLE,这也让我思考了如何在评测的时候加上对CPU时间的考虑。
第四单元的内容想要构造数据生成器就很不容易了,因此我就只是在课程组给出的starUML图样例的基础之上做修改,然后用官方jar包导出,自行测试,虽然这种方法效率不高,但不得不说还是比较有效的。
四、课程收获
OO课程结束了,我也从中收获到了很多。
首先就是,我学会了Java这门语言(太真实了)以及部分python知识,这让我不再是只会C语言的小菜鸡了。在学习的过程中我越来越感受到了高级语言的优势,各种函数各种数据结构都是封装好的,直接拿来用就行了,不像c语言什么函数都要自己写,十分的麻烦。不过我也明白学校一开始让我们从C学起的良苦用心,作为一个真正意义上的程序员,我们需要理解最基础的东西,并不是简简单单会调用函数就罢了。另外Java这种面向对象编程和C这种面向过程编程两种不同的方式也能够分别开来,理解到面向对象编程的精髓。
12次作业,每次作业的代码量都在千行左右,在不断的磨练中,我写工程代码的能力得到了很大的提升,现在让我从0写一个项目也不会感到困难了。其次,在每次作业的迭代中,我也渐渐掌握了代码设计可扩展的重要性,并且能够从代码架构方面实现可扩展的代码。
编程完之后的代码测试阶段是确保代码正确性和鲁棒性的关键所在,学会测试代码也是一个程序员一个很重要的能力。代码测试需要做到全覆盖,理论上来说很难,但是我们可以用测试数量来弥补。我在同学的帮助下学会了利用python中的各种包实现一个简单的对拍器,利用对拍器和同学的代码实现一个伪黑箱测试,除此之外编写对应的边界数据达到基本全覆盖的目的。
除了java语言,像UML语言、JML语言这些我们都通过代码实践有了深入的了解,使得我们能够利用除了java以外的语言和工具来保证我们代码的规范性。
最后,整个OO课程告诉我一件事:不懂就问,问老师,问同学,问百度都行,尤其是要学会自己上网查找资料,弄懂自己的疑惑的同时拓展自己的知识面,要知道计算机领域是非常广阔的,我们所学习的内容不过是冰山一角,更多未知的需要我们通过各种手段去获取。
五、课程建议
首先,我觉得课程组需要考虑一下把实验课的内容和答案在后续能够发布在网站上,实验课的成绩我觉得没有必要公布,但是实验课的内容和答案需要及时通知大家,因为实验课有些内容还是有一定难度的,同学们做实验的时候可能没弄太懂或者没时间仔细思考,导致匆匆忙忙随便写了一个答案提交上去,如果课下不发布实验课的内容的话,这个不懂的知识点可能就被遗忘了。因此我建议课程组在每次完成实验之后把实验内容加答案公布出来,供同学们继续学习。
再有就是OO课程可以增加一些对Java基础知识的讲解,我认为咱们现阶段课程对于同学们的工程实践设计能力训练的很到位,但是对于一些java的基础知识我感觉还是介绍的少了一点,比如我在作业中用到的容器基本上就是一个Arraylist,很少使用其他容器,因此在实验课考到HashMap,Heap等容器的时候捉襟见肘,因此我希望课程组能够针对一些java知识再多进行一些介绍。
最后就是针对指导书的一些建议,在某些有争议的地方可以描述的更详细一点,尤其是最后一个单元的指导书。不同的同学有不同的理解,这导致只能通过在讨论区或者水群里不断问来解惑,有时候甚至可能因为没有及时得到结果导致设计出错。我想这可能不单单是我们这一届有这样的情况,前面几届应该也有类似的困惑,所以我希望课程组是否可以在指导书中增加一些样例或者注释来解释清楚相关问题,而且是否可以将往届关于指导书内容的提问搬运到讨论区并置顶,我想这应该能够方便解决更多人关于指导书的疑惑。
六、线上学习OO课程的体会
本学期由于疫情的影响,所有的课程都采用线上教学方式,OO课程也同样不例外。
OO理论课采用课上观看录播视频,课下讨论的教学方式,教学效果比较明显,尤其是课后的讨论,通过对课程内容针对性的讨论题可以加深对课堂内容的理解和掌握。OO每周的课后作业都很令人头秃,这个作业他不仅仅是写代码难度上很大,更重要的是完成之后的测试阶段,我们需要在课下进行充分的测试以确保自己通过强测。我觉得OO理论课的线上学习和线下学习在效果上应该都差不多,甚至觉得线上观看慕课效果更佳,如果有听不懂的地方可以重复听,就是在完成作业的过程中由于不能面对面交流,同学们互相之间的讨论可能会受到一些影响,遇到困难的时候可能不太方便通过讨论解决(我认为讨论在OO学习的过程中是非常重要的)
实验课的话没有受到太大的影响,毕竟都是按时完成代码嘛在学校在家我觉得都是一样的。但是研讨课的话我觉得课上的效果并不算是特别好,同学们的发言积极性并不是特别高,总是需要助教点人来回答问题。
总的来说,这学期的OO之旅还是非常顺利的,线上授课方式并没有影响到实际的学习效果,重要的不是授课方式,而是我们个人的学习态度和学习动力,只要我们想去学愿意花时间去学,无论如何都能够学到所有的知识。