Loading

OO第四单元与课程总结

OO第四单元与课程总结

一、单元作业架构设计

1. 第一次作业

  • UML简图 (略去Main类,下同)
    • hw1
  • 架构简述
    • 模型构建
      • MyUmlInteraction将所给elements数组中的不同元素打包为相应的Wrapper类,并划分到不同的集合(以ID为键值的HashMap)中,完成模型的构建
      • Wrapper类将对应的原始类作为private属性以实现打包(而非继承)
      • 打包好后,再通过HashMap的查询完成元素的类的“继承树”、“接口实现图”等数据结构的构造,如将UmlAttributeWrapper通过parentId归到相应的ClassWrapper中等。
    • 交互功能实现
      • MyUmlInteraction按要求实现UmlInteraction接口,完成所有交互功能
      • MyUmlInteraction的交互方法通过ClassWrapper中的原子方法实现

2. 第二、三次作业

  • UML简图(略去与第一次作业中重合的部分)

    • hw2&3
  • 架构简述

    由于后续作业中交互功能的进一步拓展(主要是类太大了,怎么也过不去CheckStyle),原本的MyUmlInteraction功能被重构拆解为三个交互类与一个构造类,分管三种不同图的交互功能与模型构建功能

    • 模型构建
      • MyUmlGeneralInteraction类调用ModelBuilder类的构造方法并传入参数触发模型构建,具体的模型构建由ModelBuilder类的构造方法以及私有方法实现,构建模式同前次作业
      • 最终构建完毕后生成的集合如HashMap等将会随构造方法的调用传入相应的交互类中,待查询时使用
    • 交互功能
      • 三种不同的图——类图、顺序图、状态图——相关的交互功能分别由MyUmlClassModelInteraction类、MyUmlSequenceInteraction类以及MyUmlStateChartInteraction类完成,它们通过构造方法中传入的wrapper集合,以及相应wrapper中的方法完成交互功能
    • 模型检查
      • 模型检查由MyUmlGeneralInteraction直接调用相应交互类中的检查方法,后者中的方法通过调用Wrapper类中实现的原子方法以及一定的实现完成模型检查
      • 算法实现的话,遍历找路径考虑DFS+Stack(Java中采用Dequeue容器实现栈);查找重复实现、重复继承考虑图论知识(并不是什么很高深的知识),可以用上Set等数据结构。具体实现前辈们写的很详细,此处略去

二、架构设计与OO方法理解演进总结

1. 第一单元

  • 第一次作业
    • 架构设计
      • 整体上为“一Main到底”式实现,未作类的封装
      • 仅做了方法封装,也就是过程封装,整体由五个方法——输入、求导、合并同类项、清除零项、输出依顺序完成
    • OO方法
      • 没有实现数据与方法的封装,基本没有用到类的封装,拓展性差
  • 第二、三次作业
    • 架构设计
      • 在hint的提示下,对第一次作业做了彻底的重构
      • 将模式中出现的类型做了抽象与封装,抽象出因子Factor类、项Item类、幂函数Power类等
      • 通过消除左递归,将输入模式转化为表达式子表达式子项因子整数构成的新模式
      • 通过处理类WordMatcher中的相应方法,实现对应的模式匹配,并构造相应实例对象
      • 这些实例对象以类似于表达式树的形式组织,求导时调用顶部的求导方法(接口方法以统一调用),之后会递归调用树中各节点实现表达式的求导
    • OO方法
      • 初次真正自己动手实现封装与抽象的方法——虽然思路不全是自己的,但是确确实实体会到了它与之前面向过程的不同
      • 初次认识到接口对于行为的抽象带来的便捷

