BUAA 2022 OO 第四单元总结报告暨课程总结

一、第四单元作业架构设计

本单元中,由于第十三次作业没有进行层次化的设计,所以这一单元我没有建立层次化的架构,而是直接将所有的元素分门别类储存在不同的HashMap中,当需要使用时再进行遍历。对比其他同学层次化的架构,我觉得自己的架构设计地不是很清晰,但是也能用,因为我们给出的Uml Model的规模并不大,即使每次每条指令都需要重新遍历也并不会太消耗时间,所以在小规模下还是可行的。

而在第十四、第十五词作业中,由于需要使用到图的相关算法,所以创建了几个工具类用于实现dfs、bfs算法,创建了一些类来储存图的元素。

整体架构如下图所示:

 

下面介绍每次一作业的设计和迭代:

第十三次作业:

第十三次作业一开始没有分层次来储存各个元素,直接一个MyImplementation类干到底。因为这一次作业比较简单而且规模比较小,所以就也没有出现问题。

感觉没有出现错误的原因是,这次作业写的比较简单而且我代码写得比较清晰,对于复杂方法实现时一些可以划分的步骤划分了好几个private的方法去实现,代码写的比较有层次。

第十四次作业:

由于又新增了两类Uml图,所以MyImplementation只是作为调用各个MyUmlClassModule、MyUmlCollaboration、MyUmlStateChart中方法的一个类,将具体实现分别放置在后面的三个类中实现。

对于一些涉及到图论中算法的方法,比如MyUmlStateChart中getStateIsCriticalPoint()方法,这个方法还是有些复杂的,我就新建了Mystate类来储存每一个状态节点中需要的信息,以及FinalStateSet来储存所有终点,之后在MyUmlStateChart中实现了dfs,用于遍历节点,思路就是先遍历一遍,如果本来就走不到FinalState就return false,如果可以走到FinalState就删去查询的节点再遍历一遍,如果能到FinalState就return false,反之return true。

第十三次作业:

这次作业没有改动原有的架构,仅仅是在原有架构基础上,因为要实现MyStandardPreCheck中的一些功能,其中也有一些和图论相关的check,所以就新建了DfsCheck类和BfsCheck类。

对于两个比较复杂的方法:检查重复继承和循环继承

循环继承

  • 用DfsCheck去判断有没有成环,维护一个visited队列储存当前路径上所有遍历的节点,如果新加入的节点u在visited中存在,那么u以及visited中u以后的节点都是继承环上的节点。

重复继承

  • BfsCheck去遍历,维护一个geneIds队列记录所有已经遍历到的点的id,如果有重复的则表示有重复继承,

  • 同时做了一个小小的优化,每个点有一个boolean类型的变量表示该点是否重复继承,如果点a继承到了有重复继承现象的点b,那么点a也一定会重复继承,就不用继续bfs遍历了。

二、四个单元中架构设计思维以及OO方法理解的演进

OO这门课是一门注重实战的课程,虽然每周在理论课上都学习了很多有关OO的思维和方法,但是真正在每一次作业完成的过程中才能体会到OO方法和架构设计的思维。

第一次单元作业

第一次作业由于是初次接触,虽然做过了pre,但是仍然感觉第一次作业无从下手,后来经过了课上实验,学习到了experiment和training中的架构,才慢慢形成了对于表达式储存架构的理解,因为表达式本身就有层次,从最底层的因子到项到表达式,然后表达式又可以作为因子形成嵌套的层次。慢慢理解了OO设计的精妙就在于把每一种数据和其对应的方法设计成一个类,构成面向对象的模式,同时不同类之间还有层次结构。回顾过去的这四个单元的作业,仍然感觉第一单元的作业是最难的,比第二单元还要难一些。

第二单元作业

第二单元主要涉及到对于多线程的理解和运用,多线程的基础就是需要学会使用锁控制并发线程的互斥。通过第一单元的训练,我逐渐掌握了设计架构的思路,从问题涉及的主要对象出发进行类的设计,这一单元我觉得架构十分清晰,主要使用了producer-consumer模式来控制输入,新建了一个schedule类来进行request的分发,同时每一个elevator作为一个类,而策略strategy可以设计成一个接口,不同的策略可以继承strategy接口,因为横向运行和纵向运行我是用的不同的策略。

第三单元作业

