oo第四单元作业总结暨课程总结

oo第四单元作业总结暨课程总结

一、本单元作业架构设计

  本单元需要构建一个UML解析器,通过对输入的UML类图/顺序图/状态图的相关信息进行解析以供查询,其中课程组已提供输入整体架构及输入解析部分,仅需补充查询指令相关实现。本单元的三次作业是彻底的增量开发,没有对先前的作业做任何改动,因此仅分析第三次作业的架构设计。

  由于本单元作业数据量较小,性能要求较低,因此并没有采取按照元素的属性和归属进行建树或建图的方法,而仅暴力存储了每一元素的相关信息并在查询时不断遍历,架构较为简单,类图如下(仅选取自己实现的类,且略去了所有方法):

 

 

  具体而言,查询相关内容时,首先需要遍历所有元素以找到相应元素,再根据其parent_id, id, (reference, source, target)等内容进行进一步遍历或查找,以找到所需查询的信息。这样的方式虽然复杂度较高,耗时较长,但若辅以相应访问标记,在本单元的数据量下其复杂度是可以接受的。此外,这样的架构使得类与类之间耦合度较低,方法复杂度也较低,较为简单。

 


二、架构设计及oo方法理解演进

  在寒假的先导课程中,我过分关注于Java的基本语法和继承、多态等基本特性,虽然能够按照作业指导书的要求分出许多类,但对其封装原因往往云里雾里,整体上仍呈现出一种面向过程的形式。

  这种类似面向过程的架构在面对第一单元第二次作业时便遇到了困难。当时我已认定第三次作业必会出现“套娃”表达式,而面向过程、一main到底的方式显然不能完成任务,因此我进行了大刀阔斧的重构。通过工厂模式识别出所有的项(幂项、三角函数项、以加法连接的项、以乘法连接的项)并统一继承自父类Item,并分别为各基础项配备相应求导方法。在实践中我慢慢发现,使用这种面向对象的架构,能够使得我在进行细节上的实现时不需要再操心整体的过程,即只要我对每个项都施以正确的求导方法,那么就可以保证结果的正确,而不需要去关心每一步到底是如何求导的。在进行性能上的优化时也是如此,我只需给每一种基础项配备相应的化简方法,做出针对当前项的化简,而不需要关心其内部项和外部项的形式,从实现上看仅需给每种项增加simplify方法并在创建新项时调用即可,从整体上看程序便会进行“自动”的化简,虽然并没有做到类似的化简,但简单的合并同类项,消除多余的加零或乘一是完全可以轻松做到的,这对于当时的我来说是非常神奇的。除此之外,面向对象程序的可拓展性也是比较好的,事后想来,如果需要增加新的函数项,则仅需进行工厂模式的增量开发和所增加项的求导与化简方式而已,不需要改动其他内容。凡此种种,不一而足。可以说,正是第一单元的理论学习与作业实现,让我真正了解到了面向对象思考方式的强大之处。

  在第二单元中接触到了多线程有关技术,学习了锁和sy关键字的有关应用。虽然在三次作业的迭代开发中并没有出现整体架构上的改动,但是在某些细节的实现上(如线程结束的判定和通知方式)改动频繁,认为自己的的写法不怎么优雅。由于本单元的电梯场景较为简单,并不是一个CPU较为繁忙的场景,因此我这种弄不清楚就全加锁的大范围锁的写法也能通过,然而,这样的写法会极大牺牲并发效率,在高并发环境下将是毁灭性的。所以我认为这一单元我做的并不好,需要在将来进行更加深入的学习。

  第三、四单元分别接触了JML规格和UML,初步体验到了团队协作开发时的交流与约定方式,通过类似的规格限制和类图/状态图/顺序图的理解,可以在一定程度上增进多人之间对共同开发程序功能和实现方式的理解,改善协作开发效率。而由于这两个单元的整体架构课程组已给出,仅需补充其查询逻辑部分,因此并没有太多整体架构设计上的体验与感受。

 


