OO第四单元总结及学期总结

OO第四单元总结及学期总结

第四单元三次作业架构设计

第十三次作业

需求分析

​ 本次作业需要实现一个UML类图分析器,根据传入的UML类图元素UmlElement建立模型、重建关系,并对询问指令作出应答。

​ 在本次作业中有七个类,MyClass类和MyInterface类实现了AllClass接口,并且采用了工厂模式,对于UmlElements的解析在ElementFactory中完成,MyOperationHashMap存储在MyClass类中,由该类进行管理,MyClassMyInterfaceHashMap存储在MyUmlInteraction类中,由该类进行管理,构成了一种层次化的设计。在查询时,MyUmlInteraction类询问MyClass类或MyInterfaceMyClass类询问MyOperation类。被询问对象储存在哪个类,由哪个类给出答案。

​ 对于多数询问,都设置了缓存,以本次作业中较复杂的CLASS_IMPLEMENT_INTERFACE_LIST classname为例,在MyClassMyInterface中增加allInterfaceList成员变量,初始时为空,在查询时,若allInterfaceList.size()==0,则调用其实现接口和所继承类的getInterfaceList(),在过程中,其父类、实现接口、接口的父类中的allInterfaceList成员变量全部进行缓存,在下次调用时allInterfaceList.size()>0,则return allInterfaceList

public HashMap<String, String> getInterfaceList() {
        if (allInterfaceList.size() > 0) {
            return allInteList;
        } else {
            for (MyInterface myInterface : interfaceList.values()) {
                allInterfaceList.putAll(myInterface.getInterfaceList());
                allInterfaceList.put(myInterface.getId(), myInterface.getName());
            }
            if (father != null) {
                allInterfaceList.putAll(father.getInterfaceList());
            }
            return allInterfaceList;
        }
    }

第十四次作业

需求分析

​ 在上次作业的基础上,增加对UML顺序图和UML状态图的解析,建立相应的模型,对相应的查询指令做出应答。

​ 本次作业在上次作业的基础上迭代开发,MyUmlGeneralnteraction作为最顶层类,调用MyStateChartInteractionMyCollaborationInteractionMyClassModeInteraction中的方法进行查询,MyClassModeInteraction即为上次作业中的MyUmlInteraction类。MyStateChartInteraction管理MyStateMachine类,调用其方法进行查询,MyFinalStateMyPseudostateMyState实现AllState接口,便于由MyStateMachine类进行统一管理,在询问时,被MyStateMachine类调用。顺序图部分,MyCollaborationInteraction管理MyInteractionMyInteraction管理MyLifeline,在查询时也是层层调用。

​ 解析元素依然在ElementFactory中完成,先加入UmlClassUmlInterfaceUmlStateMachineUmlInteraction,再加入UmlOperationUmlAttributeUmlInterfaceRealizationUmlAssociationUmlGeneralizationUmlRegionUmlLifeline,然后加入UmlParameterUmlStateUmlMessage,最后加入UmlTransition

​ 对本次较为复杂的查询指令SUBSEQUENT_STATE_COUNT statemachine_name statename 采用了广度优先遍历,并进行缓存。

第十五次作业

需求分析

​ 在前两次作业的基础上,对模型进行有效性检查,在发现有违背所给出的八条规则的模型时抛出异常。

​ 本次作业在前两次作业的基础上仅增加了一个类MyStandardPreCheck,由最顶层的MyUmlGeneralnteraction管理调用。MyStandardPreCheck调用MyStateChartInteractionMyClassModeInteraction的方法获取检查结果。对于查询指令没有改动。

​ 对于R005、R006直接在MyClassModeInteraction每次调用下层类准备add前进行判断。在MyClass中进行深度优先遍历,同时判断该类是否违背R002和R004,在MyInterface中进行深度优先遍历,同时判断该接口是否违背R002和R003,发现违背R002时即可停止遍历,对于R001,在MyClass中,addAttribute()addAssociation()时进行判断。R007、R008在MyStateMachine中每次addTransition()时判断。

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

第一单元

​ 第一单元的作业为多项式求导,第一次作业完全是面向过程的方式,导致许多方法复杂度都很高,在第二次作业时进行了重构,设计了抽象类TermSinTerm类、CosTerm类、VariableTerm类都继承了Term,并且将大正则表达式修改为层次化的表达式。第三次作业继续重构,五种因子VarFactorConstFactorExpFactorCosFactorSinFactor继承了抽象类Factor,并重写了父类的求导方法getDiff()、输出方法printFactor()以及equals()方法。整体层次上有三层Expression类(即表达式),Term类(即项),Factor类(即因子),层层调用。在求导的时候,增加了AddDiffMulDiff两个类,在两个类中有各自的求导规则,继承了抽象类Diff,也采取了工厂模式。

