OO2022第四单元作业总结
OO第四单元课程总结
前言
本次内容主要是对第四单元和整个OO课程的总结,主要内容有总结本单元作业的架构设计,总结自己在四个单元中架构设计思维及OO方法理解的演进,总结自己在四个单元中测试理解与实践的演进,总结自己的课程收获,最后立足于自己的体会给课程提三个具体的改进建议。如有错误,谢谢指正!
1.1 本单元架构设计
1.1.1 第一次作业——类图
之前每次作业总结博客都会用UML类图描述程序,这次作业要自己来实现一个UML类图的功能,因为是第一次作业,所以只要实现对类图的元素信息提取,功能也比较简单,主要考察的就是对类图的理解,包括UmlClass,UmlInterFace,UmlAttribute,UmlOperation,UmlParameter等等类图元素的理解,其实本次作业的难点在于,利用面向对象的方法对类图元素进行解析,重点在于熟悉UML类图中各个元素之间的关系,其他的代码编写难度并不高。
要实现各种查询指令,必须先把UML类图这棵“树”建立起来,首先在构造函数里一个一个元素地识别并存储。这里我遍历了三遍,这是为了保证不出现空指针,一层一层利用面向对象的方法对类图进行解析,因此我的设计是分三遍识别:
-
第一遍UMLClass,UMLInterface,和UMLAssociationEnd,将每个类的name与id建立name2Id映射,方便之后解析查询指令中传入的name;id与类建立class映射,因为id是唯一的;此外建立双重HashMap表即HashMap<name,HashMap<id,MyUmlClass>>,用于之后识别重复类。
-
第二遍UMLAttribute,UMLOperation,UMLAssociation,UMLInterfaceRealization,UMLGeneralization,这些信息都直接存入MyClass类中。
- 最后一遍UMLParameter,这是因为parameter-operation-class是一层层依赖的。这样可以保证每个元素所依赖的上一层元素都比自己先识别。
作为类图中是最主要的元素,为了将UMLClass和它相关的属性、方法、关联关系、继承关系和实现关系等元素与类本身联系起来,我建立了一个MyClass类,在UMLClass的基础上,将它的各种关系都记录在里面,方便查询。同时我以同样的方法将MyInterFace和他相关联的Umloperation等也关联并封装了起来。
1.1.2 第二次作业:UML顺序图的查询、UML状态图的查询
和上一次不同,由于在Myimplementation里面实现所有的代码会造成代码过长,因此我在本次作业中将类图,顺序图,状态图分别建立三个大类,在三个大类中实现各自图的对应操作,MyImplementation只需要调用三个大类里面的方法即可。
我针对状态图建立了MyStateGraph和MyStatus,Mytransition三个类,跟类图分析的模式一样,在Mystatus中封装更多与status相关的类,来实现树的构建,比如transitions等等,Mytransition里封装Umlevent等。
针对顺序图建立了MyinteractGraph和MyLifeLine两个类,这两个类比较简单,我在MyLifeLine中封装了相关lost、found类型消息的个数,方便直接查询,同时封装了create这个生命线的MyLifeLine,同样是方便直接查询。
这次的指令实现起来都比较简单,唯一一个比较难的是判断一个状态是否是关键状态,我采用的方法是DFS,从起始状态出发,屏蔽掉我们需要判断的这个点,如果DFS的最终结果包含至少一个最终状态,那么这个点就不是关键状态。
有一点需要注意的是:如果状态机模型本来就无法从 Initial State 到达任意一个 Final State(包括 Final State 不存在的情况),则该状态机中所有状态都不是关键状态;
这一点我一开始没有注意到,和伙伴对拍的时候才发现这个问题,这告诉我们本单元认真阅读指导书的重要性。
1.1.3 第三次作业:UML的有效性检验。
第三次作业主要是学习了UML图中的错误情况判断,基本不需要再构建新的类。本次作业要求我们实现9个错误的判断,我认为比较难的是以下三个
- 循环继承的判断,这个是实现起来有一定难度,需要利用图DFS来解决,即利用DFS来判断有向图是否存在环。
- 重复继承的判断,我是用递归的方式,将每个类或接口无论是直接继承或间接继承的类或接口全部记录下来,判断的时候只要判断有无重复即可。
- R002错误判断,
针对类图中的类(UMLClass),其成员属性(UMLAttribute)和关联的另一端所连接的 UMLAssociationEnd 这两者构成的整体中,不能有重名的成员
,这个主要是理解有困难,问了助教和同学才最终理解。
最后是本单元的类图,可以看到层层梳理下来,逻辑还是很清晰的。
1.2 总结自己在四个单元中架构设计思维及OO方法理解的演进
1.2.1 Unit1
本单元实现的是一个多项式化简的问题,我认为这一单元是最难的一单元,难在第一次面对OOP的编程,即使做了Pre,还是有一种不知所措,无从下手的压力感。我在本单元第一次切身体会到了面向对象这种语言逻辑,也体会到了递归下降解析的魅力。本单元最大的难点在于,利用面向对象的思想,架构出多项式本身的层层结构,比如最顶层是表达式,下来是项,再下来是因子,再下来是元素,变量等,我构造了Expression,Term,Factor等类。其实只要架构好,本单元的迭代其实很简单,在做本单元作业之前一定要在纸上大致架构好要实现哪些类,要把表达式分成哪些层。这一单元主要锻炼的是同学们面向对象的思想。
1.2.2 Unit2
这次我认为是第二难的一次作业,因为针对于线程的编程还是头一次。线程的debug过程非常困难,所以与其一点点debug,不如在写代码的过程中理清思路,注重细节。这次作业主要学习了同步和互斥访问,预防线程死锁以及线程的wait,sleep,notify和notifyall。进一步了解了线程的工作原理和锁的配置,而且更注重于类与类之间的信息传递与配合。这一单元锻炼的是线程和线程安全的知识。
1.2.3 Unit3
这一单元主要是是针对JML的理解,但实际解决的是图论问题。这一单元主要是每次需求的扩充,到这里的时候我几乎不需要重构了,这是很大的一个进步,在每次写代码时都考虑一下以后的需求增加。这次还学习了Junit自动检测。这一单元只要细致阅读JML,基本不会出什么Bug问题,因为毕竟JML是一套标准的规格。
1.2.4 Unit4
这一单元解析UML图。这次是针对主要的几个元素建立了单独的类,其他元素加入到这些类中当作属性。这次写起来就很顺手了,各个功能分配到不同的类中完成,最后在总合起来,思路很清晰,架构也比较直观。本单元重点在于对于UML类图,顺序图,状态图的一些元素要了如指掌,条理清晰,代码的编写基本还是第一单元面向对象,层层解构的思想,难度不大。
1.3 总结自己在四个单元中测试理解与实践的演进
关于测试,我在第一单元没有自己写测评机,导致强测出现了Bug,互测也出现了好几次Bug,现在回头想来可能也是当时因为时间太紧了,光编写代码就用好长时间,没有编写评测机的时间。但是看到一些同学编写完评测机后真的是事半功倍,互测的时候直接开着评测机就把Bug自动Hack到了,同时自己课下测试的时候也可以自动化测试,不用自己死盯着电脑屏幕,因此我在第二单元之后编写了自己的评测机,事实证明编写了评测机之后,无论是强测还是互测,至少正确性相关的问题我没有再出现,其他的问题更多的是性能的问题。
二单元难度也很大,线程、线程安全的知识都是第一次接触,在测试的时候采用测评机和手动数据结合的方式,比如针对某个到达模式输入一些***钻的数据,测试电梯调度,调头等问题,但感觉除了非常明显的死锁,偶发的死锁应该还是需要大量随机数据的轰炸。这一单元我用自己的评测机找出了自己的Bug,同样也自动Hack到了别人的Bug,自动评测机yyds!
三单元主要采用测评机验证正确性,读代码查时间复杂度的方式,当然也用了JUnit等工具链进行测试(虽然依旧觉得没啥用),还面向某部分指令写了专门的数据生成。这一单元起数据生成不再是纯随机的,不然测到的绝大部分都是抛出来的异常。数据生成时,我才用先加入大量person,关系relation,group等元素,再进行随机大量的查询指令轰炸,这样起到的效果也不错,也能很好的找到一些Bug。
四单元依旧测评机,本单元只需要在三单元的基础上对数据生成做修改,其余均可保留原样,方法仍是在生成器里建起图,在图里随机用结点。同时本单元我也自己用starUML手绘了一些针对性更强的类图,状态图和顺序图。
1.4 课程收获
一路走来,本学期的OO课程也告一段落,这一学期充满了欢乐,也不乏很多痛苦,但正是这些困难和挫折才让回忆更有力量。在面对OO第一单元的第一次作业时,尽管做了Pre,但是还是一脸懵逼,面对多项式的化简,脑子里最多的问题就是,指导书这里是啥意思?指导书读不明白啊?这该怎么实现?这该怎么架构?好难!记得当时指导书都整整读了两天,开始架构代码的时候生怕ddl前交不上去,熬夜写代码。我觉得第一单元的第一次作业是最痛苦的,绞尽脑汁的想架构,第一次转变为面向对象的逻辑编写代码,这对我来说都是挑战。
这可能就是万事开头难吧,在后来的作业中,我渐渐对面向对象的思想熟能生巧,在写第二单元、第四单元的时候,习惯性的就会对整体架构进行层层分析与解构,一层一层的实现具体功能,不知不觉面向对象的思想已经在第一单元刻入我的脑海。
总而言之,在这学期的OO课程中,我学到了许多知识,包括UML,JML,线程,线程安全,Java的各种语法,Java的语言风格,Junit测试,python自动评测机的编写等等。
当然课程中收获的最重要的还是面向对象的思想,在一次次实践中学会了如何进行抽象,我们操作的不是一个具体的类,而是抽象出来的接口,继承和实现像是一条线索贯穿了OO的始终,灵活运用可以使代码更加简洁优雅。
1.5 给课程提三个具体的改进建议
- 课程网站的讨论区能否设置成带评论回复功能的?翻起来太麻烦了,就比如第四单元第15次作业的讨论区,由于问题太多,问题和回复往往隔了好多条问题,只能通过@符号来判断助教回答的是哪个问题,实在是太不方便了。在评论里设置回复功能,直接点开评论就可以看到助教的解答不是更好吗?
- 在JML单元,如果这个单元主要内容是让大家学会JML的阅读和理解的话,我觉得可能不需要三次作业,1~2次作业我觉得已经足够,第三次作业的话感觉就是在学习写更多的算法,其中JML的东西还是第1,2次作业那些东西,没有学到什么新的JML的知识,感觉没有必要。可以把第三次作业设计成其他JML相关的内容。
- 最重要的是关于互测的问题。
- 建议把房间数增多,每个房间分配3~4个人即可,因为我觉得互测的本质目的是为了让同学们学习别人的代码,而不是下载下来代码拿自己写的评测机来Hack别人。如果房间人数7~8人的话,就我的想法而言,我第一感觉就是:7、8份代码好多啊,我读代码找到Bug的概率好低,我还是用评测机自动Hack吧,让评测机自己评测,我去干其他的事。如果代码份数少一点的话,我觉得至少有阅读代码的动力。
- 第二,感觉目前的互测还是偏离了“让同学们学习其他同学代码”的初衷,而是一味地追求Hack别人加分。我认为可以把互测的内容增加一些,除了找他人的Bug,还可以给同房间的同学互相提出设计优化建议,总结互相学习到的代码或者架构方面的知识,这样会不会更符合初衷一点呢?