2. 第二单元

  • 第一次作业
    • 架构设计
      • InputRequest-WaitingTable-SchedulerScheduler-ToGetTable-Elevator两对生产者-托盘-消费者结构组成的设计
      • 这样设计本意是保留中间的Scheduler以期之后的任务中能得以利用(不过实际上未能如愿,反而降低了效率)
      • 临界区仅设在托盘中,即WaitingTableToGetTable中实现同步的增删方法,生产者与消费者可自行任意调用,以简化同步设计
      • Elevator本身具有“智慧”——也就是采用所谓“分布式调度”——其本身自带请求队列,且会按照LOOK算法(有一定修改)自行从ToGetTable中获得之后的请求,并选择最近的请求予以满足
    • OO思想
      • 数据封装思想体现并不明显,因为实际上类的分工在作业需求中已经基本完全定义
      • 本单元作业实际上是类的行为抽象的训练,而我在做本次作业前花了周四、周五与周六的部分时间进行了架构设计与论证,虽然未能把所有可能性全实现一遍,但对类的行为抽象这一思想也算有所体会
  • 第二次作业
    • 架构设计
      • 由于第一次作业中两对生产者-消费者的设计,Scheduler类成为整个系统运行的瓶颈,进而导致性能分很低。因此这两次作业中对其进行了重构,简化到仅有一对生产者-消费者的设计,即Scheduler-ToGetTable-Elevator,性能上实现了较大突破
      • Elevator类本身就能选择请求,因而本次作业中Scheduler类并没有“调度”的功能,充其量只是一个输入获取器
      • 而“分布式调度“也使得我第二次作业中只要把新电梯和原来的电梯放在一起竞争请求ToGetTable即可完成任务,迭代的工作量非常小
  • 第三次作业
    • 架构设计
      • 沿用第二次作业的设计,这里我仅限定电梯在ToGetTable中获取请求时,当且仅当该请求的目标楼层和出发楼层均在本电梯的可到达楼层时才响应请求,也就是没有实现换乘,这样,迭代的工作量还是非常小
        (实际上我的本意是先搞一个架构过了中测,以后再重构,这样的话压力小些,不过由于那一周的冯如杯任务略重,最终也失去了重构的机会,也算是我在OO中的一大遗憾吧——不过意外的是性能表现还不错)
      • 架构的拓展性并不高,而且Elevator类仅在状态转换时才更新请求队列,实际上更新不及时,进而对性能有较大影响

3. 第三单元

  • 架构设计
    • 自定义的架构内容很少,基本上就仅仅是读JML,实现方法
    • 不过方法的具体实现还是可以由我们这些实现者自定义的,如利用缓存降低查询的时间复杂度、并查集查找与堆优化的Dijkstra算法查找路径等,也算是丰富了自己的视野
  • OO思想
    • 个人认为,本单元的OO思想集中在理论课和实验课,课下作业其实并没有表现出太多OO特色思想,感觉更多是对课上的补充
    • 课上大多说的是抽象与规格实现,也就是架构设计与规格表达的内容,这比具体代码实现更有OO味道。而这部分工作在我们做作业之前就已经完成了,体现在JML代码中,我们只能是通过读来体会,其实还是少点什么

4. 第四单元

  • 架构设计
    • 解析工作的分工与基本数据的封装
    • 具体见前文
  • OO思想
    • 主要是第二、三次作业中我有专门进行数据与行为层面的封装,感觉还是有些成就感。尽管架构非常简单,但是感觉能够自觉使用OO思想进行抽象与封装,而且没有依赖于提示,也算是自己的巨大进步

三、总结自己在四个单元中测试理解与实践的演进

1. 第一单元

  • 白箱测试
    • 既然能通过中测,那么基本功能应该没问题,因此白箱测试可以进行”重点攻击“,重点追踪代码中圈复杂度较高的代码块,找到问题后手动构造数据让程序进入相应if块,完成Hack

2. 第二单元

  • 仍然是白箱测试
    • 本单元作业主要是多线程设计,因此重点针对多线程可能出现的bug进行检测——检测同步语句中wait语句与notify语句使用是否恰当,是否有可能发生轮询与死锁,之后采用程序定点投放并生成测试数据