三、测试理解与实践演进

  从强测和互测结果来看,本学期我在正确性上做的还差强人意,我认为这与充分的测试有很大关联。可以说,课下我学习测试方法和进行测试的时间,要远大于相关作业迭代开发所用的时间。

  在第一单元中,由于不会自动化测试相关技术,我主要依靠手造样例进行测试,这样的测试方式极不可靠,但也无可奈何。与此同期,我接触到了pb的自动化测试程序(pbnb),在使用它对我的代码进行测试的同时,我也查看了相关源码,并查阅学习了相关内容,初步明晰自动化测试应当如何构建。

  于是乎在第二单元中,我照猫画虎构建出了自己的第一个自动化测试程序,虽然简单而朴素,但它确实能跑。然而,第二单元关注多线程程序的设计,而单线程的评测耗时过长,这一点在互测中尤为突出,经常一个测试点需要数分钟才能完成屋内所有人的测试,造成我的评测程序并没有起到很大的作用。因此后期继续使用熟练掌握多线程评测的pb的多线程版自动评测程序进行相关测试(pbnb)。

  第三单元回归了单线程,然而由于本单元需要对JML语义的正确理解,因此在评测程序如何判断正确性上有待商榷。在此背景下,我搭建了对拍器,用以生成数据和比对两个程序的标准输出,同时记录耗时。这样的测试方式较为有效,不仅帮助我发现了数个对规格理解不当的地方,也使我大致了解了极限数据下程序的运行时间。此外,该对拍器稍加改动便可应用于互测中,使得互测花费的时间大大减小。

  第四单元由于标准输入的复杂性,个人认为很难自动构造出覆盖性广的样例数据,因此放弃了对拍的想法,转而进行JUnit测试。作为单元测试的常用方法,JUnit插件丰富,方法成熟,覆盖性强,虽然初次编写测试时需花费一定时间,但使用体验和效果均较好。

 


四、课程收获

  • 学习了Java的基础语法和基础特性,对于部分容器深入探究了其底层实现原理

  • 初步了解了面向对象的思考方式和一般实现过程,增进了对抽象和封装的相关理解

  • 学习了基本的多线程实现方式

  • 学习了python和Shell的基础语法,并在此基础上构造了自己的自动化测试程序

  • 复习了部分图论算法,并使用容器更为丰富的Java进行实现

  纵观整个学期的所有课程,可以说oo带给我的收获是最大的。虽然仅四个单元共16次作业,但是它不仅大幅度提高了我的编码能力,也在思考方式上对我做出了正向的指引。在今后的学习中,我将谨记在oo课中学到的内容并加以运用,也希望以后的课程都能像oo这般友好。

 


五、一些建议

  整体而言,oo课程的设计与安排已经足够妥当,在此我将从个人角度出发,提出一些细节上的建议。

5.1 先导内容与第一单元

  在预习部分中仅涉及到了Java最基础的语法和正则表达式有关内容,在此基础上我个人感觉多项式求导作为初次接触oo的第一个单元而言难度有些偏大(特指第三次作业,其也是我认为所有作业中最难的一次),可能并不能取得很好的训练效果,因此我认为应当适当加大先导内容的难度和深度,而不仅局限于最基础的语法部分和继承、多态等基本特性。

5.2 第三单元——JML

  第三单元主要考察了对JML规格的理解与运用,辅以基本的图论算法。首先是JML相关工具链和应用环境的缺失会带来不良的使用体验(存在多次细节修改的指导书也印证了这一点),其次基本图论算法的考察似乎和第四单元存在很大程度上的重复,从难度上来看第三单元也显得有些简单得不正常,个人认为仍布置三次迭代作业没有必要,换言之,可以减少第三单元作业次数而增加一二单元迭代作业的次数。

5.3 实验与研讨

  关于实验课,个人希望能在实验结束后及时得到相应反馈,亦或是参考答案。实验课作为整个课程中内容最灵活的存在,本应是解决课程组希望我们掌握而又在日常作业中无法很好考察到的内容的大好时机,然而相应反馈机制的缺失,会在一定程度上带来些许不好的体验。

  关于研讨课,个人希望课程组能更加严格地挑选展示内容。本学期中部分同学的展示内容缺乏深度,更有甚者仿佛把“我要恰分”四个大字写在脸上(纯属个人感受,如有冒犯,敬请海涵),被迫倾听这样的展示与被迫提出相关问题无疑是令人痛苦的。

 


六、线上学习体会

  除视频可以倍速和暂停让我比较开心之外,个人感觉线上与线下学习之间并没有太大区别,毕竟课上内容并不多且仅仅作为引子,更多的内容需要自己在课下进行查阅和学习。在此,向辛勤工作的课程组全体老师及助教致以我最崇高的谢意,也衷心祝愿作为教学计划一大亮点的oo课程能够越来越好。

 


  限于水平,本篇难免有纰漏之处,欢迎各位大佬在评论区进行斧正,以上。

 

posted @ 2020-06-15 21:15  Gottfriede  阅读(141)  评论(0编辑  收藏  举报