OO第四单元 UML系列 总结回顾
写在前面
终于结束了。发自内心地说,这是大学以来我上过收获最大的课之一。
虽然在无数个为了OO熬夜秃头debug的晚上,也曾悄悄吐槽过这门课。但全部结束以后回过头来看,自己受益匪浅,能力有了很大提升。
一.本单元架构设计
第一次作业

从UML图可以很容易地看出,第一次作业的规格简直不忍直视。只有两个类,其中一个极为冗长复杂,实现了N多它不应该实现的功能。实际上,本单元第一次作业的规格设计我纠结了很久,理论上而言“一类到底”是最简单最容易实现的,但可扩展性、可读性、代码规格都极差极差。然而,第一次作业的CPU时间要求2s,而中测时极短极简单的数据就已经花费0.8s,再加上第三单元因为某些奇怪的操作导致CPU时间超时,便担心频繁调用类及其方法,会导致多余的传参操作,而某些参数是较大的hashmap或者arraylist,担心由于这些不必要的调用函数时压栈弹栈的操作导致超时(事实证明我多虑了)。便听从了大佬的建议,大量使用hashmap来完成此次作业而不是建类,只建立一个myTree类来协助管理接口实现及继承之类的关系,而并未建立MyClass类,属性方法等均直接用hashmap来解决。这个决定让我后悔万分,可扩展性极差的代码,再加上长度几乎达到500行上限,让我第三次作业不得不重构,浪费了很多很多的时间。
第二次作业

当我看到第二次作业的CPU时间变为10s后,同时了解了方法、类之间传参时的弹栈压栈操作不会对CPU时间造成太大影响,心想终于可以随心所欲地建类了,于是顺序图和状态图都单独建立了MyStateChartInteraction和MyCollaboration类及state、lifeline等类来协助管理。而MyUmlGeneralInteraction则仅仅完成解析图的工作。于是UML相对于第一次有了很大的改观,层次也更加清晰。但本次作业的UML图依旧很丑,那是因为第一次作业的架构我没做修改,主要是担心重构会带来新的bug(just lazy),为了稳妥起见就没修改第一次的作业,所以MyUmlGeneralInteraction依旧显得很复杂。
第三次作业

