OO-第四单元总结暨学期总结

本单元作业的架构设计

本单元任务是基于课程组给出的代码框架,设计实现自己的UML解析器类,能够构建UML类图、顺序图和装调图,支持相应的查询操作,并且支持基础的模型有效性检验。

构建过程

为了避免checkstyle对于单个文件行数500的限制,以及面向对象代码解耦的要求,将读取UmlElement并构建uml图的过程提取成Structure类存放在MyImplementation中。

由于输入的elements不保证顺序,对于一些有着前驱后继关系的元素而言不太方便。因此我通过多次循环遍历输入elements进行构建。

private void constructStructure(UmlElement... elements) {
    for (UmlElement element : elements) {
        if (element.getElementType() == ElementType.UML_COLLABORATION) {
            addCollaboration((UmlCollaboration) element);
        }
    }
    firstConstruct(elements);
    secondConstruct(elements);
    thirdConstruct(elements);
}

private void firstConstruct(UmlElement... elements) {
    for (UmlElement element : elements) {
        switch (element.getElementType()) {
            case UML_CLASS:
                addClass((UmlClass) element);
                break;
            case UML_INTERFACE:
                addInterface((UmlInterface) element);
                break;
            case UML_ASSOCIATION:
                addAssociation((UmlAssociation) element);
                break;
            case UML_INTERACTION:
                addInteraction((UmlInteraction) element);
                break;
            case UML_STATE_MACHINE:
                addStateMachine((UmlStateMachine) element);
                break;
            case UML_REGION:
                addRegion((UmlRegion) element);
                break;
            default:
        }
    }
}

private void secondConstruct(UmlElement... elements) {
    for (UmlElement element : elements) {
        switch (element.getElementType()) {
            case UML_ATTRIBUTE:
                addAttribute((UmlAttribute) element);
                break;
            case UML_OPERATION:
                addOperation((UmlOperation) element);
                break;
            case UML_ASSOCIATION_END:
                addAssociationEnd((UmlAssociationEnd) element);
                break;
            case UML_LIFELINE:
                addLifeline((UmlLifeline) element);
                break;
            case UML_ENDPOINT:
                addEndpoint((UmlEndpoint) element);
                break;
            case UML_STATE:
                addState(element,0);
                break;
            case UML_PSEUDOSTATE:
                addState(element,1);
                break;
            case UML_FINAL_STATE:
                addState(element,2);
                break;
            case UML_TRANSITION:
                addTransition((UmlTransition) element);
                break;
            default:
        }
    }
}

private void thirdConstruct(UmlElement... elements) {
        for (UmlElement element : elements) {
            switch (element.getElementType()) {
                case UML_GENERALIZATION:
                    addGeneralization((UmlGeneralization) element);
                    break;
                case UML_INTERFACE_REALIZATION:
                    addInterfaceRealization((UmlInterfaceRealization) element);
                    break;
                case UML_PARAMETER:
                    addParameter((UmlParameter) element);
                    break;
                case UML_MESSAGE:
                    addMessage((UmlMessage) element);
                    break;
                case UML_EVENT:
                    addEvent((UmlEvent) element);
                    break;
                case UML_OPAQUE_BEHAVIOR:
                    addOpaqueBehavior((UmlOpaqueBehavior) element);
                    break;
                default:
            }
        }
    }

类图

类作为OO课最熟悉的内容,其实现也相对简单,只需要将表示类图元素的MyClass,MyInterface,MyAttribute,MyAssociationEnds,MyOperation,MyParameter根据表示关系的MyGeneralization,MyAssociation,MyInterfaceRealization组合成如下的树状结构即可。其中MyClassMyInterface除了记录自己拥有的属性和操作以外,还记录了自己继承的和继承自己的类/接口,以及通过关联关系获得的另一端的内容。类还记录了自己实现的所有接口。

顺序图

顺序图需要构建一个Collaboration用来存储有效性检查所必须的Attribute。核心部分在interaction部分,存储消息发送或接收的端点Lifeline/EndPoint,由于查询指令的关系这些端点还需要保存接收和发送的消息。

状态图

状态图由于Region和StateMachine保证一一对应,因此可以压缩一层结构,只实现MyStateMachine,只需要在Structure中记录映射关系即可。这一部分的图我将节点和边分开保存,便于实现关键节点获取的算法。

优化可能

在图中随处可见的xxxManager是我在开始设计时为了满足既能通过name字段索引又能通过id字段索引而引入的。后来发现Manager应当设计为可复用的泛型结构。但是我将重名异常抛出的功能整合到Manager中,一时没有想到如何在泛型条件下处理异常,再加上旧代码不太方便更换,因此也就将错就错的重复实现了好几个xxxManager。这一部分可以修改的更好。

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

第一单元

