OO Final Summary
OO Final Summary
各单元分总结
模仿陈昊同学的做法,对于第四单元的单元总结,单独开一篇文章记录,在本篇文章内留下链接,这样看起来比较OO。
Pre2:咕了
Pre3:戳我呀
第一单元:戳我呀
第二单元:戳我呀
第三单元:戳我呀
第四单元:戳我呀
各单元收获
Pre
项目:简易书架管理系统,电子邮箱识别
接触到的东西:Java类库,面向对象中的封装,继承与多态,读文档,UML,checkstyle
架构设计与OO方法的理解
在Pre中,我对OO的理解仅仅局限于大家常说的那几个词:封装,继承与多态,比较偏向于Java的语言特性,观点不够高。虽然寒假里也看了一定的书籍,但是因为只看不练是假把式,所以对没有训练到的部分的体会比较粗浅。Pre对我OO理解最大的影响就是让我知道了封装的好处以及不封装带来的明显坏处,具体原因可以参见我的pre3的博客。
第一单元
项目:表达式求导
接触到的东西:数据生成,自动化测试,Junit,层次化设计,归一化处理,读入鲁棒性,工厂模式,依赖倒转原则,需求的变化方向
架构设计与OO方法的理解
在设计方面:
- 首先是理解了什么叫做设计,简单来说就是把我们想做的事情规划好然后以某种形式表达出来的过程。仅仅存在于脑子中的设计似乎也叫做设计,但是这样设计的最大的问题是每次复盘都有很多不一致的地方,以及难以在脑子中对初版设计进行修改,其原因主要是我们的大脑不能像计算机的存储器一样能够相对稳定的存储信息(如果是个天赋异禀,大脑记忆能力特别强且思考问题特别清晰的人那当我没说)。所以,我个人认为我们要找到合理的表达方式来表达我们的设计,才叫做设计,只存在脑子中或者只能口胡对绝大多数人来讲不能称之为设计,充其量算是思考。在本单元,我表达设计的方式是在草稿纸上写自己设计的类的属性,方法(尤其是对返回值和参数的详细描述,辅以一定量的伪代码描述方法过程),这帮助我完成了第二次作业中多叉树架构的求导模块设计。
- 进而,我对层次化设计有了一些入门理解。所谓层次化设计,就是将要做的事情做二维拆分之后分别设计每个小部分。所谓二维拆分,一维是把一个部分分成几件小部分,另一维是对于每个小部分,继续分成更小的部分,但是这个更小的部分只能被这些小部分组成的那块整体感知到,更大的部分无法“跨级”感知到其某个拆分块的进一步拆分。对于软件的层次化设计,就是把软件的大功能不断拆解成小功能,大功能仅使用其下面一级的小功能以及一些额外的逻辑来构造。对于面向过程程序的层次化设计,就是把大的函数完成的功能分成几个小的函数,由大函数调用小函数,并加上其他的一些逻辑。
- 结合面向对象,我开始对面向对象设计有了自己的入门级理解。面向对象是把问题涉及到的主要的要素按照人的认知结合成不同的“类”的概念,分析问题中的类需要哪些信息才能完整描述以及类与类之间存在怎样的关系,进而辅助我们解决问题的一种思考问题的方式。将使用面向对象的思考方式思考出来的成果表达出来(比如写在草稿纸上),就叫做面向对象设计。在第一次作业中,如果是以“我如何解析表达式”,“我如何使用求导规则求导”以及“我如何化简结果”的“线性展开”的思路进行程序设,则是面向过程设计,其中可能解析和化简过程中遇到困难时发现需要“分类分层”来解决问题,但本质上仍然是面向过程的;而第二次作业中先对要求导的表达式进行层次化的面向对象设计,得到一套各自管理自己数据的类以及类与类之间的关系,在设计类的过程中只考虑这个类本身的解析,求导和化简如何设计,则是典型的面向对象的设计。所以面向对象的思考方式说白了就是抽象出问题中提到的或者隐含的数据和方法,封装在一起,形成一个一个类,然后逐步把问题转化成类以及类与类之间的关系。面向对象的思考方式适合构建很容易就能抽象出具有层次关系的一组类的复杂的系统,但是不适合应对那种很难抽取出来对象,过程是且只是单纯的复杂的问题,比如一些算法的流程。
- 再进而,我初步知道了如何去评价一个“面向对象的设计”是不是好的,或者说够不够“面向对象”。评价的标准可以参考6大(5大?7大)设计原则。显然,每个人只要花精力,都能用面向对象的方式来把问题转化问类以及类与类之间的关系,只不过这些类以及类之间的关系是否合理,就不好说了,不能仅通过感性的思考来评判。设计原则,就是前人通过大量实践总结的好的(或者坏的)面向对象的设计所具有的特质,我们对照设计原则去检查自己的设计,一定程度上能找到自己做的好或者不好的地方。
测试方面的收获
在测试方面:
- 本单元主要使用的是利用python正则包/手写递归下降自动生成随机函数数据以及标准答案,编写简单的spj比对标准答案和自己的项目的结果。从啥都不懂到能写出一个能跑的自动评测机并不需要费太多精力,主要考虑的只有如何生成合法的输入数据以及如何生成标准答案/如何联系别人来多人运动就可以了,但是如果想提升评测机的易用性(提供详细的评测信息比如WA和TLE,提供友好的交互界面),复用性(评测机都有启动待测项目,获取结果然后评测正确性)以及鲁棒性(及时杀死可能使得评测机崩溃的项目进程),提高数据的强度(1万条随机数据可能都比不上通过读代码发现疑点后手捏的一个数据),就需要费一些精力去研究了。
- 另外,由于读入解析模块和求导模块单独拿出来哪一个都很复杂,所以我还使用junit对这两个部分分别进行了单元测试,检测出不少bug。在做单元测试构造数据的时候,也能进一步加深对需求的理解。
- 由于自己主要把精力放在正确性上,所以没有考虑过构造对性能有较大影响的数据,算是个遗憾吧。
第二单元
项目:多部电梯系统模拟
接触到的东西:多线程基础知识(主要是同步与互斥),多线程测试与debug,线程安全设计,其他设计原则,需求的变化方向,调度算法以及性能,折中
架构设计与OO方法的理解
在OO设计方面:
- 初步了解了线程安全设计。为了更加简洁方便的去设计线程安全,一种很好的方式是使用/手搓线程安全容器(感觉很像OS中提到的管程),这样可以使得业务逻辑中不会出现大量的同步块和锁,这样就可以做到二者分离开。
- 理解到层次化设计仍然十分重要。如果不追求高并发(事实上我们的评测中似乎也没有强调这方面,可能因为这个课的主要目的是教OO吧),那么线程安全设计并不会太困难,只要做好对共享数据的互斥访问,线程之间的适时协作就好了,所以,我们能够解决多么复杂的问题,能做到怎样的运行性能,还是取决于层次化做得怎么样。比如本单元中的调度器职责的分解(单一职责原则)就是典型的层次化。
- 合理的架构设计是性能提高的基石。如果没有做到上一条中的对调度器的减负,那么基本的换乘机制在实现的时候都比较难保证正确性,而没有换乘机制,就不用说使用最短路或者其他的一些优化方法了。
测试方面的收获
在测试方面:
- 学会了编写稍复杂的
spj
;意识到了设计评测机的时候也需要一点面向对象的思想;意识到了实现评测机时可以任意选用合适的编程语言来实现某些特定的模块,不拘泥于一种语言;在上一条的基础上,意识到了评测机在实现的时候最好有一定的可移植性,有些地方不要和某个平台绑的太死。 - 初步了解了IDEA中多线程断点的使用,意识到不管我们写的是什么程序,本地测试的本质就是在程序的关键位置“添加查看”并检查其正确性。
其他方面的收获
在算法方面:
-
意识到了复杂工程问题中设计的算法的性能不容易分析
- 有些表面上的“优化”实际上只是针对我们脑中刚刚灵光一现的少数特定场景,大部分情况下反而可能是副作用
- 优化做得高不成低不就,不如不优化或者大量优化
马原课上讲过,实践是检验真理的唯一标准。在复杂问题中,只有把自己的想法落实出来,然后经过测试分析,才能更准确地去评判算法的性能,减少主观臆断带来的误判。
第三单元
项目:社交网络模拟
接触到的东西:规格,JML
架构设计与OO方法的理解
在设计方面:
- 知道了世界上居然有这么一种能够相对比较严谨地描述设计的方式:规格,并且深刻体会到了规格对程序功能的正确性带来的巨大好处。
- 体会到了接口限制下的灵活性:只要约定好接口,那么具体实现的时候我们可以随意发挥,在保证功能的前提下提高性能或者做其他事情。
测试方面的收获
在测试方面:
- 熟悉了基于规格进行静态(肉眼)debug
- 除了功能测试之外,性能测试也很重要。对于性能的测试,一方面是扩大数据规模,另一个方面是读代码,找到能卡满所用算法的复杂度的情况,后者比较难,但是认真思考才能让我们有真正的收获,而不是仅仅浮于表面。
第四单元
项目:UML解析器
接触到的东西:类图,顺序图,状态图的理解,这几个视角下关心的元素,层次化管理数据,伪团队开发环境模拟
架构设计与OO方法的理解
在设计方面:
- 深刻体会到事先设计好接口的好处
- 有利于团队开发。比如规定好接口之后,我就可以去编写交互部分的代码,而其他人就可以去编写官方包中其他部分功能的开发,真正做到并行开发。
- 局部出问题在重构代码时基本不会影响其他的部分。比如UML类图出锅了,只要把类图部分出问题的接口下的方法实现做修改就好了,其他部分如果本身没问题的话,基本不需要做改动。
- 深刻体会到层次化的重要性。在管理UML各种视图的数据时,如果不做层次化管理,那么在查询一些信息的时候,一来很难维护平铺展开的庞大的数据之间的来回的映射关系,二来在全局进行搜索时效率肯定不如做了层次化之后先逐步缩小范围再在局部查询好。
- 对面向对象设计有了进一步的理解。面向对象设计,我个人理解为其本质上就是把问题域中逻辑上紧密联系的数据聚合在一起,形成类,在类内部自行管理这些数据,对外提供外部关心的数据信息,这样的话实际上就是定义了一个抽象的数据类型。最终,我们设计的类所管理的数据以及提供的功能基本上要和现实生活中我们要描述的系统的组成部分的特点对应起来。对现实生活中的系统进行拆分的方式不同,我们设计的类也就不同,这个是因人看待现实生活中系统的角度不同而不同的,这也是面向对象的魅力和艺术所在。
测试方面的收获
在测试方面:
- 深刻体会到做测试的前提是准确理解需求,需求理解不准确,那么也不可能构造出有效的用例。本单元我在理解需求上非常懵,前两次花很多时间理解UML三类视图的内部的逻辑关系,最后一次零零散散地了解到要查询的东西在一些特殊情况下如何处理以及是否需要考虑某些特殊情况,测试方面本单元我的收获很有限,全程被其他同学带飞。
课程的总体收获
通过这个学期的OO学习,我的收获非常大:
- 个人编码实现的能力以及debug能力提高。去年的我,代码甚至都写不出来,今年的我,能用一天的时间开发千行左右的程序。
- 事前规划设计的意识逐渐得到了培养,思维逐渐自顶向下。之前的我写代码都是想到哪儿写到哪儿,写的时候一直纠结细节该怎么实现,特容易卡死,在知道了如何去描述自己的设计之后,我开始试着去在纸上/写伪代码/画UML类图来描述自己的设计,并且取得了一定的成效。
- 自动化测试以及版本控制相关的技术。去年我只稍微知道一点只需要比对答案的算法题该咋对拍,现在我可以自行编写数据生成以及
spj
;在版本控制方面,体会到了使用Git进行版本控制的巨大优越性。 - 学会了看淡结果,享受过程。我在事后发现,似乎如果只是抱着拿分和通过测试点的态度去学习OO的话,似乎也有可能可以拿到一个好看的成绩,但是,这样可能会失去很多机会,包括和同学的激烈讨论所产生的思维火花的机会,包括学习新技术并应用于完善自己的项目的机会,包括良好心态和抗压能力的培养机会等。我庆幸自己本学期没有抱着这样的目的去学习这门课。
- 结识了新的同学。通过OO课(其实还包括一点寒假里的活动),我结识了
yzr
,cja
,dhy
,fzc
,ch
等同学,他们在OO课的学习上给了我很多的启发和实际的帮助,也算是我在1906结识的第一批同学了。在此,我非常感谢yzr
同学一学期以来对我长期的帮助,感谢ch
同学治疗好了我的低血压,感谢fzc
同学和cja
同学在第四单元指导我如何理解UML以及做测试,感谢dhy
同学在第二单元我最困难的时候给了我很大的启发,没有各位的帮助,我不可能得到现在的成绩。 - 信心重建。去年的我,曾一败涂地,丢盔卸甲,学业中道崩殂,此后的三四个月时间里都感觉自己彻底不行了,曾经的一些习惯一下子全部荒废,斗志全无,朋友和爱人因我的堕落而离开,与亲人关系达到有史以来最低水平,身体状况每况愈下,最重要的是,OO似乎成了我永远的“意难平”;再次面临OO时,我下决心绝对要打赢和OO的这场生死战。从结果来看,12次代码作业编写均独立完成且均无明显翻车,结果还算不错。至此,OO再也不会是我的意难平,我不会再因为过去的表现而责备自己了,内心的废墟,在时隔一年之后也终于迈出了灾后重建的第一步。灵魂回来了,其他的一切从头再来只是时间问题而已,一点一点搞就好了。
课程建议
- 对于后半段同学来说,他们的学习困难在于不知道该怎么去寻找资料学习,另一个方面在于源于某些心理而一直想孤军奋战,但因为实力不足而陷入困难。对于既想孤军奋战又不太会查资料的同学来说,OO课几乎完全是这些同学的克星(没错,说的就是去年的我)。对于人的心理,我们难以改变,但是对于不知道该怎么查资料的这种情况,我觉得课程组可以提供更多的引导,给大家开拓更广的搜索资料的思路,介绍一下正确的资料搜索姿势。这一部分内容可以体现在每次的作业指导书里面。
- 重视demo的引导作用。第二单元的生产者消费者模型实验对大家多线程的理解以及作业的完成帮助非常大,究其原因,就是在于本单元的实验设计得非常好,对本单元的学习有重大的指导意义,故此处实名表白ganten学姐。而对于困难的第一单元第二次作业(主要是表达式的解析部分)以及第四单元的UML的理解,是否也可以通过类似的给出一个demo的手段去帮助大家学习呐?这个值得思考。虽然给出demo和培养自学能力这两方面确实存在一点矛盾,但是二者做一下折中,给出一个合适的demo,对于自学是有很大的促进作用的。
- 建议每个单元的训练栏目增加测试指导书或者测试相关内容,再不济,最好每个单元能有官方的抛砖引玉的测试引导帖子,这对大家测试能力的提高有很大的帮助。
- 建议修订第四单元指导书,把最近两年的讨论区中问到的确实有价值的问题在指导书中做出一定的补充,让需求的理解不再那么费力(当然,现在已经很好了,大部分已经说得比较清楚了)。
- 建议把少数三四单元的思想或者内容在课程伊始就介绍一下,方便让大家去理解什么是设计,什么是架构,如何表达设计与架构,这样同学们才能跟得上老师的思路。
- 建议理论课能多还原一下设计的过程,尽量少直接一整个类图一次性放出来,上课看到这样的ppt看不过来,并且不清楚这个是怎么设计出来的,只有结果没有过程,这样好好的例子会被浪费掉的。
- 建议设置专门的课程大班群。我了解到的情况是,OO课完美诠释了什么叫马太效应:强者更强,弱者更弱。大佬们扎堆讨论架构设计、优化与测试,不认识大佬的同学们就各种挣扎。有一个专门讨论OO的大班群,能方便答疑,能方便大家互相认识,是很有好处的。