​ 在第一单元的作业中,算是从完全到面向过程,到开始试着使用继承、接口等,有了一些结构的设计,并且掌握了工厂模式。同时,通过本单元的作业了解了一个良好的结构的重要性,如果初始的结构混乱,之后必然是次次重构,优化也会难以下手。

第二单元

​ 在第二单元中学习了多线程,第五次作业中采用生产者-消费者模型,调度算法采取了Look算法,但将许多调度的设计放在了run()方法中,导致复杂度较高,也不利于扩展,第六、七次作业中采取Work Thread模式加Look算法。因为从本单元第一次作业开始即确定了设计模式和调度算法,所以在之后的几次作业对于之前代码的改动不多。对于第七次作业中加的换乘要求,也是若Request可直达则不换乘,若需要换乘则在一开始便决定好换乘楼层,修改RequestoutFloor为换乘楼层,新增一个Request加入Controller新增的用于存储新产生RequestArrayList,采用固定的换乘方案。

​ 第二单元困难的地方在于多线程,需要考虑线程安全的问题。在保证线程安全的前提下,为了应对check-then-act,部分锁加在了代码内部,而没能很好地设计一个线程安全的共享对象解决线程安全问题,导致许多方法都不够简洁。本单元的整体结构基于多线程设计模式,但局部一些结构仅仅保证了正确性和性能,可读性和可扩展性都不强,从本单元开始思考如何兼顾正确性、性能和架构的优雅。

第三单元

​ 第三单元是对于JML的学习,读JML规格写代码,但是如果照搬JML规格,会导致TLE,因此需要思考使用的容器、代码的算法以及动态维护。容器主要采用ArrayListHashMap结合,ArrayList用于遍历,HashMap用于查询。关于算法,在第九次作业中,isCircle()采用dfs的算法,第十次作业中,isCircle()的实现改为了并查集,用HashMap存储pre和rank,对于geConflictSum()getAgeMean()getAgeVar()等方法都采用了缓存机制,即在MyGroup类中addPerson()的时候就改变这些函数相应的成员变量。在第十一次作业中,由于isCircle()的实现采用并查集,queryBlockSum()只需设置成员变量blockSum,在addPerson()时加一,在addRelation()时,若find()函数结果相同则减一,queryMinPath()采用堆优化的dijkstra算法,利用优先队列实现堆,存储PersonEdgequeryStrongLinked()采用了Tarjian算法,记录了每个连通分量,判断连通分量中是否包含起始点和终止点。

​ 第三单元对JML的学习理解保证了代码的正确性,但本单元作业困难的地方在于算法。JML规格对于代码的正确性有很大的帮助,同时让结构更好、方法复杂度更低,可以专注于每个部分的性能的提升。经过三次作业后,感受到设计好整个架构以及每个方法的作用之后再开始实现代码,能很大程度上提高效率,减少重构的可能性,更能专注于每个部分的实现。

第四单元

​ 第四单元是对UML类图、UML顺序图和UML状态图的解析,具体实现见上述。在经过前三单元的学习之后,本单元从第十三次作业开始根据UML的特性设计了层次化的结构,后两次作业均在该基础上迭代开发,选取了适当的容器、算法,并对部分查询进行了缓存,算是一种比较面向对象的思考方式。同时,在熟悉UML图之后,感觉这也是一个描述代码功能结构的很好的工具,在实现代码之前画好UML图可以提前分析设计的结构是否合理,是否符合要求。

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

第一单元

​ 第一单元需要构造多项式,然后判断自己的求导结果。测试时,主要根据指导书,构造各种特殊的测试样例,如结果为0或1,或系数为1或-1,或指数为1或-1或0,多个sin的嵌套等,然后逐步增加样例的复杂度。这是方法虽然可以检查一些特殊情况,但比较低效,需要花较多时间,覆盖度较差,并且在样例复杂的时候也很难计算结果。

第二单元

