OO课程总结

本篇博客是最后一次博客作业,分为两个部分:①对第四单元的总结。 ②对本学期OO课的总结。

第四单元作业的架构设计

第一次作业 · UML类图管理

​ 类图中有什么元素,我就建什么类。这包括:MyClass, MyInterface,Operation, Parameter, Attribute。

在交互接口初始化时,依据类图的具体结构,建立抽象的层次结构。查询时,直接按照算法查询即可。

​ 考虑到输入只有一次,所以查询时使用了记忆算法进行优化。

​ 类图如下:

第二次作业 · UML综合管理

​ 建立三个交互类,分别实现三个交互接口。总的交互类管理三个子交互类,并把查询任务分派给它们。

UmlGeneralInteraction是三个接口的综合
①UmlClassModelInteraction 类图交互接口
②UmlCollaborationInteraction 顺序图交互接口
③UmlStateChartInteraction 状态图交互接口

建立与三个接口分别对应的三个管理器类
MyUMLModel 类图管理器 ,管理类图里面的元素;
MyUMLInteractionBox 顺序图管理器 ,管理若干顺序图
MyUMLStateMachineBox 状态图管理器 ,管理若干状态图

对查询方法,层层拆解并分配,逐层降低复杂性。

getTransitionTrigger为例

第三次作业 · UML综合管理及自我检查

​ 顺承前一次作业的架构,把8项检查任务分配给三种图的管理器来做。对不同的检查方法,分别设计算法。架构与前一次作业没有较大改动。

8个检测方法的算法基本上是复现指导书的描述。其中有一些方法都涉及查重,采用了类似的算法:用一个Set进行深度优先搜索,如果发现重复,则直接报错,上层进行try catch处理。另外,依然采用了记忆算法,对某个类进行过某方面的查询后,把查询的结果记录下来,下次不重复查询。

四个单元中架构设计及OO方法理解的演进

第一单元:

​ 从第一次作业的面向过程开始,到后两次的面向对象,是我对OO的入门阶段。第一单元的面向对象,让我具体的体会到面向对象的一个重要优点:OO能够降低程序设计难度。在处理一个多项式的时候,我的程序里与之对应的存储了一个多项式类,把多项式拆解为各个项后,我的程序里也有Term类与之对应。多项式有加减乘除的求导法则,我的程序里也有Derivable接口与之对应。不同类型的表达式有不同的求导规律,我的程序里建立不同的子类与之对应。

​ 这样一来,求导运算的数学过程,就与程序计算的执行过程相对应,程序的逻辑一目了然,开发和维护的难度都大大降低了。

​ 面向对象的设计思想帮我更好的把程序拆解成若干个模块,每个模块解决好内部的问题,而无需过多关注总体算法,这种封装是化难为易的有效措施。

第二单元:

​ 多线程是程序的一个强大功能,要想实现这个强大的功能,离不开良好的架构设计。而良好的架构设计,又离不开面向对象的设计思想。很难想象,如果抛弃了面向对象思想,而用面向过程的方法来写电梯作业,要如何实现多线程。这个单元让我认识到,OO不仅仅是在开发、维护等很多方面优于面向过程的一种编程思想,更是实现许多高级、复杂功能的必需品

​ 那个单元的电梯,我采用了Look算法和多电梯竞争策略。多部抽象的电梯对应多个具体的电梯线程。架构非常清晰,最后一次电梯的性能也是最优的。

img

第三单元:

​ 经过这个单元的训练,我认识到:OO也可以高性能,面向对象与面向过程不是完全对立的。

​ 官方包是已经写好了接口描述的代码框架,我们需要填充里面的内容。这个代码框架是良好的OO设计,而我们完成的内容,则要在实现功能的同时,着眼于性能(时间复杂度)问题的解决。同样一套JML,尽管对应着相似的架构设计,但实现细节却因人而异。

​ 程序的整体架构是面向对象的,然而程序的一些局部算法则可以面向过程。比如求最短路径的Dijkstra算法,在实现的时候,我把它完全放在一个方法内部,即便没有把它单独提出来作为一个“求最短路径类”,也没有什么不好,架构依然清晰,开发和维护依然便捷。

