zoukankan      html  css  js  c++  java
  • 面向对象第四单元博客作业

    0 引语

      在经历了第一单元表达式、第二单元多线程电梯、第三单元JML的洗礼摧残之后,终于,我们来到了OO之旅的终点——第四单元。这一单元,我们主要学习了有关UML的相关知识,在这一单元中,我们需要完成的任务为实现一个简单的UML分析器。可以实现对UML类图、状态图(第二次作业新增)、过程图(第二次作业新增)的分析和对UML是否违反规则的判断(第三次作业新增)。总体来说,这次的作业在难度上大于上一单元,但仍在可接受范围之内。下面,我将对这一单元的作业进行分析,并发表一下自己对四个单元的看法。

    一、本单元作业分析与测试结果

    1.1 第一次作业

      一般来说,第一次作业都是在打基础,在做铺垫,所以难度应该并不是很高……

      真的吗?

      那你给我解释一下这一堆都是个什么玩意!

       一拿到作业,看到课程组下发的大礼包,内心是懵逼的:我是谁?我在哪?我该干什么?在前两单元的作业中,课程组虽然也下发了一些jar文件,内含对应的接口供我们使用,但那些文件内容都较少,而且易于使用,代码也比较容易看懂。可这一单元的文件是在玩蛇啊?!让人有一种在看操作系统labn(n>3)的感觉……

      看了指导书和接口使用说明之后,我才明白,这一次作业是让我们完成一个UML类图分析器,其中将输入解析成类的部分已经包含在下发的jar中了(不得不说课程组还比较仁慈,如果连这一部分也要自己写,怕是要写到天荒地老),自己要做的内容,只是根据这些UmlElement类生成对应的结构以及对于每一个“询问”进行对应的回答即可。我设计出的类有:

    MainClass:很短,启动AppRunner而已,略过。

    MyUmlInteraction:这次的核心类,内含接口要求的数个方法,针对每一个询问给出对应的回答(嗯?怎么和第三单元如此相似?)

    MyClass:描述“类”的类,其实就是一个可以自定义方法的UmlClass,内含一些方法以供MyUmlInteraction询问。大部分和“算法”相关的东西也都写在这里。由于这次作业的重点不是算法,而且论算法难度并没有第三次作业难度大,所以略过不谈。

    MyInterface:这次作业比较头疼的一个类,其实就是一个可以自定义方法的UmlInterface,它之所以难,是因为它涉及到了接口的多继承!这还导致了我强测中的一个错误。

    MyOperation、MyAttribute、MyParameter:在类中“填入”的东西,同理,直接用Umlxxx不太方便,所以都写了各自的My形式。

    第一次作业强测结果如下:

     

       还不错啦!但是有点可惜,在UmlInterface中,由于接口是可以多继承的,并且此次作业中允许接口的重复继承,所以在遍历的时候应该按的方法遍历(带visited标记),而我却错用了的方法遍历(直接递归,不涉及visited)。这就导致当节点及路径非常多的时候,会将大量的时间用在无用的计算上,这就导致了这个测试点的超时现象。真的佩服课程组怎么找到这种“带坑”的数据的……

    1.2 第二次作业

      第二次作业是第一次作业的迭代,不过说到迭代,这回的“迭代”算是所有(是的,你没有听错)作业中最不需要考虑上次内容的一次,我想也没什么人会因为这一次作业而重构上次作业的代码吧。因为这次作业是要求在上次作业的基础上“追加”UML状态图和UML过程图的内容。UML状态图和过程图和你类图有什么关系?根本就没影响好叭……所以,可以不用考虑是否会“改坏”原来的代码啦,可喜可贺,可喜可贺!

      不过嘛,上一次作业如果有bug,还是要修复的。并且,由于这次作业没有了互测环节,失去了不少乐趣呢,对于bug的测试面窄了,一些有bug的程序也可能通过强测,而这些问题可能在后续的作业中体现出来。那么,我是怎么做的呢?

     加入了一些神奇的东西。

    YourMachine:其实就是一个状态机,在里面用HashMap等记录了各个状态的信息,可以计算状态转移等。并没有继承UmlStateMachine类,因为总觉得继承了就不自由了,有好多写法可能会受到限制。

    YourState:“你的机器”里当然要有“你的状态”,注意这个YourState中已经包含了起始状态和终止状态,以及普通状态这三种状态。构造方法中也包含了这样的情况。

     YourInteraction、YourLifeline:和状态图类似,这是描述过程图的类。这里面方法很简单,因为本次作业针对状态图的询问本身就不是很多。

      这次新增的东西全部都是Your打头,我这样做的原因是防止和上次的内容搞混,毕竟两部分内容是相对独立的,我也不愿意一打一个字母“M”就出来一大堆东西吧。然而这次打一个字母“U”仍旧会出来一大堆东西……那么,这次的结果如何呢?

       OHHHHHHHHHHHHHHHHHHHH!这次的结果非常好!其实应该归功于这次较为详细的样例,那两个样例帮我找出了多个错误,如果不经过样例直接交的话,恐怕就要出问题了。

    1.3 第三次作业

      第三次作业时已经濒临考期,但我依然保持着良好的敲代码手感。但是,说好的只有两次作业呢?

      这次作业增加了对于“模型有效性检查”的设定,类似于第一单元第二、第三次作业的WRONG FORMAT判定,当模型的生成不符合某些要求时,便不会再进行询问,而是直接输出对应的错误信息。这次作业我并没有“主动”新增任何一个类,唯一新增的类是由于CheckStyle不让文件超过500行而强行将一个类拆成了两个类(伪·工厂模式),我直接从这次测试的结果来分析吧。

       这次的强测,老实说还是有点小翻车的,错了两个点(而且并非同质bug,在bug修复环节还要额外被扣分),那么错了哪两个点呢?

     

       就是这样,对强测数据进行分析才发现,第二个测试点看上去只是普通的类继承,其中涉及到了多个类的循环继承问题。我在检测循环继承的过程中,剪枝时发生了错误,把不该进入“环”里的算作了在环里,这就导致了这个点WA掉的悲剧。第八个测试点本应输出正确的询问结果(不应有错),但我的输出却报了008错误(一个起始类只能有一个状态迁出),这是因为,我在检查008的时候没考虑到有多个状态机的情况!生成器每读到一个状态转移,如果涉及到初始状态,就直接将一个公共变量+1,这就导致了同时存在两个或两个以上状态机的初始状态时,会报出原本不该报的008错误。

    二、全单元总结——在点滴中进步

    2.1 架构设计演进与OO方法理解

      在第一单元的作业中,由于一直以来积累的面向过程思想已经根深蒂固,在第一次作业中我几乎是完全面向过程去编写,写了一个相当大的Main函数,类几乎作为结构体来使用。在我第一次博客作业中也有提到:“从复杂度分析结果来看,第一次作业我仍旧使用面向过程的思想,MainClass的负担很重,另外两个类我也只是把它当成“结构体”来使用,面向对象语言的优点无法得以发挥。尤其是主类中的chuli方法,字符自动机处理的过程很长,使用到了许多行的代码,在编写过程中曾一度超过60行触发Checkstyle警告。”下图就展示了我第一次作业中超复杂的main↓↓

      第二单元,电梯作业本身属于较难的作业,所以对Java和面向对象思想的理解就显得尤为重要。由于要使用多线程的方式完成任务,这就使得一Main到底的做法变得完全不适用。但是据说有人在互测中还是找到了一Main到底的代码,怎么做到的?就很离谱。这一单元,我充分了解了面向对象的机制,已经基本没有过于冗长的类和方法了。而且因为我稍微有一点强迫症,Checkstyle不拿100分就不行,所以我每次都根据Checkstyle的建议避免太长的方法和不规范的命名。

      第三单元,虽然表面上是JML,但其实是考算法。由于第三单元作业需要依赖官方接口,你自己的类就必须一定程度上按照官方接口去编。换句话说,这次你想用面向过程的方法都不行了。由于有很多个类,所以这次需要考虑类与类的协调,“面向对象”味更浓了。

      第四单元,到了这一单元,我已经完全变成了面向对象的形状。遇到需要处理的数据时,第一反应不是写一个复杂的方法,而是建立一个适当的类去解决问题;类并不是被当成结构体来使用,而是各有各的方法,合理调用,合理构造。各个类真正形成了一个有机整体,这才是“面向对象编程”

    2.2 测试理解与实践改进

      测试这东西倒是和面向对象关系不大,即使是面向过程的语言也需要充分的测试以保证自己程序的正确性。事实上,在大一一年《程设》和《数据结构》的学习中,我已经掌握了一些测试的技巧。下面,我就来谈一下自己对测试的理解和改进。

      第一单元,第一单元是设计表达式求导的算法,在这一单元中,输入数据只有少少的一行,而输出数据同样只有一行。这就使得测试工作非常好进行。除了手动测试外,我还设计了自动评测机来辅助评测与互测,并且想方设法修改算法试图在保证正确性的前提下拿到更高的效率分。

      第二单元,这一单元是非常有特点的一个单元,由于涉及到多线程,这一单元的测试变得和其它单元整个不一样了:数据需要在指定的时间输入,而不是一次性瞬间输入;输出也是根据输入进行实时的输出。同时,不同的调度方法也使得大家的测试数据千奇百怪,无法通过对拍判断程序的正确性。这就使得测试的难度变得相当大。但是,我还是尽我所能,通过延长电梯运行时间的方式实现“假装”实时输入,通过缩短电梯运行时间的方式进行竞争测试和线程安全测试,最终得到了不错的结果。

      第三单元,这一单元又回到了类似第一单元那样的测试:一次性输入,一次性输出。然而,由于这次的重点是在算法,这就导致了对程序效率问题的检验。对此,手动生成几千行数据显然也不现实。所以我还是构造了数据生成器,用数据生成器来检验程序的正确性和效率,最终虽然翻了一次车,但至少通过了每次的中测和部分强测。其实,我在测试的过程中已经越来越熟练了。

    2.3 几次作业的难度评级

      以10分制评定难度的话,这四个单元共十二次作业的难度评级如下:

       其中,第一单元作业的难度属于基础级别(当然想拿高性能分的话就难了),难度也是稳步上升。

      第二单元作业,开幕雷击,多线程的线程安全问题曾经差点要了我的命。但是好在之后的难度上升幅度并不高,只要对多线程理解充分,就能完成后面的任务。

      第三单元作业,第一次作业可以算是在完成第二单元后的一个小“福利”,但后面作业的难度随着算法难度的上升而上升。

      第四单元作业,难度主要集中在对题目和官方包的理解,难度高于第三单元,但总体来说并没有第二单元高。

    三、三个愿望(给课程组的改进建议)

    3.1 性能!性能!逼死强迫症系列

      在前两次作业中,涉及到了性能分的评定。众所周知,一般来说,性能分的高低反映了程序的好坏,但是我认为作业的性能分不应该以“性能最好的同学”的分数作为基准点,而是应该以标程或“一个事先规定的值”作为基准点。因为,不同学生的代码不同,有些代码可能善于处理这种情况,有些代码可能善于处理那种情况,同时电梯数据的随机性也使得在某个点性能高的程序不一定在另外的数据点表现出色。

      逼死强迫症系列:这种分数直接给100它不香吗?

     

    3.2 中测不够强!强测翻车没商量

      在第三单元的作业中,普遍出现了中测强度不够的现象。虽然,课程组想让我们不交无效作业的好意我们心领了,但是如果是这样的话,你弱测弱一点不就好了嘛,中测如果也弱的话,就会直接导致有些bug不好测试,而最终引发强测翻车的惨剧。希望以后不仅是强测数据能够有梯度,中测的数据也要有梯度。至少不要出现下面的状况:

      

    3.3 实验多少分?提心吊胆吓死人

      做了这么多的作业,是不是差点忘了还有实验这种东西?没错,我们每次都在为了互测那1-2分而拼命刀人,为了强测那4-5分而大呼翻车,可是又有谁真正关注分数占比更高的实验呢?虽然,实验不出分可能确实有不出分的道理,但是如果实验不出分,大家就不能知道自身这一阶段的学习结果,也就不能知道自己究竟是否掌握了课程的学习。而且,不出分总会给人一种提心吊胆的感觉,害怕自己因为某次实验的翻车而导致最终不能获得一个好结果。所以,建议以后实验还是给出适当的反馈结果吧,就算不出分,适当的反馈也能让我们的心里踏实一些。

    最后,线上学习的心得体会?大可不必再专门开一个栏目去谈了。我的感受,想说的东西,已经充分分散在这次博客以及前三次博客作业当中了。至于线上学习,我认为,这种线下作业相关性超强的科目,线上形式其实和课堂上课的效果相差无几,只要老师和助教的工作到位,答疑充分,最后一样能收获很好的结果。OO课程的学习即将落下帷幕,让我们和它挥手告别吧!

    GoodBye,OO!

  • 相关阅读:
    Path 环境变量
    Scala_ 类_可见性
    ubuntu16.04 注意特别出
    Python基础之文件操作
    python之set集合操作
    python数据类型之字典操作
    python的数据类型之列表list
    Python的条件控制及循环
    使用jmeter做接口测试
    AMD64 专业名词缩写
  • 原文地址:https://www.cnblogs.com/yuanshaohan/p/OO_BlogHomeWork_Unit4.html
Copyright © 2011-2022 走看看