第三单元作业主要是体会了jml语言的规范性和可靠性,对于整体的设计并不需要我们自己去实现太多,为了减少一些重类的代码行数,可能需要额外分离出来一些工具类,比如单独新建一个类实现prem、kruskal算法。通过这一单元的学习,我进一步体会到了规格描述语言在一些需要高可靠性的大规模项目中的重要性,通过限定前置、后置条件和副作用,我们才能在具体代码中正确地实现目标功能。

第四单元作业

第四单元作业是对Uml图的建模和分析。这一单元主要是在完成作业的过程中进一步对Uml图加深了理解,理解了Uml图的层次结构和一些线的用法,比如继承、关联、实现,其实之前三个单元虽然都画过Uml图,但是从最后一个单元的学习来看,之前画的Uml图很多都是不完善的,甚至是有很大错误的,警示我们以后画Uml图的时候要严格注意Uml图的标准和规范。

总之,对于类的设计和划分感觉是OO中的重点,不同于以往的面向过程编程,面向过程是按照一个任务执行的步骤划分不同的函数,而OO则是先把任务中涉及到的数据和方法分类,将联系紧密的数据和方法设计成一个类,通过类之间的相互作用完成一个任务。由此,感觉OO更适合复杂度比较高的、代码量比较大的项目,可以有效降低项目的复杂度,架构一旦定型,每个类只要管好自己的事就可以了。

三、四个单元测试的理解与实践

第一单元:由于第一单元只debug、完成作业就花费了大量的时间,所以没有搭建自动测试程序,仅仅通过手工制造了一些数据进行测试,这也导致了在一次作业中由于测试并不充分而造成了较大的失误。

第二单元:第二单元第一次作业没有测试出来超载的情况而导致第一次作业爆炸,后面测试主要是通过和同学们的程序进行对拍,保住了二三次作业的分数。

第三单元:第三单元主要学习了一下Junit的测试方法,可以辅助编写一些测试程序来对每一个方法进行测试,确实比较方便一些

第四单元:第四单元手工制作一些Uml图借助官方包进行测试。

总之,经过OO课的学习,越发意识到测试的重要性,写代码不是写完就完事了,其实是6分写4分测,如果测试做的好,能在很大程度上减少一些不必要的小错误而导致的程序的bug。

四、课程收获

  • 增强了设计意识,以前写代码就是拿过题目来直接稍微分析就开干。但是对于复杂的需求,大规模的项目,需要迭代的project来说,设计是很关键的,感觉每一单元从分析需求、到设计架构都必须占用相当一部分时间。否则前期架构不合理,后期重构是非常浪费时间的,也会增加出错的概率。同时,一个好的架构,应该具备良好的可扩展性,对于后期迭代也很方便。

  • 意识到了测试的重要意义,以前不好的习惯就是不太喜欢做测试,感觉写代码是一件很爽的事,但是测试就不那么爽快,忽视了自查bug的能力,由此在一些作业的强测上吃了不少的亏。噫嘘唏,于是重视起测试的重要意义,如果有时间,还是尽量多做测试,尤其是刚刚写完程序,可以在需求的范围内,做一些简单的边界数据测试,以免因为没有理解到位需求而犯一些低级错误。当然为了数据的覆盖率还是写一下评测机比较好,尤其是手搓大规模数据不太现实。当然评测机也是自己写的,如果需求没有理解到位,可能也不能保证能覆盖到边界数据。

  • 掌握了多线程设计的基本思路和方法。OO研讨课我分享过一期关于多线程设计模式的内容,由此也多了解了一些有关OO多线程设计模式的内容。感觉其实多线程看起来复杂,其实基本功就是要熟练地运用锁的机制、wait-notify机制处理线程的并发。至于很多花里胡哨的设计模式,我们只需要用到的时候再去了解运用也是可以的。

  • 增强了dug能力和心态。面对一个复杂的工程,有时候一个小小的bug就得改半天,第一单元有一次一个bug找了2天没找出来,最后在助教帮助下才得以解决。

  • 代码风格也很重要,清晰简洁的代码可以提高程序的正确性。其实,代码写得清晰很多时候可以减少很多不必要的小失误,同时代码清晰也会让思路更加清晰。

五、改进建议

  • pre里面稍微加一点关于第一单元的内容,感觉虽然做过了pre,初次接触第一单元还是难度颇大。

  • 可以加一节讲测试的课,因为感觉测试很重要,但是从来没有在理论课上系统地讲。

  • 多线程可以多开一些实验课介绍一下别的设计模式,感觉会比较有趣。

posted @ 2022-06-28 00:40  Sainthousand  阅读(31)  评论(1编辑  收藏  举报