​ 马克思主义认为,真理是绝对性和相对性的统一。那么面向对象这个“真理”也是如此,它不仅有绝对性,实际上也有相对性。如果不分场合,不论需求的面向对象,就犯了教条主义的错误。

​ 我认为,对一些较大的工程项目来说,整体应当面向对象,局部可以面向过程;架构应当面向对象,算法可以面向过程;重视开发和维护的时候应当面向对象,苛求性能的时候可以面向过程。OO应当是我们的一个编程手段和设计选择,是我们编程的“思维栈”一个重要的组成部分,而不应当成为限制我们的“紧箍咒”。

第四单元:

​ 这个单元的作业,主要难点在于对UML的理解,而编程本身不难。具体架构设计见前文,这里不再赘述。

​ 值得一提的是,我在做这一单元的编程作业时,OO的思考方式已经形成习惯,我毫不犹豫的给出了层次化的面向对象架构设计,并且在三次作业的迭代过程中,代码基本只增不减,没有重构。

​ 对我来说,在工程开发上,OO,已经是一种习惯。

四个单元测试的理解与实践的演进

​ 完善的程序离不开测评。测评的效率也极大的影响了程序的优良性。这四个单元中,我都自己写了测评机,在不断的进行测评的过程中,我对测试的理解越来越深入。

第一单元

​ 作业是用java写的,测评机是用python写的,调用了sympy这个包,用于求导。在这个单元的测评机的写作过程中,我仅仅是随机生成了大量的样例,试图用样例的数量来保证测评的完备性。由于样例的数量的确很大,而且表达式的情况也并不是特别多,所以我在第一单元写的测评机取得了很好的效果:互测时基本不存在同房成员有bug却没有被我测出来的情况。我在写作业的时候,忽视了三个减号连续出现的情况,幸好用自己的测评机测出来了。我深刻的体会到:测试是查找和弥补思维漏洞的有效手段。

第二单元

​ 我依旧写了测评机,但互测时测出来的别人的bug却无法在官方测评机上复现(我只提交了一次)。他们的一些代码,通过了官方测评机的测评,但是在我的测评机上却会崩,原因可能是操作系统的差异导致了多线程bug不能完全复现。这其实体现了测评的一个根本不足:完全的黑箱测评只能证明错误,却无法证明正确性,即使是测评量再大也不行。所以,测评不能完全代替形式验证。不能试图用大量的测评来代替编程时的严密思维。在这个认识的触动下,我改变了自己做算法题的习惯:每道题都争取用形式验证来保证正确性,然后再用测评作为双重保险。在这种理念的指导下,我进行了若干算法训练,在蓝桥杯中也取得了成绩,这可以看做是OO给我的“赠品”。

第三单元和第四单元

​ 我曾经在一次展示课上展示自己的测评机,老师的点评改变了我测试的思路,让我受益匪浅。我做了一个测评机,但是样例仅仅是主观随机构造的,尽管的确测出了自己的bug,但这种“感性”的测评,其效果往往不稳定,有时候能测出bug,有时候不行,而且不能保证测评的完备性。根据老师的指点,我在下一次作业中,把输入的所有可能情况分成若干类,以表格的形式组织成了一种树形结构,并且保证我的测试点把这个树形结构的某个分支都覆盖到。这样,只需要比随机测试点更少的测试点,就能测试出更多的bug,而且测评效果也更有保证。测评,应当是理性地、地毯式的漏洞筛查,而不能是感性地、主观地碰运气。

课程收获

​ 这门课给我的收获太多了,下面按照重要性列出前三个。

增强了面向对象编程的能力和工程实践能力

​ 在上这门课之前,我尽管曾经听说过面向对象,但是却没有进行过比较大的OO项目的开发。在这门课中,我经过若干次作业的练习,对面向对象编程手法更加的了解,对面向对象的知识体系更加熟悉。在编程思想方面,我实现了从面向过程包打天下到面向对象与面向过程综合使用的思维跨越。这是我最大的收获。

​ 每个单元的作业都可以看做一个有一定规模的工程项目,反复的训练中,对我的工程能力是一个提高。而且在测评方面,我的认识也逐步深入。

友情,合作能力

​ 我深刻的认识到,现代的工程项目,很少有完全由一个人完成的,大部分都是团队合作完成的。所以我以OO这门课为契机,以合作写对拍机为主要途径,着力提高自己的合作能力。

