BUAA OO 第四单元总结

BUAA OO 第四单元总结

写在前面

完结撒花!

本单元是OO课程的最后一个单元,博客内容主要为UML相关内容、本单元作业架构、以往作业回顾整理以及整个OO课程的总结。总的来说,虽然是很辛苦的一门课程,但收获也真的很多。

第四单元作业架构设计

总体架构

本单元采取迭代开发,三次作业对于类图基本信息的解析思路完全一样,都是牺牲了空间来换取性能,主要设计分为以下两点。

  • 元素储存:在输入时将每一个元素按照类型分开储存,然后在后续的解析中按顺序处理。分类型进行储存的原因是,这样做可以避免因元素输入顺序问题带来的反复遍历(如UmlGeneralization对象对应的UmlClass对象输入较晚,故一次遍历时无法解析等);而且在后续操作中可以方便地取出所需要的不同元素。

    值得一提的是:笔者储存UmlClassUmlInterface等表示对象的类时用了两个容器,一个对应Name,一个对应自身id,方便重名报错;而对于UmlAttribute等表示对象的属性的类,笔者用了其ParentId来进行对应,方便后续的查找操作;最后对于UmlGeneralization这种表示关系的类,笔者在解析中直接将其表示的意义添加到对应的类中,所以只是储存,在后续查询中没有用到。

  • 解析操作:由于类对象所含信息过于复杂,所以新建了类似MyClassMyInterface等类,用来表示类对象的id等自身信息和父子类、关联类以及实现的接口等的关系信息,方便后续的查询和检查操作;还有类似MyRegion等内部只用来存储转换状态等关联信息的类,用来简化后续的关系查询工作。

第一次作业

由于将每个对象信息都储存了起来,所以大部分指令按照所给要求之间进行查询就可轻松解决。唯一用到算法的地方可能就是查询*父类时用到的dfsbfs算法了,总的来说难度不大。但是需要尤其注意的地方是,尽量把每个函数的主体内容放到对应的类下,不然可能会超过500行导致CheckStyle报错(不是我,我没有)

第二次作业

第二次作业加入了对状态图和顺序图的查找,由于很好的储存方式所以对代码的要求并不大,主要难在对于UML结构的理解,即清楚不同类之间的Parent指的是谁、Reference是谁、sourcetarget又是什么意思。笔者前期工作的难点主要就是不知道该用哪类对象的哪个函数,以致于无从下手,后来笔者仔细阅读了所给代码和第四次训练中的例题,理解各类之间的关系后很快就写出来了。

第三次作业

第三次作业涉及到了对于规格检查,难度较大,因为涉及到的内容错综复杂,且大部分涉及到了继承的问题,思路稍有断层便前功尽弃。笔者的主体思路是使用递归和dfs算法,依旧还是用空间来换取时间,即在进行解析的时候就对所有的类和接口进行处理,用HashMap建立一种从类和接口查询到其所有继承的父类和实现的接口的关系,在后面规格检查的时候直接遍历对应的容器内容,即可完成最难的2、3和4格式检查,正确性乐观(虽然时间复杂度不太乐观)

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

第一单元

第一单元是表达式的求导问题,主要运用的思想是递归下降。由于当时对Java的语法不熟悉,加上没有体会到面向对象思想的好处,导致每一次作业基本上都与以往毫无关系,自己新建的类也只是为了应付CheckStyle的行数要求而写的函数集合体,老师讲到的设计模式更是用都没有用过。在经历了重构的三周后,终于体会到了面向对象思想的好处(哭唧唧)。

第二单元

第二单元是多线程电梯问题,主要涉及到的是多线程的相关操作,相关架构设计也是围绕着电梯调度(如电梯扫描算法啦、*竞争算法啦)和同步锁的设置。并且,由于第一单元繁忙地重构,笔者在本单元作业中重点思考了代码整体的架构,使用到了工厂模式等设计模式,真正按照对象来划分代码中的类,使得三次的作业每一次都是在前一次作业的对应类中进行少量优化就可。

