2019-oo-第四单元总结&课程总结

oo课程总结

  • 一、第四单元作业架构设计

    • 1. 第一次作业
    • 2. 第二次作业
  • 二、架构设计以及对OO方法理解的演进

    • 1. 表达式求导
    • 2. 多线程电梯
    • 3. 地铁线路查询
    • 4. UML图的解析
  • 三、对测试的理解和实战的改进

  • 四、课程收获

  • 五、对OO课程的建议

一、第四单元作业架构设计

  • 1. 第一次作业

  

第一次作业一共有五个类,MyUmlInteraction类里维护保存MyUmlClass和MyUmlInterface的HashMap;在MyUmlClass中,维护一个UmlClass包含的属性、操作、关联对象、实现的接口、继承的对象;在MyUmlInterface中,维护一个UmlInterfac包含的属性、操作、关联对象、继承的接口(不止一个);新构造的MyUmlOperation类维护了它传入的参数和返回值;

因为MyUmlInteraction构造方法里传入的UmlElement无序,存在一个类的属性、方法等比该类对应的UmlElement更先出现的情况,所以要两次遍历传入的UmlElement,第一次遍历,建立好整个Uml图中包含的类、接口、方法、关联对应的各种HashMap,第二次遍历,将属性、associationend、继承对象、实现接口等分配到对应的类或者接口中去。

理清各个UmlElement之间的关系后,这次作业并不复杂,重要的是耐心的实现,HashMap的key存的是name还是id,自关联的处理等等。

  • 2. 第二次作业

 

 第二次作业的MyUmlGeneralInteraction与第一次作业的MyUmlInteraction功能类似,可以直接继承,为状态图和顺序图分别构建了一个类,在每个类中实现对应的方法,在MyUmlGeneralInteraction的各个方法中,直接调用MyUmlClass/MyUmlInterface/MyCollab/MyStateMachine中对应的方法,否则容易超五百行,checkstyle报错。

这一次的作业难点在002、008、009三个有效性检验上,主要是考虑成环的情况不要出现死循环。我的做法是,在MyUmlClass和MyUmlInterface中实现check002/008/009三个方法,并在主类中遍历所有MyUmlClass和MyUmlInterface,调用其check方法,判断是否正确。这样做的效率不高,比如在检查008的时候,如果出现了一个环,则环上的所有接口和类都应该是不符合要求的,不需要对齐重新执行check008方法。但是图方便,我就没有这么实现,而是选择了全部遍历。

二、架构设计以及对OO方法理解的演进

  • 1. 表达式求导
    • 对于一个java初学者而言,难度是相当大的。这个时候根本没有什么架构设计的概念,只是大概懂得了面向对象思想和面向过程的不同,能够照葫芦画瓢地抽象出三个类,实现了表达式-多项式-因子这样的结构,在这三次作业中,除去具体实现(即正则表达式的使用、爆栈的处理、特殊测试点的处理等等),主要学会的有两点,一是继承,尤其是在第三次作业中,考虑幂因子、表达式因子、三角函数因子(又分为正弦和余弦)等等不同的因子,去继承同一个父类Factor,便于统一的维护和处理。二是学会去关注程序的架构、关注程序的可扩展性,这个观念是从一次次重构的血汗中领会到的。
  • 2. 多线程电梯
    • 同样,对于一个一直使用单线程的人而言,多线程也是有相当大的难度的。这一单元的作业,有以下两个重难点。一是多线程本身逻辑的理解。二是学会几个基本的设计模式,其中以生产者-消费者模式为首。关于前者,有两个难点,一是线程之间的进程、安全性,也是测试的时候最担忧的,不知道什么时候会出现神必的死锁。二是调试。不过由于性能分的存在,比起多线程本身,在写作业的时候,我可能更多地去关注哪种电梯算法更快,而非解决死锁问题,可能有一点跑偏。
  • 3. 地铁线路查询
    • 在第三单元中,由于整体的结构课程组已经给出来了,所以顶层的架构并不需要我们去考虑,也使得这一单元重构代码量大大减少。因为存在“t”的风险,所以这几次作业也更多地去关注算法部分,包括并查集、bfs、dij等等。最体现oo思想的应该是第三次作业,在这次作业中新增的几条指令都可以用同一套方法来解决,因而想到抽象出一个DijGraph类,统一采取”拆点+dij“的做法,只是不同问题传入不同的边权,只需要在RailwaySystem里,初始化三个DijGraph类,分别对应着三个问题。
  • 4. UML图的解析
    • 这一单元的作业也是基于课程组给出的框架来填写函数,经过一个学期的学习,抽象类的思想已经深入人心,很容易想到构建自己的class、interface、operation等等类,来进行信息(比如说属性、方法)的维护,和具体函数的实现,在顶层类中,直接调用这些类对应的函数即可。