3. 第三单元

  • 黑箱测试
    • 脚本生成大数据,检测缓存和图相关算法的优化是否到位

4. 第四单元

  • 手动构造数据
    • 在理解题意的基础上手动构造mdj文件,导出数据进行测试,正确数据只能由手算得出

四、课程体会收获

  1. OO思想

    OO课程中,我深刻地体会到了封装抽象的基本思想,包括数据、行为层面的抽象。同时通过规格的学习更体会到了抽象在程序设计尤其是架构设计带来的便利性与安全性(指避免bug,同时更好问责),而第四单元正是我学习成果的体现。

  2. 设计与实现的把握

    • 第一个单元中我喜欢立刻动手,边写边想(设计),导致我的程序中出现了很多”本可以“避免、或是”本可以“用更小的成本解决的问题

    • 后续单元中,我吸取了第一单元的教训,任务布置下来以后先花他几天想想怎么实现(这时候我喜欢在寝室里不停踱步,导致室友以为我好像有什么问题似的哈哈哈),周六再开始coding,结果最后coding的时候时间不太够

    • 想来也只有《论语·公冶长》中:

      季文子三思而后行。子闻之,曰:“再,斯可矣。”

      大意就是孔子认为行动前思考两次就够了,毋须再多思考,否则可能错失良机(个人理解)。用于自己再合适不过——动手实现前当然要先思考,先设计,但是此处设计也并不需要多么周全,只需要满足好基本要求,确保没有逻辑上的bug就可以实现了。再往细了设计,效率就会降低,不如开始实现,在实现中再设计细节。以后还是要多多把握。

    五、OO建议

    1. 第一单元感觉可以提示下”消除左递归“和”递归下降“或是一些类似的更通俗的想法

    当时第一单元第二、三次作业中再去用一个大正则表达式会非常吃力,这时候如果没有一些提示的话确实难乎为继,当时还想着”递归下降这种依次分析式子的方法是面向过程的“而差点ban掉这个想法,有提示的话就顺畅很多了

    2. 研讨课的加分制度希望进行一些调整

    个人希望研讨课的加分制度是”加分“制度,或者如果是在总评占比也稍微小些。我明白这是为了鼓舞大家,希望大家参与讨论,但是对于我这种又菜又社恐的人来说感觉压力稍大

    3. 理论课上希望能够增加一些互动之类

    理论课上大部分同学都带着电脑(就我看到的,后来的课甚至很多同学都不来了),上面讲上面的,下面搞下面的,其实课上讲的很多东西都很有用,但是这样的话就届不到了。希望能够增加一些互动,包括点名、提问等,提高一下课堂效率。

    六、杂谈

    • 大家都说OO这门课非常紧张,很可能为它熬过多个夜晚云云。但对于我这样的虽然但是佛系的人来说其实感觉还不错,我的OO循环基本上就是——基本功能完成,优化有时间再做——互测有时间再看——bug?就这?——任务来了,先看两眼……不过事实上这些任务我都有在我的能力范围内完成的不错。我的OO体验虽然并不深入(指测试全靠自己,没做过正经评测机……也算是另一大遗憾了),但跟上节奏完成任务还是没有压力的,尤其是后期第二单元第二次作业开始,基本上只用周五一下午一晚上,最多再加上周六一上午,作业就都差不多了。周日再做些优化,本周OO任务就算完成了。而且现在回过头来感觉自己也确实成长不少,虽然远比不上各位大佬,但是自己的进步是实打实的,总的来说我还挺满意,如果有后来者我也希望能鼓舞下你吧。

    • 不过确实有两大遗憾,一是电梯没能好好重构一把,二是没能自己搞一个完整功能的评测机。只能是趁着假期,回去弥补一下

    • 还有什么呢?谢谢老师和助教!各位假期愉快!

posted @ 2021-06-26 16:51  4lex49  阅读(77)  评论(1)    收藏  举报