2020北航OO第四单元总结
一、本单元架构设计
本单元作业是实现一个UML图解析器,其中实现接口及主要框架课程组已经提供,只需要我们完成特定功能。
在第一次作业时,感到十分迷茫,不知道如何下手,最后在重新学习了类图的mdj文件的各项含义及内在关系后,我选择设置一个umlTree
类进行UML的解析,然后存入自己写的MyUmlClass
和MyUmlInterface
中,使其根据原有的UmlClass
和UmlInterface
构造,在其中实现operations
、attributes
、associations
、parent
等属性,自己写MyUmlOperation
,实现attributes
、parameters
属性,这样存储完整个类图,再进行各项的查询时,实现起来还是比较简单的。
在第二次作业时,增加了状态图和顺序图两种,吸取上一个单元的教训,我并没有在原有类上进行添加,而是选择创建新的类MyUmlGeneralInteraction
,使其继承自原有的MyUmlClassModelInteraction
,并且构建新的解析类UmlTree2
,在里面进行状态图和顺序图涉及到的元素的解析,同样地,存入自己写的MyUmlInteration
和MyUmlStateMachine
中,在顺序图类中实现lifelines
、messages
等,在状态图类中实现pseudostate
、finalState
、transitions
等。虽然顺序图和状态图本身元素之间的关系十分复杂,但本次作业只涉及到一些十分简单的查询,所以我也只解析了本次作业用到的元素及其关系,有了第一次的基础,可以说是比较简单的。
在第三次作业时,增加了一个总的检查功能,涉及到了三种图,所以我在继承了第二次作业的MyUmlStateAndCollaboration
(给第二次作业的查询类改了名字)后,在其中继承了umlTree1
和umlTree2
两个属性,利用这两个存储解析单元进行规格查询。在本次作业的实现过程中,出现了许多问题,比如R002和R003,一个是循环继承,一个是重复继承,前者找到环即可退出,后者找到重复才能退出,这样我就不得不实现多个查询继承类/接口的方法,但这些方法又有大量重复部分,略显冗余感,我觉得这是一个可以改进的地方。总之,这次作业较前两次作业耗时较多(一部分是由于没有很好理解题意),过程也略显复杂,并没有像我想的利用已知方法和属性即可完成。
在本单元三次作业过程中,我想达到一种类与类之间耦合性较低的效果,所以将大多查询操作放在元素类里面实现,这样,在实现一个查询操作时,往往需要从MyUmlGeneralInteraction
转到UmlTree
再转到具体的类去实现,过程有些长,但类与类间耦合度确实变低了,这种实现方法让我感觉不是很舒服,觉得这是一个可以优化的地方。另外,由于本单元的实现并没有重构过程,而是类的增加,所以仅贴上最后一次UML图。
二、单元架构设计及OO方法理解演进
第一个单元是多项式求导,需要将解析、多项式存储及求导、输出分化成不同的类去实现,将不同类的因子抽象成不同的类,利用因子→项→多项式的继承关系,采用先分后合的思想,先分别处理各个因子,将其求导,最后再合在一起,利用同类项合并、公式等方法进行优化,这一单元,将我们一main到底的思想彻底改成了面向对象。
第二单元是多线程电梯,类似于生产者消费者模式,生产者是需求产生类,消费者是电梯,需要一个调度器类在中间充当托盘的作用, 将需求分配给电梯。调度器为单例类,电梯和需求类都以调度器类为锁,实现并发性。最后的优化也主要几种在调度策略中。
第三单元是根据JML规格实现图操作,在这一单元,我没有很好地理解课程组的意图,一直在一个类上进行方法的实现,没有将图更进一步抽象出来,最后,这一单元的收获是一系列的图算法。
第四单元是解析UML图并进行查询,主要是需要自己构建类进行UML图的存储,主要分成类图类、顺序图类及状态图类,对不同的图中的元素分别进行解析处理,在作业迭代过程中,实现查询类的继承。
三、单元测试理解与实践演进
在第一单元多项式求导中,我采用了先自己构造数据然后自动化测试的方式,由于bug都是出现在类似于(x*x)这种很奇怪的地方,导致自动化测试效果不是很好,没有测出来什么bug。
在第二单元多线程电梯中,我自己写了一些测试用例进行测试,最后设计上没有出现大问题,但有一些死锁的问题,主要原因在于我对加锁理解有些偏差,最后也成功改正过来了。
在第三单元JML中,我没有进行很好的测试,导致存在致命性bug,给了我一个很大教训。
在第四单元UML中,我通过starUML自动构建测试数据,主要对循环继承和重复继承进行测试,效果还可以,最后只死在了一个TLE上,是三单元中出现过的问题,这次没有注意。。
总之,感觉在测试过程中,只要自己先进行一定的合理性测试,就不会出现大bug,至于那些边缘化的特殊情况,自动化测试也很难检测到,但只要进行足够长时间的自动化测试,那么找到bug的概率会大大增加,其实,还是自己有技巧性地构造效果更好一些。
四、课程收获
上学期虽然上过Java课,但收获其实并不大,只是掌握了一些基本的java语言技巧,了解了继承、实现等,但在oo课伊始,仍给了我很大帮助。第一次作业虽然设置了Poly类,但后面仍然重构了,因为当时对OO课程设置不是很了解,扩展性思维不足,不过在第二次作业重构了之后,后面就没重构过了,我觉得我可扩展性设计的能力得到了很大提升。
关于面向对象的思维,虽然在前几次作业我已了解了一定的面向对象思维,知道将各个元素对象化,设置不同的类去处理他们,但在第二单元作业过程中,通过对Person的处理,我才更深一步理解了面向对象的好处,因为我一开始是用Hashmap嵌套的方式存储的乘客需求,这种隐式存储的方式可读性不高,而且不易扩展,最终在第三次作业时我被逼改成了用Person类存储,立刻感觉代码可读性提高了很多,而且操作更加便捷,至此,我才更加理解将一些元素封装成为对象的好处。
在第二单元中,通过一次又一次死锁,我对多线程、并发的编程技巧理解得更为透彻。
在二、三、四单元的迭代过程中,从一开始的不断地往一个类中增加东西,到通过继承的方法扩展类,我在开放封闭原则方面也获得了很大进步。
三到四单元,从给了我们架构让我们实现图的各种操作,到完全自己去建一个图去存储UML图,我学会了怎样合理方便地以面向对象的思维去解析并存储一个图,并且熟悉了图的一系列查询操作。
五、课程改进建议
-
希望JML单元中测能增加难度
-
希望实验课可以公布答案和成绩
-
希望理论课可以增加一些趣味性,很多时候感觉课程枯燥无味,让人抓不住重点,好多作业需要用的东西反而需要自学
六、线上学习体会
总的来说,这一学期的oo课程还是使我收获颇丰的,从面向对象设计→多线程→规格化设计→