BUAA_OO_2022 第四单元总结
一、第四单元架构设计
1.1 输入和保存
UML建模具有层次化的特点,每个UML元素都有ParentId指向它的上层元素,因此采用层次化的结构对输入进行解析。由于输入是无序的,选择对输入进行四次遍历,第一次先处理最高层次的元素如UmlClass、UmlStateMachine、UmlCollaboration,后三次按照层级结构关系逐级向下展开。
为了在类中储存下层元素,需要将大部分UML元素类进行封装,增加自定义的属性和方法,如下图:
存储容器的选择:每种元素都有一个用ID索引的HashMap,此外,需要判断重名的元素增加一张HashMap进行重名记录——HashMap<Name, isDuplicated>,需要按名字查找的元素增加一张以Name索引的HashMap。在计算过程中也会用到HashSet、ArrayList等容器来保存元素或中间量,需要结合具体实现和效率来选择,随用随加。
1.2 图
接口的多继承、状态机要用到有向图,我通过储存每个点的邻接点来实现图结构。
判断状态机中的关键状态:dfs算法。考察该状态删除前后起点状态和终点状态是否连通。
判断循环继承:dfs算法,用栈追踪路径。从每一个节点出发dfs,栈中元素重复即为环路,最后将每个节点出发找到的环路进行合并。注意自环。
判断重复继承:dfs算法。从一点到另一点存在两条不同路径(等价于dfs中某个点被访问两次),说明存在重复继承。注意自环。
1.3 正确性检查
检查方法被调用时,按照层次结构将检查任务向下分派到各层元素中,下层元素将正确性信息返回,由上层元素汇总。简单的错误,在输入时可以立即发现(如接口属性可见性不是public),并用布尔值记录起来;复杂的错误则应该在输入完成后统一检查,防止多次检查增加开销(如循环继承、重复继承)。
二、四个单元中架构设计思维及OO方法理解的演进
Unit 1
第一单元的重点是表达式的解析和化简。需要建立表达式的层级机构关系,用递归下降的方式实现解析、化简、输出。我在第一单元地架构设计注重模块化和解耦合,设立了预处理模块、输入解析模块、数据容器模块等各司其职。本单元很能体现OO中的多态和继承,如每次作业都增加新的因子类型,需要对因子进行泛化。
Unit 2
第二单元的设计比第一单元更为复杂,需要对电梯进行多线程调度。用“生产者——消费者”模型和调度器类实现了线程之间的协作;将调度器抽象为一个模块,而不是让电梯自由竞争,可以在俯瞰全局的情况下作出更优的调度,如电梯空闲时,调度器会令电梯均匀分布在各楼层中进行待机,对分布不集中的乘坐请求有很高的响应效率。难点是对锁和线程的理解,在设计中要明确哪些数据是共享数据,它们的读者和写者是哪些对象;对共享数据的写操作,要用临界区包围起来;预防死锁和轮询。
Unit 3
第三单元是按JML规格开发社交网络,不太需要架构设计。重点是各种数据结构和算法,我用到了并查集、Kruscal、Dijkstra,需要将这些算法封装为函数或类方便复用,否则代码行数可能会超出500行的限制。学习到了自定义异常类的计数功能,抛出和捕获的写法。
Unit 4
第四单元实现 UML 解析器。由于UML本身具有层次结构,很适合用面向对象的建模方式来解决,将不同元素的数据和操作封装在一起。架构设计与第一单元相似。
三、四个单元中测试理解与实践的演进
Unit 1
由于时间不够,没有进行充分的自动化测试,按照自己理解的重点、难点、特殊点手动构造数据。
Unit 2
本单元中认真思考了随机生成数据的优势和劣势。用随机生成数据进行基本功能和死锁的检测,手动构造极端数据进行特殊输入下的性能测试,与同学对拍。
Unit 3
契约式编程,JML规格明确规定了数据输入范围和约束条件,测试自然也需要满足契约,严格按照JML规格进行数据生成并单元测试。复杂的ensures条件如:保证最小生成树的边权和最小,需要自己根据对规格的理解另行编程验证。
Unit 4
自动构造数据太难,而且随机生成的图结构难以控制,测试效果一般。因此借用官方样例的格式自行构造数据,测试每一条指令,与同学对拍。
四、课程收获
- JAVA语法:类和方法、容器、泛型、异常处理、多线程。
- 调试和测试:Jstack和jps排查死锁、JUnit单元测试、Python自动化测试。
- 设计思维:封装、多态、继承、递归下降、层次化建模、生产者消费者模型、流水线模型、设计模式。
- 数据结构及算法:最小生成树、最短路径、图的遍历、并查集、数组、链表等等。我的数据结构课和OO课隔了两年,刚好能复习一下。
- 字符串处理:正则表达式。
- 契约式编程:JML语法。
- 可视化建模:UML语言、UML元素的理解和解析。
- 代码风格:注重功能的解耦和分割,一个方法不应写太长,否则自己也会看不懂。
五、改进建议
- 目前Pre的内容有一些简单和重复。建议压缩一些Pre中的训练量,增加一些学习内容,如JAVA容器和泛型相关知识。
- 添加优秀作业展示的环节:每个单元一次,单元结束后挑选一份同学或课程组编写的优秀代码供大家参考。有这个需求,是因为我常常疑惑代码怎么才能写得更精炼,虽然功能正确了,性能也还可以。但看着自己别扭的方法名、变量名,冗杂的if-else语句,乱七八糟的数据容器,总感觉不够优雅,没有OO之美。读互测小伙伴的代码吧,没有那个时间,而且也不一定总能遇到写得非常好的。官方包代码,跟作业实现的功能不同,读起来体会没有那么深刻。因此希望课题组能在每个单元之后提供一份“参考答案”。
- 提前每次作业的布置时间。一些较难的作业,我的完成时间会到达15小时以上,然而从周一晚到周六晚只有五天整天,平均每天要工作3小时以上,要求太高,而且每周的周日、周一不能用来写OO作业,安排起来缺乏灵活性。建议作业时间至少延长到一周。
posted on 2022-06-29 15:45 huaimaomao-Official 阅读(51) 评论(0) 编辑 收藏 举报