ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

面向对象学期总结博客——下一站旅途

2021-06-26 12:33:07  阅读:132  来源: 互联网

标签:层次化 封装 代码 作业 学期 面向对象 抽象 旅途 单元


  • 总结本单元作业的架构设计

    ​ 第四单元的主题是UML图的解析,学习的首要任务是要了解UML图的组成、结构以及其他的一些必要知识。必须要把握UML图的本质是树,它把变成语言中的“类”与类之间的关系都抽象为对象,并将其按照一定的层次化结构组织起来,使UML图语义明确且没有二义性。

    ​ 在对UML图有了一些基本的了解后,就可以开始着手UML图解析器代码的编写了。输入和输出部分的繁琐代码课程组已经帮我们做好了,剩下的是完成中间的核心解析部分的代码,我认为这三次作业有两个明确的任务:第一个是存储,也是最难的一部分;其次就是搜索和查找,这是解析动作真正发生的地方。

    ​ 本单元三次作业均围绕存储和查找两部分进行架构设计的考虑,中间为了改进存储进行了一些架构上的调整,走了一些弯路,总体而言本单元三次作业的架构比较合理。

    • 第十三次作业
      • 本单元第一次作业是最难的一次,因为是对UML的初步接触,对UML图的结构不甚理解,需要花一定的时间去自学。在存储架构上,我也作出过许多尝试,最终都被一一推翻,形成最终的架构设计。

      • 架构设想1:全局哈希表查找
        • 第一个版本的架构是最简单粗暴的。直接将所有的数据按照输入分开不同的hashmap存储起来,不做任何处理,显然这种方式没有作任何的抽象,不符合面向对象的设计思想;虽然存储很方便,但是查找的时候会异常麻烦。
      • 架构设想2:简单粗暴的“树”构建
        • 第二个版本的架构是直接按照树的构建方法,按照原始的逻辑存孩子节点。这种方法是在理解了UML图的本质是树这一点后作出的尝试,但同样没有作出抽象,按照UML图原始的树结构来查找依然存在一定的麻烦,因此这个架构设想经过考虑后被我舍弃。
      • 架构设想3:将UML图中的“节点(Node)”抽象出来
        • 第三个版本的架构是考虑到查询的需要,将整个UML视作图,而UmlClass和UmlInterface就是抽象的节点,他们有许多共同的属性,都存储了一定的信息,都可能与其他的Node节点有着这样或那样的关系(继承、实现、关联等等)。基于这一点考虑,我将自己新建的两个类MyClass和MyInterface都实现同一个抽象接口MyNode。
        • 此外,由于查询的需要,我对很多UmlElement都做了自己的封装和处理,在实例化时存储一些关于自己的私有的属性,以便于查询;例如本次作业中的UmlClass、UmlInterface、UmlOperation等等。
        • 第一次作业直接把存储的过程暴露在了UmlInteraction上,没有作任何的封装和处理,导致代码结构极其糟糕,这是我认为第一次架构存在不足的地方。
    • 第十四次作业
      • 第二次作业比较轻松,主要是增加了顺序图和状态图的查询。由于查询的指令变多,代码逐渐变得臃肿,因此我构造了一个存储类MyStorage实现所有数据的存储,向外只提供查询和存储的接口,使结构更加合理清晰。
      • 此外,在实现MyStorage使使用了单例模式的设计模式,既保证了存储和查询的唯一性,也使调用的过程更加简洁。
    • 第十五次作业
      • 第三次作业主要是要解决“Wrong Format”的问题,只需加一个MyCheck的类,并将所有的检查代码封装其中即可。

    ​ 本单元作业的缺点也比较明显,在处理存储关系时代码仍然较复杂,在新加代码时害怕把原来写的改错,违背了开闭原则,说明我的代码封装仍然不够彻底。我的想法是将所有处理存储和查找的代码都封装在各自的handler类中,并统一实现一个handler接口,如此在新增功能时只需要新增加handler类即可,不需要对原来已经实现的代码进行修改。



  • 总结自己在四个单元中架构设计及OO方法理解的演进

    • 第一单元:多项式求导
      • 第一单元的架构设计经历了较大的挫折,经历了一次彻底的重构。由第一次的面向过程代码到后来的递归下降法,体会到了面向对象编程中“抽象”的魅力,将多项式层次化拆解并抽象成一个一个的item,他们都有一个共同的操作就是求导,每个对象只需关注自己的求导操作是如何进行的就可以了。
      • 第一单元第三次作业的错误格式检查让我印象最深刻。面对指导书复杂的描述,正确的文法捉摸不透,错误格式仿佛大海捞针,情况实在是过于繁琐和复杂了。但是第二次作业的重构使我避免了这些烦恼,将所有对象层次化设计后,合法的多项式一定是这些item的组合,item的组合仍然是item。只要按层次逐步递归解析多项式,能够成功解析的一定是合法的多项式,如果最后不能成功解析,则说明是错误格式。
    • 第二单元:多线程电梯
      • 第二单元涉及多线程。初步接触多线程,由于对各种同步和唤醒机制不理解,导致我第二单元第一次作业弄得一团糟,周日早上电梯才能正常跑起来,还好没出现太多的bug,强测没有翻车。回头看看那一次作业是我12次作业以来最狼狈的一次,也是最接近“绝望”和无助的一次
      • 第二单元是自我突破最大的一次。在架构设计上继续沿袭层次化设计的思想,实现电梯的分层调度,明确调度器和电梯的职能,分析好不同线程之间的同步关系,保证线程安全。这一单元后半阶段并没有遇到很多死锁问题,这得益于架构设计和线程并发设计的合理性。
      • 第二次单元是我尝试最多的一次,观察者模式、单例模式、策略模式、状态模式……在这一单元为了更好地完成作业,我听取了老师和同学的建议,采用了许多设计模式,最后实现在代码中效果都非常显著。。
    • 第三单元:JML规格化编程
      • 第三单元的架构设计比较固定,自己新建的类比较少,主要是理解JML规格的语法,明白JML语言的含义,按照规格编程,保证对规格的理解正确,细心一些就可以了。第三单元是四个单元中最轻松愉快的一个单元。
      • JML单元设计一些算法的设计和数据结构的选择,这都不是本课程的重点了,在此不多赘述。
    • 第四单元:UML解析
      • 第四单元的架构设计已经在第一部分叙述。


  • 对OO方法理解的演进
    • 面向对象是一门大学问,即使是经过一个学期的千锤百炼,我对OO的理解仍然停留在很浅的层次。如果说这个学期下来,OO给我留下了什么印象,我想那一定是封装、抽象和层次化设计,对这三个关键词的理解在每次代码作业中一次次深入。12次代码作业下来,我相信这也是课程组希望我们在这个阶段能掌握的编程思想和方法,而每次作业的迭代开发,都仿佛是课程组在我耳边疯狂提醒我:再不封装你就完啦!再不抽象你就完啦!再不层次化你就完啦!

    • 封装
      • 封装,或许是大一下学期上荣老师的C语言课时一直提醒大家的“拆函数”的能力。而在OO的世界里,代码就不仅仅是“函数”这么简单了,封装本身涉及到类的规划设计,类的属性可见性,类的方法可见性一系列复杂的问题,也是每次架构设计中脑子里两个小人在吵架的内容:哪些东西应该直接暴露出来,哪些东西自己藏着,不能乱来,要看必须经过我的允许
      • 面对纷繁复杂的需求,合理的封装是非常必要的。以第一单元为例,求导的过程是需要封装在item类里面的,而解析多项式,把多项式拆解为item(解析item的过程)这一部分代码也是需要封装起来,与输入解耦的;第二单元中的调度器调度功能、电梯载人功能都是需要封装的;第三单元各算法的实现细节都是需要隐藏在类里面的;第四单元的存储、格式检查也是需要封装的……封装看似平常,但是却体现在每一次作业中。封装的作用之一是为了增强代码的可扩展性,当需求改变时尽可能将代码的改动范围缩小至代码封装的范围之内
      • 封装的作用之二,在我看来是为了使方法调用更有条理,不会使方法调用满天乱飞。比如第四单元,我还因为封装的问题出了小毛病;由于需求过多,类里面的方法较多,外部的调用函数到处乱飞。而我没有封装好寻找接口的部分代码,导致外部调用的时候因为错误调用(这个方法是实际要调用方法的子方法,返回值有细微差别且不易察觉,理应隐藏)导致出现bug,这种错误发生在单元是很不应该的。
    • 抽象
      • 抽象是老生常谈的话题了,与其说这是一种编程思想和方法,倒不如说是一种哲学上的方法论。抽象的内涵非常丰富,抽象没有固定的模式,需要具体情况具体分析,根据需求对代码进行合理的抽象。
      • 其实抽象本身就贯穿在我们的日常生活中,抽象程度的高低在一定程度上决定着我们对问题认识的深浅,反映我们对问题是否理解得更深入。具体到代码实现中,合理的抽象可大大提升代码的可扩展性。
      • 具体来说,在第一单元中,我第一次接触”抽象“的概念,在课程组的引导下,成功把”derivable“这一类抽象出来,就是说所有的东西都是可求导的事物。如果需求增加,例如增加求偏导功能、求高阶导功能,增加求不定积分的功能,等等,都可以在不改变原来代码的前提下增加抽象类(或接口)或增加接口中的实现方法,有条理地实现新需求而不需要对原来的代码进行改动。第一单元作业改变了我对面向对象中”抽象“的认识,所谓”抽象“并不是对类的简单划分,而是将具有在深入考虑类之间的关系以及共同点后,人为地将一些类的共同点上升为更高层次的抽象类,为扩展留下了空间。
    • 层次化设计
      • 层次化设计也是课程组一直强调的设计方法,并将其贯穿在四个单元中。第一单元中的层次设计思想效果是非常显著,之后的作业包括第二单元的电梯分层调度,第三单元的network-person层次结构,第四单元的UML树状层次结构……四个单元下来,如果没有层次化设计,一定会过得非常痛苦。
      • 层次化设计体现的就是分而治之的思想,如何把复杂的需求下放,分解为一个个简单的小需求,多方配合协作完成一个复杂的需求(电梯分层调度就是一个非常典型的例子,电梯yyds!)。其中分层的粒度是非常值得玩味的,简单来说就是站在类(或线程)本身的角度去思考,”我是谁?我在哪?我要干什么?这事你干还是我干?这事我要干到什么程度?我干不完会有别人帮我接着干完吗?“,反复琢磨每个层次的职能,确定合理的分层粒度。
      • 以电梯为例,总调度器-子调度器-电梯三层结构各自的功能是整个代码的脉络所在(总调度器负责决定将请求分配给哪一类电梯,子调度器负责决定将请求分配给该类中的哪一部电梯,电梯负责执行请求并将执行的结果返回给总调度器),层次化设计思想使三者的职能更加清晰明了,不同层次之间的配合、协作关系更加清晰,为维护线程安全提供了极大的方便。(ps:第二单元第一次作业我就是因为层次化设计非常糟糕,调度器和电梯运行的各个环节紧紧耦合在一起,线程协作一塌糊涂,导致电梯跑成一块废铁,主要原因还是因为没有理清各个层次的职能是什么)
    • 总结
      • 上述对于封装、抽象、层次化设计的表述,都是基于12次作业和个人的一些理解粗浅谈之,记录OO这门课程在我脑海中留下的痕迹,回顾一学期走过的路,仅此而已。


  • 总结自己在四个单元中测试理解与实践的演进

    • OO课程的测试环节也让我收获颇丰,从一开始的依赖随机数据黑盒测试,到后面学会研读自己代码找逻辑漏洞(白盒测试);从一开始的随机数生成数据,到后面的有针对性、点对点式的构造数据,与朋友合作构造不同侧重点的有一定强度的测试数据(主要体现在第三、四单元),我认为我在测试这一方面有了比较大的进步。

    • 第一单元
      • 测试小白选手。对于表达式求导数据的生成采取随机、黑盒的测试手法,生成一坨强度不大的数据,并自以为测试得十分充分。但是最后的bug都是因为自己反复琢磨代码发现的漏洞,通过测试测出的bug少之又少(现在想想似乎甚至没有)。
    • 第二单元
      • 对测试方法有了一定的了解。针对线程安全问题自己手动构造了一些有一定强度的电梯请求序列,果然给我自己测出了几个死锁问题(主要是电梯无法正常结束);此外对于电梯的运行逻辑,也是手动构造一些特定的请求序列,观察电梯的运行状况,通过这一手法我发现了电梯的运行逻辑上的漏洞(一开始的设计不符合ALS的运行规则, 有超时的风险)。总而言之,第二单元的作业使我养成了善于自我纠错、以及永远要怀疑自己代码有bug的习惯。
    • 第三单元
      • 第三单元针对的是单元测试,但是很可惜的是由于学习成本过高且Junit运用不熟练时的测试没有强度,我在这一单元没有采用单元测试的手法。同样也是通过黑盒测试/代码走查来检查代码的bug。但是由于有JML语言的规范,这一单元的代码走查相对而言比较有条理和把握,是相对比较轻松的一个单元(无论是从代码架构设计、编写和测试的角度)。
    • 第四单元
      • 第四单元我完全养成了白盒测试的习惯,(白盒测试才是yyds!)。尤其是最后一次作业,这次作业是我12次作业出现bug数量最多的一次(我也不知道为什么 摊手.jpg),然而八成的bug都是通过代码走查+白盒测试找出来的,想想如果我还是依赖黑盒测试这单元该会死得有多惨(bushi。
      • 在前三个单元的基础上,我养成了边写代码边留存疑点的习惯,mark下可能会出现bug的地方,并在编写完成后立刻测试。例如:这个地方是否会报空指针异常?这个地方是否会出现越界访问?在编写代码的时候都无从得知,代码编写完成后针对这些点进行一一验证,(一般这种地方都会真的出bug,很神奇),测出bug以后定位变得非常简单,一步一步修改和完善即可。可以说,前三个单元养成的测试习惯,救起了我的最后一次作业qwq。


  • 总结自己的课程收获

    • 谈完了知识上的收获,下面来谈点别的。

    • 第一次接触面向对象这门课程是在寒假的pre,当时是抱着学习java语言的心态来学这门课程的,一次一次的task迭代非常有意思,看着自己编写的类相互协作能跑出正确的结果也是成就感满满。当时想的是:面向对象不过如此嘛!不就是将类和它们的属性、方法封装在一起然后嗯跑就完事了!

    • 让我印象最深刻的是开学后第一次课,荣老师举的四则运算的例子,还有助教用面向对象写的C语言实现四则运算代码,是我面向对象的启蒙。那时我才第一次意识到,面向对象绝对不是简单的函数封装化的面向过程,这是一个站在更高的层次编写代码的思想,它对代码的理解有着更大的格局,不仅仅是满足于本次代码的需求,而是立足本次需求尽可能地谋求迭代开发的最大可能性,是一门非常高深的学问。原来面向对象这么高深,看来是自己之前太肤浅了

    • 直到我鼓起勇气报名了本学期我们班的第一次研讨分享,站在台上分享自己代码的实现方式(正值第一次作业到第二次作业的重构阶段,个人认为这次重构是编程习惯和编程思想的一次小小的质变),与老师和同学们进行交流,对我的帮助非常大。同学们提出的各种问题我自己在实现的时候也并没有考虑到,老师在一旁的解答也让我收获很大。面向对象要有所为有所不为,架构设计的时候尽可能地不考虑太多实现的细节以及输出的优化,但是在一些关键问题上必须要较真,例如层次化设计、如何对类进行抽象等等,都不能含糊。代码一定要有自己一套完备的运行逻辑(即使简单),在架构设计之初就要考虑清楚和尽可能完善,否则会在后续代码编写的时候出现这样或者那样的问题。

    • 到了第二单元接触了多线程,了解了线程安全问题,了解了这样或那样的设计模式并尽可能地在自己的代码中加以实践,这样的实践效果是显著的,也让我在第二单元作业中尝到了甜头。第二单元是我感触最深的一个单元,这一单元的单元博客也是我写得最认真最详尽的一次,特别是在博客的感想部分,三次单元下来受过的挫折,思考过的东西都可以在博客的感想中表达出来,算是对自己三次作业的一个小小的总结,为了让我以后能更好地前行。

    • 第三、四单元主要是JML和UML的使用,虽然没有开学初那样刻意强调”面向对象“了,但是我自己编写代码的过程中已经不自觉地”面向对象“了(也是被课程组的迭代要求整怕了)。在编写代码的时候下意识地考虑下一次的迭代可能,不经意地将课程组强调的封装、抽象和层次化设计运用于代码之中。现在回顾起来不禁感叹,面向对象确实也不是什么神秘的东西,它的方法论并不困难,困难的是将这套方法论运用于代码实践的过程。

    • 一路走来除了老师和助教的帮助以外,还非常感谢身边朋友的帮助——一起编写测试数据,一起debug,如果没有和朋友们的团结协作,OO这条路我可能会吃更多的苦头。

    • 很久没有因为一件事写了这么多的纯文字,这一次是要和OO说再见了,上周日OO课程组也非常有仪式感地跟我们说了再见。一学期下来,只能说感谢所有的遇见,如今是时候奔向下一站的旅途了


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

    • 理论课程的ppt字体可以适当调大一些,实在装不下分页也可以呀qwq,UML和多线程那一块理论课一堆看不清楚的代码样例听得好难受。
    • 总结课上可以适当分享优秀代码的实现过程供大家伙参考参考,仅凭互测屋的那些代码很难让我们把握到这单元的优秀代码到底长啥样(好奇.jpg)
    • 建议弱化第一单元的性能要求,多项式求导的结果优化过程实在是过于面向过程和过于痛苦了。

标签:层次化,封装,代码,作业,学期,面向对象,抽象,旅途,单元
来源: https://www.cnblogs.com/lyxcorgi/p/14933957.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有