是的,这一次我彻底重构了。因为第一次作业的架构极为混乱,第三次修改根本无从下手,于是迫不得已重构,对于类图,单独建立MyClass类来完成,MyUmlGeneralInteraction仅仅实现图的解析工作,不再保存相应信息。于是代码风格有了很大改观。但实际上,我建类并未分的太清楚,逻辑也有很大的改观空间。目前设想可以将Interface之类独立出来单独建类处理。层次会更清楚,可扩展性也更强。
二.四个单元中架构设计及OO方法理解的演进
这四单元作业下来,我感觉有了很大进步...从刚开始啥都不懂,都现在觉得自己勉强有了一点点面向对象的思维。
第一单元作业
现在回过头去看第一单元作业的架构,真的很辣鸡...感觉第一单元的代码能运行完全是巧合,至今都惊叹,我第一单元写的东西竟然能运行。
三次作业,每次都重构,每次都是从头开始。但是,每次的思路都一致。以第三次作业为例,我针对表达式建类失败,于是按照指导书上的规格,建立了常数类、因子、多项式等等,按照种类建类,每个类下实现自己的求导等方法。但是,我的定义是递归的...表达式里含有因子,因子里含有项,项里含有表达式,而我对于递归的处理还没处理好,以至于复杂度直线上升。另外,整个架构极为混乱,判断合法、解析、求导、输出结构全在同一个类里实现。还造了一个没有任何意义的求导接口,判断合法、解析的内容有很多重复,还是放在了同一个类里。而判断合法的代码也并不集中,而是散落在各个地方。
总结来说,就是自己完全没有面向对象的思想,完全就是面向过程地在解决问题。而在面向过程时,又没有完全想清楚怎样处理这些一个个问题,导致了代码很复杂、毫无逻辑、可扩展性极差。
第二单元作业
总结了第一单元的经验,吸取了惨痛的教训,下定决心一定不要每次作业都重构。于是第一次作业就充分考虑了未来可能会做的更改,决定采用生产者-消费者模型,并总体采用LOOK算法。充分考虑架构,于是第二三次都没有做出过多修改,一直沿用了该模型。
但是架构也并不是完美的,依旧存在非常之多的问题,例如,由于输入较为简单,故并没有构造生产者模型,而是把输入部分放在Main类,这实际上使得Main类有了很复杂的职责。调度部分的算法也没有单独建类,而是全部放到了托盘(缓冲区),也遗留了一定的问题,如果问题变得更复杂,那在扩展修改时也会很麻烦。电梯运行的部分处理得也很混乱,唯一逼迫我建立多个方法来处理该问题的原因是每个方法不能超过80行...所以这一部分虽然实现了,但方法之间的逻辑还有很大的改进空间。
第三单元作业
第三单元并未独立建类,而是沿用了MyPerson、MyGroup、MyNetwork类,使用这三个类完成了全部的问题。在架构上并没有太多问题,但是细节部分的实现则很考验人。如何正确、完美地实现JML,如何提高性能,如何利用缓存机制来以空间换时间,都很考验人。我依旧存在很多问题,例如,MyPerson类里的某一些属性(比如熟人集合),明明定义为private,但get方法则直接把这一个hashmap整个return。
第四单元作业
第四单元作业是我做得最不满意,也是最后悔的。做第一次作业时已经快步入烤漆,面临几门荣誉课,想着考试优先,于是并未太纠结OO的架构,只求不出bug。明明能够将代码写得更清楚,架构更合理。
三.四个单元中测试理解与实践的演进
记得某次研讨课上,诸老师让仍采用手动编数据这种方法来测试代码的同学举手,当时心里想着我就是其中之一。四单元作业做下来,我主要de出bug的方法仍是手动编数据,以及利用python自动生成大规模的数据,发给朋友来对拍。
第一单元作业特殊情况极多,个人认为手动构造测试数据比较适合。而第二单元主要难点在于多线程的实现,代码实现以后,出现bug的概率并不算大,特殊情况也不多,因此并未做太多的测试。第三单元作业我则利用Python自动生成大规模数据,并尝试写了一个自动评测机,但效果并不是很理想。第四单元则依旧是手动画图手动测试。
四.自己的课程收获
发自内心地说,这是大学以来我上过体验最好的课之一。
虽然在无数个为了OO熬夜秃头debug的晚上,也曾悄悄吐槽过这门课。但全部结束以后回过头来看,自己有了非常大的收获,能力有了很大提升。
第一单元的作业,当时还在想明明一个求导的题,把规则弄得如此复杂、判断表达式是否合法就得花费大量时间是否有意义。但实际上,只有写过代码之后才能感受到,处理这样一个复杂、棘手的问题,比解决N个简单的问题都有意义。如何理解问题、如何规划、怎样化繁为简,都值得深思。第二单元的多线程则打开了一个新的世界。第三单元、第四单元让我了解到,代码也有规格,并非性能好、无bug的代码就没有任何问题,可扩展性、可读性、好的架构都非常重要,也初步了解了UML和JML
整个学期下来,我从一个未曾接触过java的小白,进化到基本初步掌握了java语言。基本有了一点点面向过程的思想。懂得在下手写代码之前,考虑代码的架构,设想未来可能的扩展,并充分考虑代码的可扩展性。掌握了多种测试方法,能够在上交之前发现自己代码里存在的部分问题,也能找出别人代码里一些明显的错误。也慢慢开始与他人讨论问题,参与讨论。
而最重要的,还是这种面向对象的思想,面对对象,总结特别,思考交互。这种思想不仅在专业课程的学习上对我有影响,在个人的思维、日常生活中处理问题时,都能给我助力,让我能站在一个不同的角度思考问题。这样的思想让我获益匪浅。
五.给课程提三个具体改进建议
1.改进三四单元的作业。第一单元的作业个人认为很合适,第二单元个人感觉第一次作业和第二次作业之间跨度较小,可以舍去第二次作业,仅保留第一、三两次作业,或者加入新的一次作业。第三四单元的作业,感觉或许是我没抓住重点,第三次作业的主要难点还是在图的算法上,第一次作业接触JML以后,第二三次就基本没考虑。三四单元的作业量也都不大。
2.公布实验详细情况。实验课结束后,建议公布正确答案(或者比较标准的写法),并提供实验成绩查询通道。否则不清楚自己完成的情况,也不知道正确答案,这样自己能从实验中学到的知识其实很有限。
3.优化博客方式。虽然写博客的那周是我最开心的时候,每次写博客也都能写得很嗨...但很多时候我也想把博客写好,但不知道该如何总结。“根据UML图分析自己的架构并提出改进方法”,自己很多时候都无法下手,最终贴一个图就水了过去。建议再细化博客要求,或者开一次教学,每周也可以展示优秀博客,供大家学习。
六.线上学习oo课程的体会
香,太香了。
这是仅有的几门我感觉线上学习效果并不弱于线下学习的课程。首先,这门课并不需要太多必须线下操作的事。而线上研讨课也比线下研讨具有更大的参与度,微信群、大班水群、OO网站讨论大家也很积极。线上课程可以倍速,听不懂也能回放。个人感觉OO线上学习开展得很好!

浙公网安备 33010602011771号