2022 OO 第四单元

2022 OO 第四单元总结

一、本单元架构设计

  本单元的架构设计很大程度上依赖对于 mdj 文件的理解,对于指导书内容的理解程度以及对于细节的处理也会影响到程序的正确性。

  由于意识到三次迭代作业中需要完成对于类图、顺序图和状态图的方法查询和异常处理,因此主要对不同种类的模型分别建立对应的查询类,根据查询接口实现的方法所指向的查询类别,来分配不同的类分别实现对应的方法。该设计的优势在于,可以较好地实现模型元素的解耦,除了 UMLAttribute 这类需要同时存在于类图和顺序图中的属性外,其余的属性基本都只需要被分配到三种模型中的一种。

  在数据的存储方式上,主要使用了 HashMap HashSet ArrayList 容器。如果能够较好地利用 Set 的去重功能,以及各种容器接口自带的 equals 方法,则能比较容易与官方包提供的接口相互配合,并在重复判断中减少冗余代码等。

  对于需要查找继承关系接口实现状态转移等需要进行索引的对象,最好通过其 id 以及 name 进行索引。尤其对于 UMLElement 来讲, id 是唯一的,在索引时不容易出现歧义,也更容易应对输入中可能出现的引用出现在定义之前的状况。对于比较难以控制的对象,比如状态机,新建了一个单独的类来控制和其相关的属性行为,比如状态机下对应的各种状态及触发事件等。由于最开始认为不同的查询类之间可能存在很多类似的行为,因此还实现了一个 Diagram 接口,只有得到所控制的属性类型和处理全部元素两个方法,但实际上不同的类之间其余类似的行为所剩无几,该接口虽然可有可无但也并没有什么坏处。

  在算法上,主要采用了 BFS DFS , 虽然暴力了一点,但它们真是 yyds,几乎能用少量的代码解决本单元作业中绝大多数问题,让 500 行代码完成一个类不再是梦。代码实现上也主要应用了 stream 流操作,对于容器中符合要求的元素提取或修改并进行映射操作等处理较为高效,降低了代码编写的难度。最后吹一下官方包源代码,有很多高级写法是通过自学不易学到的,比如对于不同属性进行分类我就借鉴了官方包中新建容器时直接加入元素,这可以在一定程度上提高程序的可读性,如下:

    private final HashSet<ElementType> dataTypes = new HashSet<ElementType>() {{
            add(ElementType.UML_CLASS);
            add(ElementType.UML_INTERFACE);
            add(ElementType.UML_OPERATION);
            add(ElementType.UML_ATTRIBUTE);
            add(ElementType.UML_PARAMETER);
            add(ElementType.UML_GENERALIZATION);
            add(ElementType.UML_INTERFACE_REALIZATION);
            add(ElementType.UML_ASSOCIATION);
            add(ElementType.UML_ASSOCIATION_END);
        }};

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

第一单元

  第一单元是以化简为目的实现表达式解析的任务,主要是通过递归下降法建立表达式树,在架构设计上用不同的类代表不同的解析成分。在第一单元作业中我还没有形成对于架构设计思想的整体认识,在代码实现上对表达式树成分进行生搬硬套式的拆解,因此虽然架构设计看起来很 OO,但执行起来的思想还是很面向过程的,我的代码中没有体现出 OO 方法的优势。

第二单元

  第二单元是以电梯为载体引入多线程任务,主要是通过不同的设计模式和调度策略体会多线程设计与单线程的区别。设计模式包括生产者-消费者模式,状态模式,单例模式,工厂模式,策略模式等,不同的设计模式各有千秋。我借鉴了实验代码中的生产者-消费者模式,采用了自由竞争架构,用引用逻辑实现多电梯共享候乘表。

  对横向电梯和纵向电梯的所驻楼层或楼座分配 BlockingQueue 等待队列,通过使用多线程工具实现了数据的安全共享。通过对于共享对象的有效识别避免死锁,以及等待-唤醒机制避免轮询,对于对象间的协作关系及其对于性能的影响有了更深刻的认识,对于横向电梯和纵向电梯是电梯的多态、换乘请求和普通请求是请求的多态等设计问题以及实现有了更深刻的理解。

第三单元

  第三单元是在人际关系模拟的背景下引入 JML 规格理解与设计任务,主要是通过阅读 JML 规格按照一定的规则实现程序的功能和异常处理。通过 JML 规格,更深刻地认识了保证程序正确性和兼容性的范式,这对于设计大规模的程序以及合作编写代码中有着非常重要的作用。此外,本单元在强测和互测中针对程序的性能提出要求,我学习到了缓冲读取等常用的机制,对使用各种算法解决和实际关联性较强的问题进行了实践,认识到 OO 方法在处理大规模工程问题中的现实意义。