有一说一,笔者的代码编写能力和架构设计思维在第二单元的作业中有了质的飞跃,此后单元的作业都是只在第一次作业的基础上修改,感觉确实从面向过程编程转变了过来(才不是孩子重构怕了)

第三单元

第三单元是JML规格的相关问题,主要考察对于JML规格的理解和算法性能的内容。在本单元可谓是让笔者对面向对象思想的理解有极大的提升,并不像第二单元只是简单地按对象的类型进行分类,通过阅读所给代码,明白了用这种设计模式时可以将每一个小函数都抽离出来,单独完成对其的实现,而且即使出现了问题,也不会影响到项目的大部分功能,还可以根据错误信息快速找到对应的代码,可以说是极大地降低了复杂项目的工作量。

第四单元

第四单元是UML图的解析问题,主要考察对于UML规格的理解和对储存信息容器的维护。繁杂的信息量和关联关系让笔者再次深刻理解到了面向对象的思维方法是按照对象的类型和性质进行划分,而不是对不同的任务进行划分。

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

第一单元和第二单元

在前两个单元中,因为第一次侧重正确性和化简后的长度,而第二次则是侧重时间长短,所以笔者只是用了简单的手写数据来检测正确性,用随机生成的无意义数据来检测性能分,结果经常因为笔者考虑不周而导致强测和互测bug频发。

第三单元

第三单元笔者学聪明了,测试数据多是根据自己对题目的理解而做的边缘数据,其次加上大量数据来和同学进行对拍进行测试,这样做正确率倒是有很大提升。但渐渐发现,在全写完代码后进行测试,出现bug后一检查发现往往是一层一层的bug叠加出了错误的结果,修改起来过于繁琐,还容易导致新的问题。

第四单元

在最后一个单元笔者终于发现了单元测试的好处,写一点查一点,极大地便利了debug的过程。笔者亲身经历:在最后一次作业中,笔者的R004检查出现了问题,且在R004中用到了R002R003的相关内容,假设笔者没有用单元测试,三个最复杂的函数一起检查想想就头疼的不行(笔者窃喜)

综上,笔者最终的测试是在编写代码的过程中进行的,每完成一点小内容后就依靠自己对题目的理解来制造边缘数据进行测试,无误后再开始接下来的工作。这样到整体代码完成后,只需要用大量的随机数据来检测性能即可,极大缩减了测试的工作量。

三个具体改进建议

  • 建议课程组可以对每次的上机题目给出反馈,不然感觉好像每次都是去签到,随便写一写交上去,是不是对的也不知道,如果错了应该怎么改也不知道。
  • 希望可以增多研讨课的次数,感觉在研讨课上听听别的同学的分享对自己的代码编写有很大的帮助,尤其是在毫无思路无从下手的时候。
  • 希望在第一单元中就加入不能用同一错误hack过多次的限制,不然的话,狼人只要找到一个bug,就能通过反复提交获得较多的分数,可能会导致狼人的分数过于不平衡,笔者在第一单元就被别人用同一组数据(每次只是改个数字)攻击了好几十次。

课程收获

OO课程真的很辛苦,但坚持下来后收获真的很多。

现在回想起我在一天从对Java零基础到写完整个Pre3和第一次作业,仍然有一股莫名的心悸...(那一天,笔者终于回想起了被OO支配的恐惧)。那一天也像是我这学期OO课程的缩影,忙碌但也收获满满。虽然学会编写Java程序、做代码测试、Markdown和写博客等一些事情非常重要,但在我心中,最重要的是学会了面向对象的思维方式。OO于我不仅仅一种编写代码的方式,更像是一种思维方式:OO让我明白了面对问题时应该如何分析,应该如何拆分,应该如何封装,又应该如何进行测试,可以说是让我整个人的代码风格和思维方式都受到了巨大的转变。

感谢课程中的每一个人

最后的话,感谢老师们的悉心教导,感谢助教们的辛勤付出,也感谢身边同学们的热情无私的分享。真的很开心也很庆幸自己能够经历OO课程的一切。

希望咱们的OO课程可以越来越好!

上一篇:清华操作系统实验ucore_lab3


下一篇:Android Studio打开Android源码工程