BUAAOO 第四单元总结&课程总结
写在前面
oo课程终于结束了,生活也重获平静。
哦,还有bug没de,那没事了。
第四单元架构设计
三次作业的架构整体来说没有太大变化,都是一个图的初始化和解析的流程。难度最大的是对于各个element
的理解以及对谜语指导书的思考。
第13次作业
先上类图
本次作业主要完成的是UML类图的构建,总体来说就是一个较为复杂的图的初始化和解析的过程。因此,通过MyPreprocess
类对所有的element
元素进行预处理,解析各个成员的信息,并把它们分别对应着加入到自己该在的元素之下。由于class
、interface
、operation
等元素中,需要添加很多附属信息,比如类之中的元素,接口之中的方法等等,因此设计了MyUmlxxx
,这些类的作用就是一层套壳,来将所有的相关元素可以和对应的顶层元素联系到一起。当然,类似attribute
这种最底层的元素,没有附属更下一层的其它元素,也就没有必要再单独创建一个MyUmlAttribute
类了。
第14次作业
先上类图
本次作业增添了uml的顺序图和状态图的解析
虽然类图看上去有些许复杂,但稍加分析便可知,本次作业的迭代内容也就是在预处理类MyPreProcess
中增添对新添加元素的解析和预处理,并把相应元素挂到更高层元素中。由于增添了一些更高层的元素,因此也就设计了更多更高层元素的套壳,来为其添加相应的元素。
第15次作业
本次作业的架构与上一次作业没有任何区别,主要增添的check系列的代码都被我整合进了MyPreProcess
类中,因为这个类在初始化的过程中存储了整个uml图所有的元素信息。
总的来说,只要理解了各个元素之间的关系,便不难设计出来整个架构,而只要设计出架构,所要填写的方法也就水到渠成信手拈来了。
四个单元中架构设计及OO方法理解的演进
第一单元:多项式求导
架构核心:递归下降!
有多少人,曾因为轻视了第一次作业,设计了一个屎一样的架构,导致在第二次作业中完全推翻重写的
有多少人,曾不理解递归下降,而苦陷于字符串解析而难以自拔的
我,完美踩坑。
幸好有了oo课上教学的救赎,让我形成了初步的面向对象思想,而真正写出了一个有着清晰架构,有着完善的思路,且有利于迭代开发的代码之后,我也真正尝到了面向对象编程,以及设计出一个好的架构的甜头。第二次作业强测的爆炸,也让我感受到了oo课程的残酷。当我充分认识到了架构的重要性后,在之后几个单元中,也都做到了先设计架构,再动手编程。
第二单元:电梯调度
面向对象的感觉来了,但多线程编程的感觉还没来。不过多亏了实验课代码的提示,让我对于生产者消费者模型的应用有了更深刻的理解。这个架构运用在本单元的电梯中十分给力,每次迭代需要改动的地方少且清晰。
层次化设计在多线程中是必须的,毕竟要把每一个层次抽象出来,每一个线程也都分工明确。一个好的架构对于多线程而言是前提,多学几个架构也没啥坏处。但把模板架构与具体任务结合起来的时候,就要花一点心思了。
遇到最大的问题就是多线程的问题了,无外乎是死锁问题和线程安全问题,而只要合理实现生产者消费者模型,就可以很好的避免这些问题。
第三单元:JML
没有进行架构设计。都是只实现了官方包,严格按照JML规格进行实现,并没有增添新类。官方已经把架构设计的很清楚了,没有必要再解构了...
而本单元我学到的最多的是对于代码规格的理解,在面向对象编程的过程中,好的规格的设计既能在编程的时候有清晰的思路,又让代码看起来更加通俗易懂。
难点是几个算法,而我也第一次吃了代码运行速度上的亏,导致在互测过程中被大佬构造的测试点hack。我也深刻地意识到,程序的性能的的确确是与架构设计密切相关的,而对于同样的代码规格,也的的确确是有非常多的实现方式,这些实现方式不仅性能上有极大的差异,美观程度上也有很大的差距。就以并查集为例,可以说并查集是一种非常优美的数据结构,不但降低了复杂度,而且十分直观,代码量也不多,是我在这个单元的最大收获之一。
第四单元:UML
刚刚过去的第四单元,是我这几个单元里最狼狈的。没能理解题干含义,没能了解uml的解构,没能分析出所有element的作用,导致第十三次作业我熬了很久,在我心目中,这次作业的难度远高于电梯,与第二次作业有得一拼。
具体架构在上面已经提到了,而oo的思想在这个单元还是有很多应用的:将每个uml中的元素都抽象为各个类,这些类中的操作便组成了整个uml中的各种操作。其实在编程过程中,我并没有意识到我正在使用面向对象的编程思想,而在写完代码之后我才发现,整个代码的架构十分清晰,而且充满了面向对象的思维方式。从第一单元强迫自己创建类来分离各种属性,到最后一个单元不由自主地把一组元素抽象成类再进行后续操作,我想,这就是这个学期我的最大改变吧。
四个单元中测试理解与实践的演进
这个世界上没有完美的程序,想让自己的代码不出错,离不开各式各样地检查和测试。在这四个单元的测试中,我既使用了原始的肉眼看代码的方式来debug,也使用了自动生成样例的方式,也使用了对拍的方式(也有的直接放弃了debug)收获满满。
第一单元
第一单元我才用的是肉眼debug和python半自动化测试两种方式来debug。肉眼主要观察容易出错的正负号个数问题的解决方式,化简时可能出现的一些问题。python使用的sympy等库函数,进行正确性比对。由于边界样例比较难以构造,也并没有询问大佬有关自动化构造边界数据的方式,所以我的半自动化测试的效果并不理想,绝大部分的bug都是靠肉眼看出来的。
第二单元
多线程的dubug就是个玄学!
大家普遍认为这个单元的测评机很难搭,我也就放弃了测评机的搭建,只使用了最原始的肉眼观察的方式来debug。(但是效果并没有像第一单元那样明显,因为多线程的bug大多数都是线程安全问题,而很多问题甚至都是难以复现的)
事实上也是如此,在互测屋中,大家并没有像第一单元那样有很高的hack热情,都只是寥寥草草随便刀几下,绝大多数也都是空刀。
第三单元
第三单元其实只要按照规格来写就很不容易出现bug了,而听学长们说的也是这样,第三单元的问题主要是性能问题,因此我就把心思主要放在了性能hack上,我非常自以为是的用脏位来解决部分的性能问题,但奈何大佬们可以很轻松地使用加一个人查询一次的方式将我的优化破解掉,导致被刀了几次性能tle。
我们也搭建了对拍机和样例自动生成机,但奈何自动生成的样例强度不足,只能解决一些浅显的正确性问题。
我的经验就是,只要复杂度达到了O(n^2),就要考虑着改进自己的程序了!
第四单元
这一单元没有互测,但也并不能掉以轻心,我们通过对拍机和到处搜集的一些uml样例,对自己的代码进行了较为详尽的测试,以防强测爆炸,事实证明这种做法是正确的,我找到了一些自己由于手误而出现的bug,而这些bug的产生我想应该都是由于写代码过于仓促吧。
课程收获
我认为OO课程是我在计算机学院上过的所有课中收获最大的一门课。
正如知乎上的一条评论所说的,北航的OO是真正贴近工业生产的,真实的公司里的编程过程,与OO课设十分接近。这是一门学以致用的课程,与其它理论性较强的课不同,OO能给我带来切实的成就感,以及对于以后的工作也打下了坚实的基础。
通过OO,我也切实提高了自己的的debug能力。回想起每周天的debug场景,经历了痛苦,得到一份较为满意的代码,这种感受是别的课程带不来的。
我十分感激吴际老师的辛勤教导,我也深刻感受到了OO课程组的水平之高。OO就是六系的王牌课程!
改进建议
真真切切经历了一个学期的oo学习,我的确有几点想要吐槽的:
1、建议在pre的过程中,能给同学们提供几份示例代码,否则向我这样第一次接触的人来说,不清楚自己的代码到底有多烂,而这种风格甚至可能延续一个学期。
2、对于第四单元的uml,我认为这个单元的难度跨度有点过大,指导书也过于不清晰,很多内容甚至需要读者来猜,很多也是在讨论区解决之后才能继续往下写。或许,这一单元的代码可以和jml结合起来,用规格来替代模糊不清的指导书,这样也更不容易产生歧义,也间接减轻了同学们理解(猜)指导书含义的压力。
3、我希望可以增加对于课上实验的反馈,让同学们知道自己做的是否正确。