​ 第二单元需要构造上电梯请求,然后判断电梯的运行情况是否正确。测试时,新建一个类,自动生成随机请求并输入程序。对于运行情况的判断主要包括上下人的数量,以及人上下电梯的楼层正确与否,电梯是否有特殊情况,如无人上下但是开门,是否一层层运行,有无在禁止开门的楼层开门。并且可以通过改变生成请求的时间间隔和楼层的范围检查结果,加长请求间隔时间可检查电梯能否正常await()signnal(),增大和减小楼层范围可判断算法的正确性,以及优化的方向。

第三单元

​ 第三单元需要生成各种指令,然后判断反馈结果是否正确。在第三单元,用python进行自动化测试,随机生成测试样例,并用networkx包建相应的图,可调用nx.dijkstra_path_length(G,source=id1,target=id2)nx.single_source_shortest_path(G, i1)等方法测试几个算法较复杂的方法,对于其他函数的测试,则直接对应JML规格在python程序中无脑循环,检查结果是否一致,同时用time.perf_counter()计算程序运行时间,使程序运行时间大致上不出现太大的偏差。

第四单元

​ 第四单元需要构造UML模型,然后判断查询指令的结果是否正确。本单元比较难随机生成样例,因此手动画各种特殊情况的UML图,如各种同名、继承实现的各种圈儿,然后导出,观察程序运行结果,判断是否正确。然后在输入查询指令时,测试各种异常,如查询不存在的类等。

小结

​ 从第一单元手动构造测试样例,到第二单元在程序中随机生成数据进行测试,再到第三单元用python进行自动化测试、同时判断程序运行时间,测试的覆盖性越来越强,程序的正确性也有了很大的保障。

课程收获

​ 这一学期的OO学习让我受益匪浅。从刚开始只专注于程序的正确性,一拿到题就开始吭哧吭哧写、写完吭哧吭哧改,到开始在写代码之前思考代码的结构、结构的可扩展性和算法的性能,在有一个大致的脉络之后再开始写代码的工作。面向对象的思维对代码的结构也有很大帮助,思维方式的改变提高了效率,减少了重构次数,也有利于代码的正确性、可扩展性和性能。

​ 在结构方面,了解并学习了许多设计模式的应用,如:工厂模式、生产者-消费者模式、Work Thread模式等,并学会通过封装继承、实现接口等方法建立一个较好的架构,降低代码的复杂度、耦合度,更利于代码的扩展。

​ 在算法方面,开始重视容器的选择,并且学习到了许多新的算法,在保证正确性的基础上,提高代码的性能。一些情况下,缓存机制对于代码性能的提高也有很大帮助。OO第三单元也让我花费很多时间查阅博客查找资料,了解学习了一些比较难的算法,培养了自己查找资料进行自学的能力。

​ 在测试方面,从第一单元手动构造测试样例,到第二单元在程序中随机生成数据进行测试,再到第三单元用python进行自动化测试,对我来说是一个较大的进步,意识到了测试的重要性,自动化测试对代码的正确性、优化的方向也有很大帮助,在代码交上去之后终于不是刚开始那种听天由命的感觉。

​ 同时,在不知不觉间也提高了自己编程的能力、debug的能力,能更加耐心专注,也提高了查找资料自学的能力。并且了解了一些如JML规格、UML图之类的工具,以及多线程对未来的学习和工作都有很大作用。总体来说,过程有多艰难,收获就有多少。

改进意见

  • 部分OO理论课上的内容较为抽象,比较难理解,关于一些抽象的思想,希望可以更多地结合作业讲解,因为对于作业是最了解的,结合作业解释更能体会到那些思想的优势,以及如何应用。同时,理论课上对于写作业实际需要学习的内容涉及也较少。
  • 诚然,OO研讨课上有许多非常宝贵的经验分享,十分实用,让人豁然开朗,但还是有一些内容,感觉对于当下来说作用不是很大,过于高端。
  • OO第三单元是对于JML规格的学习,但是感觉这单元对于算法的要求较高,主要时间都花在了算法的学习上,而不是对于JML规格的理解或者写出JML规格的能力。

线上OO学习体会

​ 线上的学习对我来说,其实并没有很大影响,甚至有许多好处。网课可以在之后反复观看,让我能更好地理解课上的内容。而且,对于一个不怎么参与讨论的人来说,可以看到大家在群里的讨论,给我的帮助也很大。并且,即使在家编程,OO也是一门让人很容易投入的课程,在家学习的效率比其他学科高很多。总体来说,OO的线上学习除了让老师助教们花费了更多的精力,实验课有提交不上的风险之外,对我个人来说,是利大于弊的。

posted @ 2020-06-19 20:12  AhaSokach  阅读(202)  评论(0编辑  收藏  举报