第四单元

  第四单元是通过完成 UML 解析器加深对于 UML 模型理解的设计任务,主要是对于类图、状态图和顺序图进行属性查询和异常处理。虽然相对于第三单元来讲在性能上没有很高的要求,但是通过完成本单元的作业,我对接口实现、继承、代码静态检查等的原理有了更加深刻的认识,能更好地实现数据的存储和查询,同时对于 Java 语法有了更深入的了解,比如 stream 流操作、枚举类型、查看容器源代码等,我认为善于使用现有工具也是 OO 方法的重要体现。

三、测试理解与实践演进

第一单元

  主要采用了构造小规模特殊数据的测试方法。比如测试程序是否能正常处理和 0 次幂相关、带有 sin(x*x) 项、带有多层括号嵌套项等的数据,针对单一问题测试是否能得到正确结果,再测试将其组合后的结果,最后测试其能否按照要求化简,主要还是采用了比较传统和简单的测试方法。

第二单元

  在数据生成方面主要出于性能的考虑,主要采用了 JProfiler 和任务管理器来检查程序是否出现轮询情况。使用 JProfiler 可以查看发生轮询的主要方法,从而对于出现问题的方法有更清晰的定位;而使用任务管理器主要用于在对于轮询的产生有比较准确的把握时,能够快速检验程序发生轮询的时期。比如通过手动构造请求具有较长空窗期的数据,以及很多请求在同一时刻被加入的数据等,结合工具进行测试。

第三单元 & 第四单元

  第三、四单元由于对于 JML 规格、UML 模型以及指导书的理解不到位,因此主要采用了 Junit 编写单元测试,以及黑箱测试和多人对拍的模式测试,对程序的实现细节进行修改,纠正一些错误认识等。第三单元主要通过数据生成器测试边界条件,观测程序性能;第四单元主要针对单一规则或方法进行测试,通过 debug 模式逐步调试。

四、课程收获

Git 版本管理

  通过使用 Git 版本管理和 GitLab 代码管理仓库,更好地实现代码的版本管理。从最开始机械地用于提交作业,到后来用于将代码恢复到出现难以修复的 bug 之前的版本,我对于实际工程中比较重要的时间结点有了把握,比如重构前(doge)。

Java 语言和语法

  说来也许不太光彩,但在 OO 课程前完全没接触过 Java 语言, C 语言是老师教的。但是由于 OO 课堂上不可能深入讲程序设计语言,因此经历了通过实际案例学习编程语言的过程,虽然有点痛苦,但对提高自学能力有很大帮助。在完成四个单元作业的过程中,加深了我对于容器及其接口、异常处理机制和 Java 8 新特性 stream 操作(感谢 Dong_HY 大佬推荐)等的理解。通过使用 IDEA 了解到实际工程中应用广泛的 IDE 和主要编写文字性代码或在初学阶段所使用的 IDE 的区别。

多线程常用设计方法

  通过对于多线程库的调用,主要是同步块 synchronized 和阻塞队列 BlockingQueue,以及 wait-notify 结构,包括多种相关测试方法。虽然没有用到非常多样和复杂的多线程工具,但对于多线程工具和架构设计的适配性有了初步的认识。

各种算法学习和实现

  很多算法在数据结构课程中学习过,但是由于没有很广泛地应用因此对其理解有些欠缺。OO 课程中涉及到的递归下降法、BFS / DFS 算法、最短路径算法、最小生成树算法、并查集算法、强连通分量算法等,加深了我对于树和图算法的理解。对于一些数据查询的动态维护,以及空间换时间的思想等,也对我很有启发。

OO 思想

  其实 OO 思想是一个宏观笼统的概念,这可以体现到架构设计、规格及测试方法等的方方面面,虽然四个单元的知识点比较琐碎,但是 OO 思想却是贯彻其中的,让我学会通过不同的方法将实际的问题抽象成数据和行为,规范了我编程中的一些陋习,比如命名不规范、逻辑不清晰等,从很大程度上提高了我的编程能力和与人合作的能力。

五、课程改进建议

预习

  考虑到很多同学可能和我一样在 OO 课程学习前不了解 Java 语言,尤其是多线程相关的知识点,在预习时可能有些无从下手,建议课程组以书面形式提供一些学习资料,比如参考网站、视频或博客等,还可以简单介绍一些在编程中可能会实际用到的技巧和方法。

讨论区

  我认为大多数同学可能更关注微信群而不是讨论区,我可能在遇到指导书相关的问题时会先问助教,后来才开始在讨论区中通过自行检索的方式查询相关问题。如果讨论区页面中能将提问和回答放在一起、而不是以时间顺序排列,可能会更有利于查找相关问题的解答和参与讨论。

实验课

  实验课代码具有很强的 示范作用,但有时因为课上时间紧迫,没来得及理解的内容,没有后续开放指导书和答案,不容易促进同学真正学到知识。虽然不知道出于考核的角度是否能真正改进,但我还是暂且提出这个问题,感谢老师和助教的付出。

posted @ 2022-06-27 01:50  RacerK  阅读(11)  评论(0编辑  收藏  举报