面向对象第四单元&课程总结

北航OO第四单元(UML解析)&课程总结

一、架构设计

本单元的总体任务是设计一个UML解析器,从最初对类图的解析到支持状态图、顺序图,再到最后支持几种基本的模型检验功能。

1、第一次作业

为了将只用parentId联系的不同Uml参数真正连接成Uml代码中的树形结构,我将每个用到的参数都再包装成自己新定义的一个类,并在每个类里面加入对应的容器来存储本来在树形结构就应该由这个类去存储的其他类。除此之外,为了实现构造时更方便的通过parentId找到父节点的功能,每个可能作为父类的类都在最外层设计了一个Hashmap用于直接通过Id查找,而不需要再去遍历外层的树形结构来查找。具体映射如下

    private final HashMap<String, ArrayList<MyClass>> classes = new HashMap<>();
    private final HashMap<String, ArrayList<MyInterface>> interfaces = new HashMap<>();
    private final HashMap<String, MyClass> classesById = new HashMap<>();
    private final HashMap<String, MyInterface> interfacesById = new HashMap<>();
    private final HashMap<String, MyOperation> operations = new HashMap<>();

除此之外,最外层只需要去调用所有我自己定义的类的方法即可完成结构的构建,大大的节省了构造函数的行数。
具体结构如下

简单来说就是构造结束后每个类都拥有原来自己的全部属性和其原来在Uml结构中所拥有的类。并且MyClass和MyImplement还会额外拥有它们继承/实现的类方便查找。

2、第二次作业

沿用第一次的思路,这次作业其实就是将顺序图和状态图也做了建模。值得注意的是,因为顺序图的所有元素的parentId都是UmlInteraction的,所以我直接把UmlCollaboration给架空了。定义的映射和结构如下。

    private final HashMap<String, ArrayList<MyClass>> classes = new HashMap<>();
    private final HashMap<String, ArrayList<MyInterface>> interfaces = new HashMap<>();
    private final HashMap<String, MyClass> classesById = new HashMap<>();
    private final HashMap<String, MyInterface> interfacesById = new HashMap<>();
    private final HashMap<String, MyOperation> operations = new HashMap<>();
    private final HashMap<String, ArrayList<MyStateMachine>> stateMachines = new HashMap<>();
    private final HashMap<String, MyStateMachine> id2StateMachine = new HashMap<>();
    private final HashMap<String, MyStateMachine> regionId2StateMachine = new HashMap<>();
    private final HashMap<String, MyState> id2State = new HashMap<>();
    private final HashMap<String, MyTransition> id2Transition = new HashMap<>();
    private final HashMap<String, ArrayList<MyInteraction>> interactions = new HashMap<>();
    private final HashMap<String, MyInteraction> id2Interaction = new HashMap<>();
    private final HashMap<String, MyLifeline> id2Lifeline = new HashMap<>();


整体还是和上一次作业思路一样。唯一不同的是我将起始状态和最终状态整合进了一般的状态中,将UmlEndPoint整合进了一般的UmlLifeLine中,只是添加了特别的成员变量用于标明,这带来了统一的结构,能减少不必要的分支判断。

3、第三次作业

由于前两次作业我直接建立了完整的树形结构(继承等等也都是一个邻接表构造的图,检查时可以直接用图算法非常方便),第三次作业其实是基本不怎么需要动构造函数的(只需要为了顺序图的R006将UmlLifeLine的插入后移就行)但是第二次作业已经让我的MyImplementation类行数达到485行岌岌可危,肯定是要突破500行。于是额外设计了一个Data类,用于存储我定义的繁多的Hashmap,并把全部200多行的构造函数迁移过去,所有的调用改为调用Data类的get方法。其余的还有用一个boolean数组存储可以构造时检查的检查结果。

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

第一单元可以说是OO的一个下马威,也是远超pre难度的复杂面向对象构造的一个入门。这里我第一次需要自己去思考自己的类应该怎样设计自己的功能,最后组合在一起完成预设任务。但是这单元我的架构设计可以说是理解的较为浅显。我就将类理解成了可以存储值的函数,设计的三个层次的类只需要调用最外层的构造函数,就会递归地调用内层的构造函数,最后当最外层的类的构造函数结束,需要输出的值也就存储在了最外层函数的成员变量中。而完全没有用到类的(构造函数以外的)方法。现在看来,当时我有了架构设计的想法,但是思路还局限在面向过程的编程思维(设计出来的架构完全可以直接通过函数实现而不需要类),也没有解析和数据解耦的思维。

