BUAA-OO-Unit4与课程总结

BUAA-OO-Unit4 与课程总结

1. 本单元架构设计

​ 本单元作业实现了UML解析器, 分别支持类图、时序图和状态状态以及模型有效性的检查. 与以往三个单元很不同的是, 课程组已实现了对mdj文件的解析工作, 并保留了mdj文件中最基本的元素信息. 我们需要做的, 即是思考利用何种手段将这些数据组织存储起来, 方便查询.

​ 在架构设计上, 我并没有选择用层次化设计, 而是直接重建关键UML元素类, 对内封装一些数据, 便于后续实现各个查询接口. 架构大体如下(在此只给出):

​ 在代码实现上, 我在某些查询方法中使用流式编程进行编码, 提供了代码的可读性. 例如以下代码:

public int checkClassAttributeDependency() {
    return (int) getAllAttributesInTree().stream()
        .map(UmlAttribute::getType)
        .distinct()
        .filter(dataType -> dataType instanceof ReferenceType
                && !((ReferenceType) dataType).getReferenceId()
                .equals(umlClass.getId()))
        .count();
}

​ 在架构设计上, 除了某些UML元素的自建类, 我还分别为类图、状态图和时序图设计了数据库类, 便于进行数据的存储、整理以及对外查询功能. 在数据库类中, 我使用HashMap存储数据, 实现元素id到元素本身的一对一映射, 同时在数据预处理时即可判断是否含有重名元素, 并使用HashMap<String, Boolean>进行缓存, 便于后续查询.

​ 需要注意的是, 官方包给出的元素是无序的, 因此我们需要在数据库类中添加analyse方法分别对所有有效数据进行分析和整理, 建立各个自建类之间的联系.

​ 关于算法问题, 在第三次作业中, 在判断循环继承时我使用记忆化dfs搜索方案, 目的是为了保证找出所有环路元素的基础上尽可能降低时间复杂度.

2. 四个单元中架构设计思维及OO方法理解的演进

2.1 第一单元

​ 在第一单元中, 是我第一次将OO思想实践在程序设计中, 我也初步意识并体验到一个好的架构对工程化设计的重要性, 好的架构可以带来高扩展性和可维护性, 便于后续的迭代开发工作.

​ 就架构而言, 第一单元使我体会到了层次化设计的思想, 更体会到面向抽象编程的妙处. 这一点有点像OS中设备管理软件的层次关系, 每个层次只需调用底层提供的接口即可, 并不用关注底层的实现细节(其实两门课真的有很多互通之处).

​ 具体来讲, 在第一单元中, 我依据BNF建立起多项式的层次化结构, 通过抽象化和多态对各类对象进行归一化管理, 高层类只需调用相关方法即可, 方法的实现细节则交给具体的类来实现, 有点像各司其职. 而这一步抽象, 则是需要建立对具体问题的考察以及分析之上, 抽象出具体对象之间的共性属性和行为, 建立层次化结构, 这是第一单元所教会我的.

2.2 第二单元

​ 第二单元重在强调在进行并发程序设计时, 需要建立线程安全控制意识. 对于线程安全最重要的是, 分析出哪些资源属于是临界资源, 并利用加锁的方式进行线程同步, 控制线程的相对执行顺序, 保证行为的正确性.

​ 在本单元中, 通过对第一单元自己架构设计的反思, 我进一步加深了对SRP原则的理解, 将电梯类和策略类完全分离, 并利用内部类, 将电梯的运行逻辑封装在抽象电梯类中, 具体到横向和纵向电梯只需要实现各自的部分方法即可; 同时, 我设计了独立的策略类, 实现了策略的可插拔.

​ 在本单元中, 还对层次化设计的体验更深一步, 如果说第一单元中下意识建立层次关系, 本单元中则是通过自己对问题的观察和分析, 琢磨出横纵向电梯在行为上的高度一致性, 并果断重构建立层次化结构.

​ 最后, 在本单元实践中, 我还学习并应用了不少设计模式, 比如状态模式, 流水线模式, 单例模式和策略模式, 体会到设计模式带来的高扩展性, 与蕴含其中的解耦思想. 第二单元中唯一相较遗憾的是没能在作业中应用到工业界广泛使用的可重入锁进行编码实现.

2.3 第三、四单元

​ 在第三单元中, 学习到了契约式编程的思想, 初步学习了JML并在作业中依据规格进行程序设计. 在第四单元中, 学习了UML建模语言, 初步了解了是如何通过语言来进行更为广泛的建模工作.

​ 在我看来, 第三四单元更重于让我们体会OOP思想在数据组织存储上的优势之处. 在第三、四单元的领悟比较一致, 就是封装的思想. 将逻辑上具有紧密联系的一组数据通过类的方式紧密联系在一起, 并将运行逻辑封装在类之中, 使其对外不可见, 而只是对外提供一些业务查询接口, 从而实现"高内聚、低耦合"的设计思想.

