面向对象设计与构造第四单元作业总结

面向对象设计与构造第四单元作业总结

前言

随着本学期课程的逐渐结束,面向对象课程也落下了帷幕。还记得,从假期的java-pre开始,到求导,到电梯调度,再到jml,我们在与面向对象作业的交手中已经学到了很多,本单元的uml解析器也终将画上一个句号。虽然我本人水平有限,在本学期的面向对象课程中磕磕碰碰了一路,表现一般,但还是很高兴学到了很多东西,不仅仅是什么是面向对象的思想,更是整个计算机专业技术水平的提升。

对于本单元的uml解析器部分来说,比较困难的地方在与对uml的类图,顺序图,状态图的理解(尤其是结构层次和相互关系等)。理清了uml各个部分的逻辑之后,本单元的内容也就较为简单了。紧接着的这部分是本单元的设计架构等内容。

单元作业的架构设计

第一次作业

在第一次作业中,我们需要实现的是MyUmlInteraction类,该类需要继承UmlInteraction接口。我们在本次作业中需要完成的内容,也只有UmlInteraction接口中的各个方法。至于剩余的类和方法,包括输入输出等,都已经由官方实现。

虽然在官方的代码中,我们能够看到已经实现了以Uml开头的各个类,如UmlClass等。但是这些类内部只定义了基本属性,包括name,id,parentId等,缺少对方法,属性等元素的承载和管理能力。因此,我们需要单独实现MyClass,MyInterface等类。在本次作业中,我选择额外实现了MyClass,MyInterface,MyOperation这三个类,用于抽象层次的包含与管理。这里并没有实现MyAttribute等类,因为MyAttribute显然不会再在逻辑层次上含有下级(至少在本次作业中不会),直接使用UmlAttribute即可。

第一次作业的类图的简单架构如下:

  • UmlClass
    • UmlAttribute
    • UmlOperation
      • UmlParameter
    • association、parent、interface
  • UmlInterface
    • UmlOperation
      • UmlParameter
    • association、parent

第一次作业的实现内容如下:

此外,在本次作业中,为了提高查找的性能,整体上的容器选择了两个HashMap,分别是id索引的HashMap<String, Object>和name索引的HashMap<String, ArrayList<Object>>。每加入一个元素,则在两个容器中同时加入元素。如果使用id查询,则使用第一个HashMap,如果使用name查询,则使用第二个HashMap。基本上整个第四单元作业都是使用了这种容器。

第二次作业

在第二次作业中,我们需要对已经实现的MyUmlInteraction类进行拓展,使其能够额外支持顺序图和状态图。

第二次作业的顺序图简单架构如下:

UmlCollaboration

  • UMLInteraction
    • UmlLifeLine
    • UmlMessage

第二次作业的状态图的简单架构如下:

UmlStateMachine

  • UmlRegion
    • UmlState
      • OpaqueBehavior
    • UmlPseudostate
    • UmlFinalState
    • UmlTransition
      • UmlEvent
      • OpaqueBehavior

第二次实现的内容如下:

在第一单元的基础上,MyUmlGeneralInteraction类中额外记录了所有的StateMachine和Interaction。

对于每一个StateMachine,内部都记录了所有的State,而State之间的转移关系被记录在了State的内部,也就是说每一个State都记录了所有能够转移过来或者转移过去的节点与方式。

对于每一个Interaction,则含有所有的LifeLine,每个LifeLine记录了其他节点发给他的message和他发给其他LifeLIne的message。

第三次作业

第三次作业是针对类图,顺序图和状态图进行检查,并抛出对应的异常。整体架构与前面第二次作业保持了一致,只是在MyUmlGeneralInteraction等类中对额外实现了错误检查方法,对错误实现了检查。

这里唯一值得一提的便是是否由循环继承的判断,这里我选择使用了dfs的方法。对每一个节点使用dfs,如果在dfs的过程中发现了自己,则说明该点在某个循环当中(为了避免死循环,需要记录已经访问过的节点,如果访问到了已经访问过一次的节点,那么该节点无需重新访问)。

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

第一单元

可以说第一单元是我OO上路的部分,在这一单元中我对OO的理解有了较大幅度的提升(大概主要来自于重构),也正是在这一单元中,我理解了为什么要使用类,为什么要提前思考可拓展性,为什么要做整体架构设计,也明白了类之间解耦合的重要性(也是单元中比较靠后了)。

在第一单元三次作业的实现过程中,由于对OO思想的不熟练和对可拓展性的理解程度较差,重构了两次,每一次作业都有一种全新的认识。

第一次作业的整体思路应该为将各个项等部分进行单独的封装,尽可能调用已经封装好的方法,降低各个类之间的耦合度。在第一次作业中,由于只有x这一种存在,因此我只实现了MainClass和关于多项式的类,这也就导致了可拓展性极差。因此第二次作业直接选择了重构。

在第二次作业的实现中,虽然将各个对象相互独立出来单独处理,有了OO思想的原型,但是仍然有着可拓展性差,类之间耦合度高,方法依赖于具体的类等问题。而且第二次作业花费了大量的时间对性能进行了优化(虽然写出来了bug...),在没有掌握面向对象的方法的情况下,对项目整体的把控能力远远不足,导致了项目逻辑最后完全纠缠在一起,理不清。

第三次作业对第二次作业又进行了重构,并且有较好的效果。但是最终还有有着较大的问题,包括类之间数据流动依赖于具体的类,类的组织形式仍然存在问题等。如果对第一单元继续进行内容的拓展,仍然存在较大的迭代困难,可能仍然需要进行部分重构。