三、对测试的理解和实战的改进

第一单元:

在第一单元还是在手造数据的阶段,主要是针对各种各样的“wrong format”,和复杂的三角函数、复合函数来进行针对性的测试。

第二单元:

生成大量随机数据,并重复测试,检查是否出现死锁或者其他多线程不安全的情况。

第三单元:

用JML来验证程序正确性,用Junit自动化测试,不过要自己写断言,也有一点复杂,但是有助于精准定位bug所在位置。当然也要生成大量随机数据(不过也不是完全随机,比如说add和remove指令的间隔等等有利于测试被t的风险)来进行测试。

四、课程收获

  • 坚持就是胜利的信念

  在历次oo作业中, 有几次是真的艰难到想要放弃,比如表达式求导的第三次作业,别提性能分了,就是整个结构的实现就非常困难了,可能因为整个思路和架构的问题,由于表达式因子的各种嵌套,合法性的判断越理越不清楚,直到周二的早上,才下定决心进行重构,换了一个处理的方式,经过一通魔改才最终通过了中测。又比如说地铁线路图的第三次作业,对于拆点有两种处理方式,一种为每一个点设置两个虚点,即起点和终点,分别设pathid为0和-1,对于每个NodeId,从终点到起点连边的边权为y,其余同NodeId不同PathId的点到终点连边边权为0,起点到,其余同NodeId不同PathId的点连边的边权也为0,另一种是对于同一个NodeId的(n+2)个点,两两构建边(n为这个NodeId的不同路径数)。我本来采取的是后者的做法,但这样做构建的边数相当之大,导致后序遍历及其他操作非常缓慢,等发现自己慢到绝对会t,迷迷糊糊通过讨论区弄懂前者的方法的时候,已经到ddl当天晚上八点多了,然后又是一顿紧张刺激的魔改,竟然真的在十点前改对了。

  两次作业到最后都挺气馁和绝望的,但最后咬咬牙坚持一下,竟然也都能挺过去,起码每次作业都是有效作业了。

  • 面向对象的思想

  包括抽象出功能不同的类、多线程、设计模式等等在第三大点中已经提到的oo思想,让人受益良多。

  • 测试的方法

  学会了许多测试程序正确性的方法。

  1. 如何手动构造一个较为完备的测试集,尤其是涉及到特殊情况和边界条件。
  2. 如何构造对拍器。
  3. 如何利用junit进行单元性的检查。
  • 良好的代码风格
  1. 良好的命名风格
  2. 增加方法的数量,减少单个方法的功能。

 

五、对OO课程的建议

  1. 利用讨论课的机会,请优秀作业的作者能够讲述一下整体的思路和实现,简略地讲就可以。主要是完全不讲,硬读代码有的时候不太理解,也会产生惰性,导致很多优秀的代码都没有珍惜。
  2. 在互测中,能够有效发现数据点是否针对同质bug,对同质bug多次提交数据点,比如说超过5次,给予扣分惩罚,要不然太影响互测体验感和心情了,有一次作业1个同质bug被hack了33刀,一大半来自同一个人。就会导致同组的人想弥补自己被hack的分数,开始无脑提交同质数据点来hack别人,恶性循环。
  3. 增加中测的覆盖面,比如前几次作业,因为中测覆盖面广,难度大,强测表现就更好,而后面可能因为中测很弱就懈怠了;降低有效作业的门槛,weak5这个点总是让人很迷惑,有的时候真的难以de出来,而可能只是一点没有考虑到,就要担心自己作业无效也太担心受怕了。

最后的最后,非常非常感谢课程组用心的指导(书),以及大佬们每一次研讨课、讨论贴的分享!祝oo这门课越来越好!

猜你喜欢

转载自www.cnblogs.com/Tian-y/p/11070292.html