BUAA OO 第四单元反思与课程总结

BUAA OO 第四单元反思与课程总结

写在前面

本单元主要考察了对UML图的理解与运用,以及一些基础的图论知识。目的是实现一个 UML 解析器,使其支持对 UML 类图、时序图、状态图的分析,可以通过输入相应的指令来进行相关查询。

由于解析的大部分内容已经由助教们完成并给出了源码和接口,我们只需要实现 UserApi 接口完成相应的查询方法即可,总体来说难度并不是特别大。

第四单元作业的架构设计

本单元的架构设计上我认为比较简单,主要思路如下所示:

1.对UML各种类进行再封装,添加一写我们需要的方法和属性。

2.在构造方法中将 UmlElement 根据_type的不同装入不同的容器。

2.在容器选择上,如果没有特殊需求,尽可能采用Hash类容器,可将查询时间复杂度降至O(1)。

如图是构造方法:

public MyImplementation(UmlElement[] elements) {
        this.elements = elements;
        for (UmlElement element : elements) {
            switch (element.getElementType()) {
                case UML_CLASS: classes.add((UmlClass) element);
                    break;
                case UML_INTERFACE: interfaces.add((UmlInterface) element);
                    break;
                case UML_OPERATION: operations.add((UmlOperation) element);
                    break;
                case UML_GENERALIZATION: generalizations.add((UmlGeneralization) element);
                    break;
                case UML_PARAMETER: parameters.add((UmlParameter) element);
                    break;
                case UML_ATTRIBUTE: attributes.add((UmlAttribute) element);
                    break;
                case UML_INTERFACE_REALIZATION:
                    realizations.add((UmlInterfaceRealization) element);
                    break;
                case UML_ASSOCIATION: associations.add((UmlAssociation) element);
                    break;
                case UML_ASSOCIATION_END: associationEnds.add((UmlAssociationEnd) element);
                    break;
                case UML_STATE_MACHINE: stateMachines.add((UmlStateMachine) element);
                    break;
                case UML_REGION: regions.add((UmlRegion) element);
                    break;
                case UML_PSEUDOSTATE: pseudostates.add((UmlPseudostate) element);
                    break;
                case UML_STATE: states.add((UmlState) element);
                    break;
                case UML_FINAL_STATE: finalStates.add((UmlFinalState) element);
                    break;
                case UML_TRANSITION: transitions.add((UmlTransition) element);
                    break;
                case UML_EVENT: events.add((UmlEvent) element);
                    break;
                case UML_OPAQUE_BEHAVIOR: opaqueBehaviors.add((UmlOpaqueBehavior) element);
                    break;
                case UML_COLLABORATION: collaborations.add((UmlCollaboration) element);
                    break;
                case UML_INTERACTION: interactions.add((UmlInteraction) element);
                    break;
                case UML_LIFELINE: lifelines.add((UmlLifeline) element);
                    break;
                case UML_ENDPOINT: endpoints.add((UmlEndpoint) element);
                    break;
                case UML_MESSAGE: messages.add((UmlMessage) element);
                    break;
                default:
                    break;
            } 
        } 
	}

同时在这个单元,我遇到了之前没有遇到的一大难题——类的行数超过500行的限制。

我采取了以下策略来解决这个问题:

1.将重复的代码段尽可能提取方法。

2.对于模块性、功能性较强的部分可单独提取出来写成一个工具类。

3.对于超出行数特别多时,可以考虑再写一个类继承当前的类,再在新的类中完成剩下的方法。

架构设计思维及OO方法理解的演进

第一单元

第一单元的主题围绕表达式化简展开,主要训练的是层次化设计能力。在这个单元中我学习了递归下降法,相当巧妙的运用到了接口、继承的一些思想,让我第一次运用了这些面向对象的特性。

在之前的编程训练中,架构设计一直是被我忽略的一个部分,比如在之前的程序设计或者数据结构课程中,都是尽可能怎么简单怎么来,代码可读性、可拓展性等等问题我几乎完全没有去考虑过。这种编程方式,在面对OO课程作业的设计要求时,就会暴露出很大的问题。本单元是我第一次采用面向对象的方式进行编程,很多地方看起来依然不够成熟,比较的面向过程化。但第一单元通过3次迭代开发的作业,还是让我体会到了面向对象的思想特质,也让我开始意识到了一个可拓展性强的架构的巨大优势。

现在回头看看,第一单元其实是践行面向对象设计思想最彻底的一个单元,递归下降法的继承与接口实现关系,极大的简化了解析表达式的复杂度。

第二单元

第二单元以电梯调度为背景,训练的是多线程程序开发与线程安全等问题的解决。在这一单元中我采用了生产者消费者模式,来进行多线程交互,使用工厂模式创建不同类型的电梯。