第一单元是对表达式进行解析并化简。或许是因为认真体会了完成pre的过程,在第一单元最开始,层次化的设计思路就出现了。第一次作业按照表达式中的各种元素类型建立类,并将这些类按照表达式的层次组织起来,加以递归下降的解析器,基本上可以自然的实现表达式嵌套解析和嵌套化简输出。但是在迭代的过程中由于最开始只考虑了多项式结构,在引入三角函数和自定义函数后经历了相当痛苦的重构过程,最终对于自定义函数的解析也是通过预处理替换完成的。当时对于面向对象的理解还不够完善,没有比较良好的架构设计思维,对于面向对象的理解也停留在数据组织层面,在代码中将解析和化简杂糅在一起,感觉仍然有许多优化的余地。

第二单元

第二单元是名声在外的电梯单元。在引入了多线程之后,对于编码和测试的难度增加了不少。在这一单元的学习过程中我掌握了不少面向对象设计模式,包括生产者消费者模式、单例模式、Template Method模式等,也对与多线程设计过程中线程安全的保证方式掌握了不少。这一单元的架构设计相较签一单元有了不少进步,三次迭代过程中几乎没有很大的变化。

第三单元

第三单元主要是根据JML规格的描述实现功能。这一单元的编码过程并不复杂,因为JML已经给出,要点在于正确理解JML,并在一些地方使用高效的算法避免超时。课上学习的核心则是如何构造合理有效完备的JML,以及如何根据JML进行测试的设计。这些知识结合给出的JML规格,让我对架构设计有了更深的理解。

第四单元

第四单元要求解析构造出uml类图、顺序图和状态图,支持有效性检查和若干查询指令。这一次作业和第一次作业在某种程度上有些类似,只要按照层次化设计的方法拆分各种uml图中的元素,并将查询指令的实现也按照层次化方式一步步细化为更细节的处理,就能构建出比较合理的设计。

测试理解与实践的演进

第一单元

第一单元的数据生成规则比较简单,只需要按照题目提供的形式化表述实现即可。因此在第一单元自己尝试写了黑盒测试代码,通过随机生成数据检测程序的正确性。同时也会结合代码查找bug。

第二单元

第二单元由于引入了多线程,完全随机的数据生成策略更有可能找到线程不安全的问题。但在多线程条件下生成对应的正确输出数据比较困难,本单元作业中没有自己完成一个测评机。查找bug的过程也主要通过查看代码并辅以便于生成的极限数据进行。

第三单元

第三单元由于每个函数都有对应的规格化描述,比较适合使用JUnit进行单元测试。但是在尝试了JUnit后感觉没有特别理解其使用方法。因此还是使用常规的测试方法进行测试。但是即使这样仍然可以通过JML规格描述全面的对各种情况进行测试。

第四单元

第四单元可以通过构造比较特殊的UML类图进行测试,比如自循环继承、多继承同一接口等特殊数据。由于构造合理的.mdj文件比较困难,因此也没有实现黑盒测评机。

课程收获

面向对象思想与架构设计

在课上理论知识的学习和每周一次的代码实操过程中,我对于面向对象思想的思想有了更深的体会,同时四个单元每单元的迭代开发的经历更是提醒我架构设计的重要性。编码不是项目的开始,而是项目的结束。uml图对项目结构的描绘,JML规格对于各个函数功能的描写,这些才是真正关键的部分,一旦架构设计完成,编码不过是按图索骥。

多线程编程

第二单元引入的多线程让我第一次体会到了多线程编程的复杂和巧妙,并发性带来的奇妙与痛苦一样丰富(bushi)。在第二单元的学习过程也让我领悟到线程安全保障的代码实现。这一收获甚至有助于我理解隔壁OS课程的进程并发。

代码风格

OO课程中还有着checkstyle分数的规定,这让我开始有意识的优化自己的代码风格。维持特定风格的方法名与类名、维持类与方法的简单性(减少行数)等等。从另一个方面推着我使用面向对象的层次化思路去编程。

代码量

每周一次非常规律的OO单元作业,让我在这学期的代码量增加的不少,代码能力得到了提升。

改进建议

测试专题

从某种程度上,OO课程对于测试是很重视的,无论是每周常规的圣杯战争互测阶段,还是在第三单元明显弱化过的弱测、中策,无疑是鼓励同学们自己进行测试的。然而一方面,由于课业任务比较多,自己的效率又有些低,另一方面,测评机本身也确实具有一定的复杂度,所以总是没有时间自己琢磨如何设计测评机。因此希望在OO课程的pre中,或者在每个单元的作业中都增加测试数据构造方法论,以及如JUnit等测试插件的使用方法等内容。

第四单元课上与作业

对于第四单元的课上内容与代码作业,感觉存在一些割裂感。课上内容主要在介绍uml图是如何参与进架构设计中的,是如何利用uml图这一工具进行设计。而代码作业中强调的是对uml图的代码存储格式(.mdj文件)的理解。

时间安排

实验课最好能提前一些安排。现在安排在周四的话,对于有思路的同学可能周四之前就完成了作业,但是在架构上因为没有比较好的引导在后续迭代中会不太舒服;对于没有特备好思路的同学,可能需要到周四上机之后才能受到启发,而这样的话时间又会比较紧张。

posted @ 2022-06-29 00:39  scrail  阅读(27)  评论(0编辑  收藏  举报