​ 具体来讲, 就是在这两个单元中, 我们需要思考的问题其实是如何存储数据, 以何种方式存储更有利于实现相关的查询接口. 第三单元中, 是基于社交网络建立起了无向图的结构, 方便后续MST和最短路径的查询; 同时还选择了相应的容器, 减少查询时的复杂度. 在第四单元中, 基于JML模型元素间的关系建立起了树状结构, 便于后续查找循环图等查询操作.

3. 四个单元中测试理解与实践的演进

​ 在OO课程中, 我在测试方面的收获是巨大的.

3.1 第一单元

​ 在第一单元中, 初次尝试实现一个完全自动化的评测机(数据生成+自动评测), 在hw1中我并没有太过注重数据的强度, 在中测结束前那个中午, 在跑了数万组数据后还是阴差阳错发现了一个致命的bug, 这次经历的教训就是, 不能完全依赖于自动化测试, 自动化生成的数据的随机性会使某些规律性输入才能触发的bug无法被察觉.

​ 在hw3中, 为了能够有效测试到自己所做的一些三角优化, 如何进一步提高数据的针对性是我在本次作业测试的过程中思考的问题.

3.2 第二单元

​ 在第二单元中, spj的方式不再是调包, 而是自行编写spj. 同样地, 由于并发程序测试的不确定性与低效, 我开始思考如何利用并发来提高自动化测试的可靠性和效率, 并逐步开始根据自己需求思考如何进一步提高自动化程度, 为此, 我为评测机添加了一些小组件, 来进一步提高自动化程度, 比如自动记录错误信息, 自动记录输入, 自动记录输出便于后续查看. 为了方便互测时操作, 增加了多种测试模式的功能.

3.3 第三、四单元

​ 在这两个单元中, 正确性验证的方式我选择对拍的方式. 在这一阶段中, 我开始逐步思考如何最大化复用自己的每一次评测机的代码, 而不是每个单元都重构一遍(第一单元就是每次作业重构一遍评测机, 感觉心好累.....).

4. 课程收获

​ 在OO课程中的收获是丰富的, 包括但不限于:

  • 对JAVA语言的了解初步加深, 并学会利用JAVA语言提供的接口去完成更具可读性的代码.
  • 学习并理解了面向对象设计的架构设计思想, 对工程化设计和编码加深了理解.
  • 对测试的理解逐步加深, 并能独立写出一套功能相较完整的自动化测试系统.
  • 不论是通过研讨课, 还是日常的作业训练, 认识到了许多优秀且有想法的朋友和助教们, 学习到了很多新鲜的想法, 开拓了眼界, 明确了学习方向; 在这个过程中更锻炼了表达能力, 和朋友一起交流架构思考, 并初步尝试一起合作开发.
  • ....

5. 课程建议

​ 在这个部分, 我是基于自身在作业内容以及讨论课内容上感受到的问题, 给出几条我认为可能的解决方案.

  • 第一单元中, 第一次作业到第二次作业的迭代内容和难度较大, 第二次到第三次作业的迭代内容较小. 是否可考虑将嵌套括号和三角函数放在第一次作业中, 一方面引导同学们在设计之初就选择正确的架构而是避免后续重构, 另一方面可以减轻hw1到hw2的迭代内容和迭代难度; 在第三次作业中可添加新的运算(比如函数关系合成? 即复合函数, 本质上就是函参可为函数因子)从加法、乘法和合成的三种运算的角度建立层次化结构.
  • 第二单元中, 可根据不同的情景模式, 设计出更多的运行策略, 让同学们进一步体验策略和运行逻辑相分离, 策略可插拔的解耦合设计思想. 比如加上19级早晚高峰的搭乘情景, 可设计出不同的调度策略.
  • 关于研讨课, 个人感觉这是小组交流的环节设计的很好, 能够和优秀的同学们进一步交流架构和设计思想, 无疑更能让我们打开眼界, 并锻炼自己的交流和表达能力. 但小组交流的时间较为短暂, 通常可能仅有不到三十分钟? 感觉每次刚讨论到引发共鸣的时间点上就被迫停止了, 可以考虑压缩一下小组发言的时间, 毕竟大概十几个小组可能在发言的内容上大部分是重叠的.

6. 感言

​ OO课至此就完结啦. 在此想要感谢所有帮助过我的小伙伴和助教, 感谢所有为我们能够收获更多而辛勤付出的助教和老师们 ! 最后, 祝OO课程能够越来越好!

posted @ 2022-06-29 12:26  Wang_zm  阅读(12)  评论(0编辑  收藏  举报