在这一单元我更加加深了对面向对象思想的深刻理解,对于一个电梯类,它只要需要关注一个电梯需要进行的操作,如上行下行、进入乘客、放出乘客。而对于其他的比如外部等待人数,是否捎带等不应当关注,这一部分内容理应交给去调度器完成。

这个单元的重点出了正确性之外还有一个运行时间时间,这是调度算法设计优劣的体现因此应当充分考虑各种情况,追求让调度算法在更广泛看可能性中有稳定的表现。

第三单元

第三单元围绕JML与契约式编程展开。这个单元同样考察了相当多的基础图论算法。该单元的核心思想在于规格设计与代码实现的不一致性。对于同一个规格设计可以又很多中复杂度不一的代码实现,有些实现方式很简单,但是时间复杂度较高,会有tle的风险;有些需要设计一些算法来实现。

第四单元

第四单元的主题是三种UML图的解析。重点就是各种UML元素的数据结构的重新搭建,搭建好了之后各种功能的实现就会相对容易很多。

在本单元中我认为更多阅读一下助教提供的解析代码,各种封装接口的巧妙实现更能够体现面向对象的思想。

测试理解与实践的演进

在第一单元以及第二中我主要是靠自己构造特殊边界样例进行测试,同时也会使用一些比较复杂的数据与同学进行对拍测试,并没耗费特别多的精力,但在个别作业总也会由于测试不充分而翻车。

从第三单元开始,我逐渐意识到了测试的重要性,同时由于作业难度和工作量的适当减少,我也有了更多的时间去进行测试。为了提升测试覆盖率,这个单元我使用 python 自己写了数据生成器进行测试,以第三单元为例:

from numpy import random

addperson = ""
addrelation1 = ""
addrelation2 = ""
addtogroup = ""
qlc = ""
for i in range(1500):
    addperson = addperson + 'ap ' + str(i) + " name"+str(i) + ' 10\n'

for i in range(1500):
    addrelation1 = addrelation1 + 'ar ' + str(i) + " " + str(i+1) + ' 20\n'

for i in range(1980):
    addrelation1 = addrelation1 + 'ar ' + str(random.randint(0, 1500)) + " " + str(random.randint(0, 1500)) + ' ' + str(random.randint(1, 50)) +'\n'

for i in range(20):
    qlc = qlc + 'qlc ' + str(i) + ' \n'

fo = open("case3.txt", "w")
fo.write(addperson+addrelation1+qlc)

第四单元的测试难点主要在于构建图, 使用 starUML 画出UML图后使用官方包中的jar包工具进行解析生成测试数据, 同时要注意一些边界条件比如null,重名的情况等等。

经过事实检验证明,只要是经过充分的课下测试的作业,在强测中都没有出现问题,而对于写的时候没有特别注意细节而测试又因为种种原因没有做充分的情况,在强测中往往就会出现一些意想不到的bug,在互测中也会遭遇hack。

课程收获

知识层面,我第一次接触并且系统性学习了面向对象的概念与实践,属性并掌握了java这门新的编程语言,学会了层次化设计方法、多线程程序设计、JML规格、UML图等内容,了解并运用了工厂模式、生产者-消费者模式等多种设计模式。还有,对于递归下降法这一编译中的重点方法有了初步认识,对一些图论的基础算法有了更加深刻的印象。

能力层面,每周的雷打不动的高质量作业让我的心态得到了很好的锻炼,从一开始的无从下手而焦虑,到后来能够慢慢分析题目并进行架构设计,我面对这种任务的心态有了很好的提升。其次这12次的作业充分的锻炼了我程序设计、架构设计、算法设计的能力,培养了架构意识和充分测试的概念。同时每次的上机以及后两单元的作业加强了我阅读理解代码的能力以及debug的能力。

学习方法层面,在学习OO的过程中和同学有非常密切的交流,遇到不理解的点有了一个可以随时提问没有顾虑的地方,这让我的学习的效率得到了提升。同时大家一起构造数据进行对拍,相互找bug的过程也加深了同学间的交流与了解,增进了友谊。

给世界一流课程一些小小的改进建议

  • 第一单元的刚刚开始的难度有些许的大,递归下降法的理解需要花一些时间,整个作业完成起来非常的不容易,希望能够在预习部分给出一些铺垫。
  • OO 作业指导书太长了,而且还有多个大标题,小标题,阅读难度有点大,建议在不造成歧义的前提下精简题目的描述,同时在指导书最开头能够给出包括各级标题的目录。
  • 对于实验上机希望每次结束后能够公布答案,或者在仓库中给出一些反馈,这样的话感觉上机能够发挥出更大的作用。
posted @ 2022-06-26 22:26  Arosy_24  阅读(19)  评论(0编辑  收藏  举报