• OO第四次博客作业(第四单元作业及期末总结)


    (注意:本文写作顺序与作业要求不完全一致,但涵盖了作业的所有要求)

      一学期的BUAA特色OO课程结束了。

    PART 1  我想先写我这一学期的感想

      从第一单元满怀期待地写完多项式求值到最后看着60分不到的成绩伤心欲绝(这个词用的其实并不是特别夸张),到第二单元作业在截止前两小时还在做不停地思考和调试,再到第三单元在活页纸上记下一种又一种可能的实现方法(然后还有一堆bug2333),最后到第四单元,也就是这个单元的与考期共舞,与程序广度作斗争,每个单元都是你从未玩过的船新版本(因为OO课程改革所以还真的是船新版本),每一次作业都带来完全不同的体验。虽然写作业的期间,不仅是我,好多人面对满屏的代码和各种各样毫无逻辑的bug陷入自闭,但一旦挺过来,回头一想,自己确实完成了一些规模比较大,架构较为复杂的项目,而且是在比较短的时间限制内完成的,虽然还是不能从根本上改变咸鱼本鱼的本质,但至少算是做了比较大的努力,实现了一些以前自己不敢想的事情吧。从一学期的OO课程一步步走过来,回过头发现,自己真的走过了一段很远的路了。

    PART 2  写完感想再写一写对OO课的祝愿,感觉这样行文比较流畅

      之前的博客作业没少发过牢骚了,这一次,作为课程的结束,想发自内心祝愿这门课在以后能越来越好,能为学弟学妹们提供更好的指导作用。虽然,按当今的社会状况,不要说一门课,通过整个大学阶段的学习,也很难从本质上改变乃至塑造一个成功的人,就好比只能对一棵已经长成的树做一些修修剪剪,而不能从一棵小树变成一棵参天大树。但是,我还是希望,哪怕只是想象一下,让学了这门课的学生,至少有一个自信,他能够胜任一些中小型的企业工程项目(更激进一点的想法,应该是大中型),有能力去企业做一些相关的实习,更好地与未来的工作相接轨,而不要让他们感觉自己无论学没学,都还是一条不中用的咸鱼。

      如果说具体做法,首先既然谈到实习,那如果有可能的话,可以真的为学生提供哪怕只是一周,或者一个中型Project的实习机会,去与工业界最亲密地接轨。可能对于相当一部分人(也包括我),还是需要以类似于作业的形式进行逼迫(或者说被动)式的学习才能真的吸收一些东西,既然这样,那把他们置身于工业界,置身于职场,在那种紧张的环境下,可能是对他们更加直接的逼迫,让他们感受到从构思到测试以至release的每一环节的不可或缺,全过程地感受“钢铁是如何炼成的”,这里的钢铁当然是代码的“钢筋铁骨”。限于条件,也可以进行类似于工业环境的模拟,但总归是差了点感觉,尤其是在测试的迫切性上。感觉只有置身于工业级的程序发布环节之前,才有那种必须不断、反复进行测试的必要性和紧迫性,才会真的想去一遍又一遍地进行各种测试。

      另外,如果局限于作业的形式,我觉得我们写的程序虽然在难度上真的不低,但距离一个真正由现实用户使用的程序,还差了一个难度上不大,但对绝大多数程序都不可或缺的环节——图形用户界面GUI。虽然一般的程序设计课上,不太可能单独掏出一个板块来讲解GUI的设计,但我们BUAA的OO本来就不是一般的程序设计课,它是基于project来实践练习的课程,既然如此,何不让课程内容覆盖更加完整,来一学期”从内到外“的面向对象编程练习呢?个人甚至脑补了一个具体的实现方式:在project总数不变的情况下,把JML第一、二次作业合并,挤出一个做GUI作业的project(个人感觉,在工业上与学术界广泛使用的UML,比实际用的不多的JML反而少一个project,本身就不怎么合理,感觉UML是一张真正的蓝图,而JML更像是一种玩具),在最后一次作业中完成一个GUI的设计。测试时如果无法实现机评,就用人工检测的方法,检测程序是否能够通过图形界面操作,实现对应的功能。这样一来整个project的难度其实会相对简单一些,一定程度上减小了烤漆复习的压力。还可以采用比较特别的性能分区分方式{比如按UI美观程度给分,当然不要太过分,只要不是BAD UI就拉满),给之前单元学到快自闭的咸鱼们一个翻身的机会,毕竟作为一门课程,给予学生充分的自信心是必要的,总不能让人一直coding司马脸,debugging司马脸吧。

      上面的建议可能太过空想化,仅仅作为我个人的一点祝愿写在这里吧。另外一些细枝末节的建议,就是尽量让每次指导书的要求明确一些,不要有bug或者含混不清的地方吧。当然这个事情是不能强求的,我自己写的程序都有一堆bug,又有什么资格苛求别人呢。

      (以上三段在统计时每段算做一个建议吧,太长看不过来的话)

    PART 3  回归本单元作业

      两次作业放在一起讲吧,懒得分段了,何况它们是包含而不是并列关系。

      这单元的作业,从难度上可能不是特别大,但广度上真可谓无可匹敌。先是关于UML类图的各种操作,后又扩展到顺序图和状态图,还要实现对类图的基本规则验证。这就直接导致了一个结果:最后一次作业的代码量远超之前任何一次作业,成为爆肝的有力见证

      一开始我想直接采取遍历输入的方式实现每个功能的操作,结果证明行不通(这不是必然的吗?)。之后便老老实实地按UML结构建立了保存类模型的struct,从class,到attribute、operation,再到parameter,一级一级建立起来一个完整的结构,也就意味着说初始化的时候要遍历至少三次输入。类和接口采用同一个结构模型,只用了一个boolean变量来区分二者。对于继承、实现、关联等各种各样的关系,采用两头区分的方法,以继承为例,有一个保存父类的ArrayLIst AppendFromList,也有一个保存子类的ArrayLIst AppendByLIst,这样就将所有的输入信息转化为便于处理的,类似于图的结构了。对于UML顺序图和UML状态图,我也采用了类似的处理方式。实际上,这次作业中相当的码量和时间,耗费在了结构的构造和构造方法的书写上。

    既然这单元学的是UML,那我就导出一个超级大的UML类图放在这里吧(手动滑稽)

      代码的核心逻辑部分,我觉得自己真的是吃了数据结构,尤其是图的部分没学好的亏,总是出问题,出各种问题,害得我半夜3点又烧脑又爆肝地debug。就算我投入了大量精力思考导致bug的原因,就算最后一次作业要求已经简化,强测的bug最后还是出在了图结构上。第一次的bug没什么好说的,没完成指导书要求(还真不是没看,解决方法都想出来了,感觉自己明明写了,结果发现没有,晚了!)加上迷信指导书样例,忽略了接口重名要重复输出这一点。第二次的bug,checkForRule008改了好几次还是挂了一个点,暂时先不管了,专心把博客写完,你看又半夜12点了。

    PART4 总结四个单元架构设计和OO方法理解的演进

      因为寒假预习工作做的不错,至少在理论层面,对OO方法已经有了一定的理解。

      第一单元:理解归理解,在相当多的地方,面向对象的方法没怎么体现出来,无非是将表达式拆成了三个部分。但就是这门一分,带来了面向对象给我带来的第一份便利:化整为零,用简单、细小的部分拼凑成复杂的、庞大的部分,用简单、短小的方法去实现复杂、冗长的方法。虽然构造方法上,结构式编程的痕迹还非常明显,但封装、继承、接口实现等基本操作已经得到实现(P.S. 现在想起来第一单元作业还重复继承过接口2333),到第三次作业,已经不可能再用结构式的思维去实现,而凭借前两次作业的面向对象基础,就比较轻松地完成了。

      第二单元:与其说面向对象,不如说这一单元演练的是多线程编程的能力。可能在写的时候,并不觉得因为面向对象带来了多大的便利,不过后来证明那是因为多线程编程本身的难度,而不是面向对象方法不行(写完OS Lab4的fork函数就知道了)。这单元是最难的一个单元(虽然就这么一句话让我每次都有后面单元很简单的错觉,然后每次都写到自闭),最后一次作业更是难上加难,电梯的封装、调度器的实现、调度算法的选择、多个电梯线程与调度线程和输入线程的同步,随便一个都可以难倒一大片人。尽管最后没有难得地没bug实现了,但面向对象的程度还不够,代码耦合性比较高。

      第三单元:这次绝对是正宗的面向对象编程了,可惜封装的部分不是我们亲自完成,而是助教帮我们实现的。架构上也并不困难,就是典型的无向带权图,加上严格的卡时间限制,仿佛穿越回了一年前的数据结构课堂。但与之前不同的是,这次是采用面向对象方法实现的图结构,用更少的码量、更清晰的程序逻辑,实现了更为复杂的功能。

      第四单元:和上次类似,也是助教帮助我们进行的封装,而且这次帮得可以说更多,以至于架构占了码量的大头。而且架构实际上也有种还原UML图的意味,虽然工程量大,但难度上并不太高,甚至给了我一种再加把劲可以自己写出来个StarUML的错觉(被打醒)。

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

      简直是哪壶不开提哪壶,丢人啊。看那个翻车的表情包我真是想笑又笑不出来。

      第一单元测来测去,覆盖性不足,扑街;第二单元,借助别人写的测试工具,好歹是测出了几个重要的bug;第三单元,感觉上没问题了,但感觉这个东西真的一点都不靠谱,想做一些测试,JML跑不了,想写JUnit,发现自己不会用,根本上还是测试不充分的问题;最后一个单元,迷信指导书样例,忽略重要情况。

      由此就可以看出一个要命的问题:覆盖测试。这里指的不是代码的覆盖,而是各种情况的覆盖,说白了就是多跑几组不同的样例。覆盖测试充分的程序,bug就少或者没有;没怎么进行充分测试的程序,bug就多得令人发指。基本的功能测试和单纯的边界测试并不困难,但想要做到覆盖测试却很难,最难的一点,就是很难通过人力来进行覆盖,测来测去总漏边界情况。关键是对于一个有bug的程序,它引发bug的边界是不确定的,这是我写代码的时候最最最最头疼的一点。

  • 相关阅读:
    【leetcode】第一个只出现一次的字符
    【leetcode】0~n1中缺失的数字
    054696
    053695
    053694
    053693
    053692
    053691
    053690
    053689
  • 原文地址:https://www.cnblogs.com/P-R-E-T-T-Y/p/11071174.html
Copyright © 2020-2023  润新知