你轻轻地走了
一、架构设计
(1)第一次作业
类图
复杂度分析
如上图是本单元第一次作业的架构设计,由于本人最开始未发现可以直接继承官方的类,所以自己将所用到的各种type都重新建了类,于是这就导致了整个src里面看起来十分臃肿。不过这样做的好处是完全理解自己的类中应该放什么,不应该放什么。并且大部分类都是比较重复的存取id和name,操作比较简单,所以写起来的感觉还不是很坏。
我觉得在本次作业中,比较难写出来或者比较容易错的方法都是需要统计包含自己父类中的操作或者属性的方法。这样就要求在书写程序的时候使用递归或者dfs、bfs等算法,来寻求到父类中所存的属性等。由于我将各个类的属性与操作等全部存到了Umlclass类中,所以之需要按部就班的跑一个dfs就可以统计到它对应的所有父类中的属性或操作。
这里有一个比较烦的点就是,接口是可以多继承的,所以在实现的时候需要对dfs进行遍历,增加了程序的复杂度,甚至还一度担心可能会超时。
总之本次作业第一次写完之后,就几乎没有bug,只是有一个方法理解错了,不过好在有对拍的存在,然后找到了就直接改了,所以十分的稳。在架构上觉得已经初步理解了面向对象的思想,比较好的进行了类与类的解耦。
(2)第二次作业
类图
复杂度分析
以上是第二次作业的类图即复杂度。
从上面可以直观的看出,我建了25个类,这也是由于没有继承官方类的缘故。而且我不得不将对UML类图分析与顺序图和状态图分开,不然单个类的代码行数就会超过限制,而反观我的朋友却没有这样的问题,可以看出我在架构设计上还不是很熟练,我认为的问题有,为减少方法行数而将一个方法可以实现的功能拆解到好几个中,而且由于没有继承官方类,冗余重复的方法比较多,所以导致了src的类有25个,显得十分臃肿,如果之后还要做有这样需求需要仔细研究一下官方类之后再去设计自己的架构,不然就会越写类越多。
从本次指导书中分析,可以说涉及到顺序图和状态图的部分已经被课程组大大的简化了,估计是考虑到同学们的烤漆时间不太充足,里面涉及到的六个方法,只要理解正确统计的是哪个type,就只是数数而已,可以说是十分良心的作业了。但是由于数据限制的问题,我也想了很久才去写,如果没有那些数据限制,实际上还有很多的细节需要去考虑,这里就留给优秀的窝窝助教,对下一届进行惨无人道的鞭挞吧。
至于对于类图的检查部分,这里确实是十分容易出现bug的,R001还比较容易,R002继承循环就有比较大的问题,最开始是考虑跑dfs,直接记录路过的路径,然后直接得到一圈数据,后来经过朋友提醒,可以用for循环,一次只得到一个数据,这样做虽然复杂度上升了,但是比较好写。同理,对于类也是这样,只不过在处理的时候,由于多继承的存在,复杂度再次上升,好在数据不是那么强,所以才得以幸存。
我觉得最难的就是R003的检测,额,也不能说是难,就是想比较简洁的写出来,复杂度爆高(指循环dfs找类,在每一个类实现的接口进行dfs找其继承的接口,看访问次数,如果大于等于2那就说明重复继承了),其它的倒是还好,看了一下强测跑的秒数,最慢的1.3s,最快的也1s,和朋友一比稍显逊色。这就说明自己设计的方法只是求写起来比较简易,而没有考虑性能的问题(还好没有性能分)。
(3)总结
总的来说,这两次作业虽然都和烤漆离得比较近,而且写起来也比较费时间,但是都满分还是比较不错的回报,这两次的架构是真切的体会到了面向对象进行解耦的好处。因为我两次作业都和朋友去对拍,然后发现了bug之后,觉得十分好改,而且改了之后完全不担心其它的功能会因此出错,因为两者完全不相关,所以说,至此可能面向对象才算入门吧,这单元也是我历次作业中觉得自己架构设计的最好的一次,终于由完全的面向过程,转向了面向对象。
二、架构设计及OO方法理解的演进
(1)第一单元
这个单元是刚开始写java代码,上来就是十分难受的字符串处理,而且还加入了wf的问题,我觉得这点对OO新手来说不是很友好,尤其是第三次作业,嵌套求导让我这个面向过程选手直接推倒,完全重写,花费了十个小时之多,不过好在没有出现bug,不然就亏大发了。
因为那时候刚刚接触面向对象,本着偷懒的原则,没有细细去理解,于是写的就完全是面向过程,一两个类打天下,过后再回去看自己的代码真的是惨不忍睹。如果稍微改一下需求就需要完全推导重来。
如果当时就理解了面向对象的思维的话,或许我会分解成x类,sin类,cos类等,进行解耦,来获得更好的顺延作业体验。
我印象最深的就是,把功能完全实现了之后,疯狂拆自己代码中的方法,看哪里能拆,就分出另一个方法,不然就会出现checkstyle问题,这更可以说明自己当时的码力十分的弱。
(2)第二单元
这个单元是多线程,感觉也是理解起来比较费解的一个部分,因为输出是不确定顺序的,有的时候bug完全无法定位,不过好在实现了代码之后就没发现bug,不然写起来真的是恶心。
可能是由于要训练多线程,而且考虑到大家刚接触,电梯的要求其实还不算困难,只需要很少的代码就可以实现。
我也是在这时候才体会到,不需要完全推到重来的代码有多么舒服。第二次的电梯可以经过少量的修改直接应用到第三次中,这里就运用到了解耦的思维,只需要把控制器调度的代码进行少量的修改,就可以实现所要求的功能,而且性能也不算很差。本单元可以说是我写的最舒服的一次作业,总用时也最少,加在一起的时间甚至还没有其它单元最后一次作业用的时间多。
(3)第三单元
这个单元是对于图的理解(数据结构还债课)
为了完成本单元最后一次作业,我成功的自学了dfs,bfs,floyd,dijkstra等一系列图的算法,这在当时的DS中都是直接抄PPT模板就完事了。
最难的是第三次作业,前两次并没有什么难度,最开始的时候,确实不清楚应该如何去实现最少票价和最少不满意度,看了讨论区大佬的帖子之后才知道只需要把权重矩阵修改,把连接修改,就可以通过bfs来得到了票价和路径,可由于用floyd是一次性更新整个图,而我当时架构设计必须使用floyd,经过计算,复杂度绝对会导致自己超时,想了很久不知道应该怎么办,还是经人提醒,才明白加入一个cache就可以了,把之前更新过的矩阵存起来就行。这可以看出我对于代码的思维能力还有些欠缺,在其它地方学到的知识无法很好的融会贯通。
不过这次的架构 也还可以,修改也比较容易,我重构了第三次作业三次,这点十分不友好,十分爆肝。
(4)第四单元
具体分析在之前的一中已经分析过了,这里不再赘述
(5)演进总结
可以说从第一次的表达式求导中的纯面向过程,逐渐转向了面向对象,这经历了一整个学期,速度不是很快,但好在最后还是稍稍理解了面向对象究竟是怎么一回事,也算自己没有白上这个课。
我深刻的体会到了OO的方式写代码,在发现自己bug时,可以十分容易的就去修改。而之前和别人对拍过的不出错的功能可以不用再重复检测,之需要面出现bug的部分修改就可以了。而面向过程如果需要去修改bug,甚至可能把整个代码推倒重来。这四个单元确实让我对面向对象思路从最开始的抗拒,到逐渐接受,再到现在觉得这简直是精品。
变化还是很大的,希望自己可以把面向对象的思路应用到以后的写代码中吧。
还有一点值得注意的就是对于变量的命名问题,由于第四单元最后一次作业我涉及的类比较多,所以对于变量的命名十分具有迷惑性,我在改bug的时候差点就迷惑了,就得先看代码才能知道当前变量是做什么用的,这点是在架构设计中做的不太好的地方,之后要改进。
三、测试的演进
首先我觉得课程组所讲的各种测试方法,比如从最基础的读代码找bug,应用看嵌套之类的技巧,到用junit生成测试样例进行半自动化测试,都是十分不错的测试代码功能正确性的方法。不过在我们课程这样密集的作业和debug和互测节奏中,这样并不是很快速的测试方法并不是很友好,可能你在电脑屏幕前盯了一天,修改了很久junit,只找出了几个甚至一个bug,这对于自己时间的浪费与得分的比值是十分不值得的,如果唯分数论的话,这样的测试比较拖慢节奏。不过我相信,课程组所教的方法都是以后在工作过程中真正要应用的方法。我本人每次测试都是使用了对拍,和同学的程序,或者自己写的python程序去对拍,以此来发现自己的bug,或者是互测找别人的bug,挂几个小时就可以收获好几个bug,在时间效率上还是很不错的,虽然这样失去了认真发现别人bug的机会,但是在闲暇时刻,读读架构比较好的大佬的代码,也是可以精进自己的思维的。我个人比较推崇针对不同的情况用不同的测试方式,比如说对于这种密集作业型来说,就适合用对拍来解决,所以我也是这样做的,而对于之后工作上的代码,并不可能让别人的程序和自己的功能性做对拍,而且也大多数是交互情况的代码,十分不容易去写出对拍,这时候就能应用到课程组推荐的方法了。所以我认为,没有最好的方法,只有最适合的方法。
四、课程的收获
我觉得课程给我最大的收获是如何写出优美的对拍程序(误)
之前也分析过了,从面向过程的C编程法,到现在的面向对象的java编程法,我觉得自己编程的思路上面有了很大的拓展。而且之前写的程序代码行数都比较短,以至于写出第一单元的作业的时候还惊叹了下,作业代码行数怎么这么多,好几百行,后来就逐渐习惯了越来越多的代码行数,越来越大的压力。可以说这个课程带给我的不光是编程思维的改变,还有对于压力的抗受能力,从最开始写几百行就觉得十分疲惫,到现在连续写一两千行也觉得是洒洒水,我想这确实可以表现我的蜕变。
回顾一下各个单元,第一单元的时候,刚开始学习写java代码,只经历了寒假作业比较简单的培训,就直接去写几百行的大程序,最开始确实有些吃不消,当时还在和冯如杯做斗争,所以还有挺大怨言的。写第三次作业的时候差点自闭,因为那周周六得去答辩,得从周日开始写,最开始还没什么思路,不过好在都过去了。
之后到了多线程,因为上课时候只是从理论上知道了多线程的相关知识,但是没有从实践上真的去写还是不行,引用之前数据结构老师的一句话“learning by doing”,对于编程这一课,确实不能只停留在理论上,而更应该动手去做。第二单元的第一次作业还摸了鱼,并没有用多线程去写,然后第二次作业成功还债。不过由于为了让我们体会多线程而降低了难度,还是比较容易完成的一个单元。
在之后就是数据结构和图论还债课,正好是这个单元刚开始,家里出了点事情,心态完全爆炸,于是每次就等着问别人的思路,然后草草写完,再写个对拍就不管了,所以这个单元感觉做的比较失败,虽然全部正确,但是对这个单元的印象最浅,感觉并没有学到什么东西,只是把以前的东西进行了复习。
最后一个单元的作业和烤漆纠缠在一起,不过好在课程组帮我们进行了延期,不然我甚至可能都不会去写本单元的最后一次作业了。在考马原的前一天,和朋友进行了对拍,找到了自己的一个bug,不过后来发现是因为课程组限定了不会出现那种情况,而我朋友的代码处理了,我的没处理,无伤大雅。
这一个学期下来,收获了很多,有过开心,也有过痛苦,不过总归是还算圆满的完成了自己的工作,也希望OO课程可以越办越好吧。
五、建议
询问过学长之后,发现今年的OO课程进行的改进十分的巨大,其中比较好的部分就是,在互刀的狼人阶段,不用完全靠助教仲裁,而是采取更科学的评测机方法,让人信服,观感很好。
但是,OO经常被挂在知乎上,我觉得也是有原因的,虽然可以说是人无完人,课程组也尽力了,没有办法尽善尽美,但是我觉得确实还有一些问题需要提起课程组的注意。
首先是对于延期的问题,第一单元第三次作业,仅仅是因为有很多同学没写完就去延期,这完全不符合公平的原则,对于全部正确的同学可能无所谓,但是对于出现了bug的同学,这样的延期可能导致排名下降,分数下降,我相信课程组是为了大多数人着想,但是反过来想,为什么不能让不能按时完成任务的人得到应有的惩罚呢?难道以后去工作了,老板会很宽容的原谅你没有按时完成任务吗?我觉得对于这种事情,课程组还需要再斟酌斟酌。
其次是对于指导书描述的问题,从第四单元最后一次作业可以看出来,对于数据描述的不清晰,很可能导致同学们无法书写代码,因为可能理解不同,就得把代码整个推倒重写。当然,课程组肯定无法在发出指导书之前就能考虑到所有的问题,但是我希望在每次指导书发出来之前,课程组可以进行内部讨论,看看针对指导书可能出现什么样的情况,对数据进行规范化,就好像第一单元作业那样,十分严谨的写出了表达式的定义,这就让同学们可以更快更好的上手。
最后是希望有可能的话,调整一下作业的顺序,或者调整一下作业的结构。就拿本学期的课程来说,没有学过java的人,上来就开始写一个大型的表达式求导程序,那估计大部分人都会直接选择自己更熟悉的面向过程方式,这样这个单元的作业就失去了对于面向对象训练的意义,如果在开始的时候,进行类似于完形填空,补全方法一样的面向对象训练,在第一单元最后一次作业再让同学们完全由自己书写面向对象的代码,可能会让同学们更加容易接受面向对象的思想一点。
窝窝课程已经落幕,而我们仍需继续前进,希望窝窝课程越办越好,也希望我们越来越好。
正如你轻轻地来