​ 我们有一个OO学习小组,每次作业结束之后都会对架构和算法进行交流和讨论。在不断的思维碰撞中,我们的能力都有所增强。在最终的发奖环节,我们五个人获得了四张证书。

助教们精益求精态度带给我的心灵启迪

​ OO课程组是我上过的所有课程里最用心的课程组。这门课精益求精的态度深深的感染了我。精益求精,这才是一门金课应有的样子。

​ 所谓“工匠精神”,未必只能用来形容传统手工艺者。程序员也可以有工匠精神,程序员也应当有工匠精神。编程工作的快捷,不代表编程质量的低下。编程,要“快工出细活”。

​ 下面是我有一次对助教的回复。

随着我的成长,OO的知识会内化为我技术水平的一部分,我可能不记得某些OO知识是在什么地方学的,但是这门课精益求精的态度却是让我终身难忘的。

立足于自己的体会给课程提三个具体改进建议

下面分三个方面提出建议,由于我技术水平和编程阅历均有限,所以我的建议可能不好,还请读者海涵。三个建议按照重要性排序。

①建议及时公布实验课的成绩和答案。

​ 这涉及到课程组对实验课的定位。

​ 如果课程组对实验课的定位是检测同学们的学习效果,那么就应该严肃实验课的纪律,并且应当提前发布测试主题。

​ 如果课程组对实验课的定位是培训和提高,起到对理论课的补充的作用,那么就应当给同学们及时反馈,而且实验课的内容不宜过难。

​ 有些实验课的内容在理论课上没有介绍过,对于这种情况, 我个人认为实验课的题目不宜过难。否则,在这种“有限时间学习+做题”的模式下,实验课就成了适应性测试,但适应性测试的意义是“选拔”人才,与OO课程“培养”人才的目的并不一致。

②建议降低电梯单元第一次作业的难度

​ 电梯单元一个重大的难点是多线程编程。第一次作业不仅要求实现多线程电梯,而且分成了Morning,night,random等多种模式,对电梯的性能也有要求。

​ 其实对于没接触过多线程的同学来说,多线程本身已经很难了。因为不仅需要学习多线程编程语法,而且思维也需要从串行转变到并行,这并不容易。很多助教和老师都可能会轻视多线程对同学们的难度。这是因为“多线程”之难,主要难在概念上。它是“会的不难,难的不会”。如果已经学习过多线程,熟悉加锁的若干技巧,当然会觉得多线程容易,但是对没有学过这些东西的同学来说,这是很难的。

​ 电梯单元第一次作业如果过多的强调除了多线程之外的内容(比如电梯的性能),不仅仅会增大同学们编程的难度,而且有可能冲淡了同学们对多线程的思考和学习,这是得不偿失的。

​ 个人认为,没有必要为了防止某些同学采用单线程而对性能进行过多要求。指导书上已经说了“本次作业要用多线程实现”,这是一个君子协定。如果有的同学不遵守,那么它第二次作业一定做不完,属于自讨苦吃。没有必要为了提防这一小部分同学,而让大多数同学承受过过重的负担。况且,如果有些同学无法用多线程来完成作业,这是不是反而从某种程度上说明,作业的难度过大呢?况且,即使课程组想检测同学们到底有没有用多线程实现,也有无数种其他办法。

③从细节入手,进一步提升课程品质。

比如,关于课程网站评测界面

强测界面中,代码风格分竟然比强测得分字号更大,这有点喧宾夺主的意思。私以为,程序的正确性是要经过艰辛的努力才能保证的,然而代码风格却可以通过idea的快捷键来做到,所以强测得分应当比代码风格分更加重要。既然强测得分更重要,字号是不是也要更大呢。

比如,关于指导书的语言表达

指导书的语言表达可以再明确一些,把同学们有可能在讨论区问出来的问题提前做出回答,能够提高课程的效率。

我当然知道,由于作业本身的复杂性,指导书的书写并不容易。但是如何由浅入深的介绍作业内容,如何用简洁清晰的语言来描述作业要求,体现了课程组的创造力。

posted @ 2021-06-25 22:34  邢云鹏19231177  阅读(94)  评论(0编辑  收藏  举报