第二单元多线程应该是我OO逐渐熟练的过程,因为久闻电梯大名,在单元开始之前就读完了图解多线程设计模式,这也对我本单元的架构设计和代码迭代(指不需要重构)做出了很大贡献。生产者消费者设计模式和Guarded Suspension设计模式贯穿这一单元始终,各个类之间的协作和互斥也很好的锻炼了我对“每个类应该完成什么事情、而什么事情不要让他管”解耦设计以及写代码前的架构思考的一个锻炼。第二单元我的代码架构相当清晰,以至于在几次增量开发中基本没有感到太大压力(甚至有空又花了半天动态调度算法),第一次体会到了一个清晰的架构的重要性。写博客时看着自己的代码甚至有种爽感

第三单元则是从JML直接约束了我们创建的类中的方法,在架构上基本没有什么自由度。只有通过一些中间变量来分摊复杂度和算法上的设计。

第四单元的时候我的OO能力已经相对成熟,直接仿照着Uml类的结构关系来设计自己的架构最终也就取得了不错的效果。

三、测试的理解与实践的演进

第一单元中我使用了自动生成数据用sumpy对拍和手动构造极端数据。但是限于水平,自动生成和评测数据只能写出生成括号嵌套的表达式,而不能做到自定义函数和求和函数,手动构造也忽略了一种情况导致hw3互测出了这学期唯一一个bug非常残念

第二单元的测试我使用的是随机数据生成器配合输出检查器的黑盒测试。在数据生成随机性上我让数据出现的频率分布不均匀,模拟局部的高并发可能带来的问题以及调度器的性能。然后就可以大规模的挂机跑数据。

第三单元推荐的是用JUnit进行单元测试,但是经过试验还是感觉直接通过输出信息对拍效果更好,而只需要分析一下数据的覆盖率即可。除此之外,也通过手动构造数据来测试一些关键函数的时间复杂度。

第四单元测试的难点是要生成符合标准的Uml图,并且如果随机生成的话数据的覆盖性很难保证,再加上快到期末了事比较多,就没有写数据生成器,直接手绘一些复杂的Uml图来测试,搞得这个单元强测都心慌慌的)

四、课程收获

首先自然是学会了面向对象的设计方法和面向对象的思维,从一开始感觉“什么都要新建一个类还有那么多约束麻不麻烦啊”到现在直呼一句真香。其实对于架构设计思维的培养是在代码编写中潜移默化的,从面向过程转为面向对象之后,我的代码的清晰度越来越高,开始习惯性的用类和方法来管理而非把大部分的逻辑全堆在一个函数里以前写个dijkstra就被逻辑绕晕的日子一去不复返了

除了设计思维方面,当然还有很多更具体、细碎的东西:java语言的熟练应用啊、复杂度分析啊、多线程和同步互斥问题啊、复杂JML的阅读能力啊、UML的解析能力啊等等等等。

最后呢,这一个学期的高强度学习+代码实现也对课下的自学能力有很大的提升吧。总之就是在各种方面上都有很大的收获和成长(。

五、改进性建议

  1. 希望可以单独有一两节课或是教程来讲解自动化测试程序的编写方式。(避免出现我这种已经到学期末了还是只会把数据生成器和检查器分别编译出来再用一个函数去命令行分别调用的人)

  2. 或许预习阶段可以再增加一些对第一单元设计模式的预习(比如再来个pre4),现在体验是第一单元上来直接从面向过程的思维或是pre中不用自己设计类而只需要实现突然转换成需要自己整体设计全部的架构去完成一个大型任务,刚看到作业的时候完全无从下手,U1课下花费的时间和重构次数也远大于后面的单元。

  3. 实验课或许可以再早一些,实验课可以给我们的架构设计提供一种清晰易用的思路,但是每周四的时候一般来说本周作业就已经写完了,发现了实验课的精妙思路也懒得去改了(基础已经成型了下次作业重构的动力也不会很大)。

posted @ 2022-06-21 11:42  gdfwj  阅读(31)  评论(0编辑  收藏  举报