第二单元

第二单元的主要内容为电梯调度算法。本单元我觉得很大程度上是提升了自己的面对多线程编程的能力,在架构的设计上做的还不错。不过也还是学到了不少架构上的知识。

在本单元中,我进行了一次重构。重构不是因为架构设计出现了问题,而是因为将分配式改为了竞争式。

在本单元中,我认为我学习到的很重要的一点是不要过度设计。在第一次作业中,我提前思考了后续单元可能实现的内容,并且做好了充分的设计(基本上是按照后面的设计走的),导致了设计复杂度相当高,而且相对于第一次作业的性能要求来说,性能效果远远不行(单电梯不用分配肯定比分配快),而且最后时间并不是十分充裕,为了不产生bug删除了一块未做测试的代码(提升性能的部分),导致了整体的性能远远不行。

除此之外,在本单元中提升的架构能力仍然与上单元中提到的能力类似,不过这次是潜移默化的提升,而不是像第一单元一样的跳跃式上升了。

第三单元

我觉得第三单元教给我最多的便是“规格“与”规范“。本身第三单元的难度不是很高,架构上带来的压力不是很大。理解规格和规范并自我约束是保证本单元代码质量的一大重点。在本单元中,我还在研讨课上做了“面向接口编程“的分享。也正是在这次作业和分享中,我在规格的方面有了很大的收获。

第四单元

第四单元的架构设计相较于第一单元和第二单元的设计就相对简单。基本思路就是架构按照UML的组织结构实现,如果某个部分内容极少,则直接耦合在已经实现的内容里。如果某个部分在需求拓展后增加了较多的内容,则设计新的类对原有的部分进行替换。

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

整体上来说,为了保证代码的正确性,需要使用的方法是随机生成数据的验证,自己手搓数据的验证,还有用眼看(当然主要是后两个单元了)。

第一单元

在第一单元的学习中,我其实对于测试的重视程度不是很高。主要精力放在了性能的优化上,导致了程序的正确性存在部分问题。

在第一单元中,我主要采用的验证的方式是自己手造一部分数据来检验,这一部分数据主要包括了简单的各种大面情况,各种能想到的边角情况以及可能导致程序超时的数据点。

第二单元

第二单元对于测试的重视程度有了很大程度的提升。在本单元中出现了一次较为严重的bug,在这次之后,我略微降低了对于程序性能的追求。本单元验证的方式包括了第一次自己手搓了一个评测机(保证能通过参数的调整生成各种数据类型)。此外,还对原代码各个线程的运行速度进行了调整,略微提高了随机生成数据的覆盖程度。此外,本单元同样注意了自己手搓数据,包括了极端数据和大面数据等。数据的强度和覆盖面相较于上单元有了很明显的改善。

第三单元

第三单元的测试方法主要使用了随机数据对拍和手造样例的方式。随机数据的生成仍然保证了有较多的类型,能够覆盖最基本的类型,保证大体上功能不会出问题。此外,还使用了Junit进行了单元测试,使用了构造的对应样例。除此之外,构造样例的时候,还设计了整体的样例和可能导致TLE的特殊样例。

第四单元

因为期末时间问题,第四单元做的测试较少。只是构造了对应的样例进行基础内容的测试,对于边界条件的测试。时间问题主要通过时间复杂度的控制来保证,并未做专门的测试。边界条件的测试也主要侧重了循环继承的各种情况等。

课程收获

面向对象课程虽然难度很大,但是给我带来的提升也是显而易见的。包括层次化抽象能力,多线程思维,规格化约束思维,程序建模设计思维等方面都得到了卓有成效的提升。具体来说的话主要有以下几个收获:

  1. 对项目的整体控制能力得到了有效的提升。包括对于项目要求的分析与认识,对于整体架构的选择与设计,对于设计的抽象能力,对于各个抽象层次与抽象对象之间的解耦合能力与可拓展化能力,以及最后的代码实现能力和测试能力,都得到了全方位的提升。
  2. 对自主学习,自主探索能力的提升。在面向对象课程进行的过程中,我们往往需要自己去查阅对应的资料,自己学习,凭借从各个地方得到的学习内容,最终完成对于某个知识点的学习,并且完成任务。
  3. 编程的规格意识,规范意识的提升。就从最简单的checkStyle来说,在对代码风格进行了约束之后,自己写代码的逻辑和表达的方式也得到了很大的改善(事实上也将该代码风格运用到了如操作系统等课程中)。

……

感觉面向对象课程给我们带来的最大的改变还是潜移默化的影响。我认为在将来的代码生涯中,这种在思想与习惯的方面的影响将会逐渐显现,并给我们带来更大的好处。

三个具体改进建议

  1. 对于课上实验的相关建议。在课上的实验部分,希望略微增加需要自己完成的内容,同时也希望能够在实验结束之后提供评测的结果或者分数。
  2. 对于博客作业相关方面的改进。目前的博客单元作业存在的很大的问题是同学们没有意识到博客的重要性,而且也对怎么写博客没有头绪,希望能够增加类似于学生互评之类的环节,也希望老师或者同学能够给与一定的指导。
  3. 关于研讨课的建议。目前研讨课存在的很大的一个问题是同学之间的互动明显不足,而且在分享的过程中大家对内容的关注度明显不高。希望能通过讨论或者其他的方式改进,提高研讨课的效果。
posted @ 2021-06-26 20:28  RE_REG  阅读(47)  评论(0)    收藏  举报