Fate/Beihang OO最终话——第四单元总结 & 课程总结

Fate/Beihang OO——第四单元总结 & 课程总结

一、第四单元架构设计

在本次作业中,我三次作业迭代发展,使用同一架构体系。我没有构建图结构,而是使用了比较非主流的思路。

在作业之初,我的想法是让所有查询操作的复杂度尽量保持在O(1)。也就是预先储存好所有需要的数据,在输入后就进行所有处理而不用进行遍历。大概是第三单无TLE怕了。再加上,本单元均只有一次性输入,也就是说,只要我在输入后处理得当,就可以省去许多麻烦。事实上也确实如此,我的三次作业都写得顺风顺水,只是在第三次作业中掉以轻心犯下了一些细节性的错误。

以类图为例,我的架构大体如下:

  • 构造适配器,将所有能做parent的类型扩充,以储存各类信息

  • 在构造函数中,将所有Element分类,将有适配器的类“安上”适配器,再按照先子再父的顺序分别处理

  • 在处理每个元素时注意维护需要的量,如每个Attribute更新可见性计数器

  • 对于继承 实现 关联 属性等涉及父类继承(或者说图结构)的元素,采取记录其所有子孙及父辈的策略,而不是记录图结构。在处理继承关系时,只需将子类及子类sons集合增加到在父类及父类的fathers集合的sons中,对子类处理类似

如此,便可以在保证正确性的情况下降低复杂度,同时避开图的各种复杂算法。

同时,在第三次作业中查错也能占到很大的便宜。对于找环与找重复,均不需要任何算法:

  • 找环:sons集合中是否包含自己
  • 找重复:在构建继承时检查fathers中是否已含将增添进去的元素,及将要增添进去的元素是否已继承重复(我在第三次作业中的一个错误就是忘了后面这种情况)

如此一来,增加方法的工作量就很小,只需要在构造各种元素时进行处理即可。

为了避免构造器过于臃肿,我将构造过程单独成了一个类,并让MyUml继承,以起到(伪)解耦的效果。

最主要的目的是避免超过500行的50分che'ckstyle扣分

第二次与第三次作业的构造依然按照以上思路。

总体来说,我对自己的第四单元作业比较满意,要是第三次作业没有失误,那将是最完美的句点了。

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

面向对象的关键就是理解“对象”。在我看来,OO的关键其实就是讲究一个“各司其职”。面向对象仍然离不开过程。类和方法提供了解决问题的方法,而解决问题还是需要调度这些方法,这个“调度”就是面向过程。我们在OO课上要学到的就是将过程“抽象化”为一个一个的类与方法,最后适当地组合起来,解决一个个问题。

第一单元

第一单元可谓开头难。在这一单元中,我还基本没有理解什么叫“对象”,甚至连JAVA的语法都没有掌握熟练,所以我重构了三次代码,工作量巨大。这一章中,我对OO的理解大概就只有“类”这个概念。我将类与C语言中的结构体作比,认为其就是封装了一些函数的结构体。我的写法也基本基于过程,导致难以迭代。

在这一章中,我基本是在熟悉JAVA的语法(在pro中基本功没打牢)。继承、多态,这些我基本在第三次作业才摸清楚。

第二单元

这一单元是多线程,OO祖传电梯惊魂,我也毫不意外地写出了一万个死锁。经过了第一单元的惨痛教训,这一次我使用了一个具有可延展性的架构,一次也没有重构(事实上,除了第一单元都没有重构)。

这一单元最主要的是对多线程的安全性进行考虑,而这也更突出了一个“各司其职”的思想。想要避免死锁,就必须要理清楚架构,顺清楚各个部分的分工,弄清楚其对灵界区资源的利用,这才能有效防止死锁。

在这一章,我在JAVA语法上留下的坑基本就只剩下对异常、抛出等概念的理解了。当然,在第三单无中这些也顺理成章就理解了,不成什么问题。

至于对于OO的理解,可能与现在并没有太大的差别了。这时我已经初步理解到了“抽象化”的含义。

第三单无

这一单元是JML规格,在架构思考上比起前两单元要轻松得多。事实上,我更愿意将这一单元称为数据结构图论章节。对JML规格理解的不完善反而是细枝末节,图的各种算法才叫人头大,难免让人有种本末倒置的不适感。

JML事实上就是一种抽象思想:我们不需要关心实现的具体过程,只需要实现每个功能即可,而OO就是将一个任务不停向下抽象,直至最后的类、方法,我们只要保证每个类与方法层层架构能实现最终功能,最后再实现类与方法就好。

第四单元

这一单元是对UML图的教学,但做完三次作业后我对UML的了解仍然是一知半解,所以也没有什么理解可言。至于架构如前文所述,这里不再赘述。

对于OO的理解,这一章更像是在复习以前的知识,用UML这种方式让我们直观地理解面向对象各种元素的结构。


总体而言,面向对象课程让我明白了分工的重要性与架构的重要性,这是做好一个大工程的基础功夫。

三、测试理解与实践的演进

测试是写代码中一个很重要的部分,充分的测试才能在更大程度上保证一个程序的正确性。

碍于不会PY与对JAVA的不熟练,再加上自己没有动力学习,这门课程的所有课程都是手动进行。

第一单元

手撸数据,手算结果,自己构造压力数据和边缘数据测试。不过这也限于互测,自测阶段的测试因为时间和精力原因进行地不是很到位。这显然也是一种舍本求末的表现

第二单元

因为数据需要按时间输入,故不会写投放机的我基本没有一个好的测试方式,形式化验证成为主要的手段。静态测试和随机压力测试就是最大的测试手段。因为不方便构造数据,所以自测做得一塌糊涂,这也导致两次没有进互测的惨剧发生

唯一一次进互测阶段的数据基本仰仗朋友的援助。

第三单无

这一单元的测试主要是基本功能测试与压力测试两部分。基本功能测试主要靠样例测试法和手动构造法,手动构造可以兼顾一些刁钻的情况。而压力测试全靠朋友们给的数据(hack也用的那些数据,很香)。

JML单元当然要用JML,不过因为太麻烦了所以也没怎么用。

不过这一单元除了后面的图论也没什么特别大的坑,手动构造足矣。

第四单元

出于对UML理解的不到位与期末大作业的压力,这一单元采用形式验证法为主,样例测试法为辅的方式,甚至没有自己画图构造数据。因为没有互测,也可以少考虑很多幺蛾子。


综上所述,我的测试方法丝毫没有演进,甚至可以说在退化。这也是我不太上心的一个证明,实在惭愧。不过在想法方面,基本还是秉持着基础、边缘、压力的原则,我认为还是挺到位的。

形式验证法万岁!

四、课程收获

不得不说,OO课程是一门很好的课。作为一个程序员,在写OO代码的时候感受到了十足的快感——大概我们都喜欢逻辑清晰整齐的东西吧。

  • 以课程为契机学习了JAVA语言的基础
  • 学习了面向对象思想,学习了抽象化架构,学会了在解决工程问题前先思考架构与课拓展性的方法
  • 在一定程度上认识到了数据结构选取的重要性(特别是JAVA中种种容器)
  • 认识到了用心的重要性
    • 细节的重要性
    • 深切体会到了测试的重要性与不赶DDL的重要性
  • 对结构化、抽象化、模块化等思想有了更深的认识

五、改进建议

  • 第三单无可适当修改,如删去第三次作业,改为加大大一DS难度。JML单元考察内容有走题之嫌,特别第三次作业考察内容基本是图论考察,有些本末倒置之感。
  • 第三单无的工具链改进,博客的要求可删去工具链一栏。JML本就年久失修,在网上找资料也基本是北航6系前辈的脚步,这足以说明此工具以落后于潮流。课程组可以考虑换成其他方式进行课程。至于其他工具,如OpenJML、JMLUnit等等,更是配置时间远大于使用时间,且使用出来也并没有给我带来什么收获,有种非常形式主义的感觉。
  • 建议在pre课程中增加对JAVA的讲解,或者至少重要知识点的讲解,特别是与C语言不同的地方。我在面对继承、多态等时吃了不少亏。虽然pre中多面体有关于这些的运用,但我当时也完全没有使用多态、继承,自然对知识点也是云里雾里飘飘然。
  • 奇怪的建议:建议在BUG修复 非合并修复 中增加 BUG数量 填空项。之前因为几个BUG无论哪一个不修改都无法通过任一测试点,可又不可能选择非合并修复导致全部爆炸,只得选择了合并并在文档中注明了原因

六、线上OO体会

曾与亲朋好友笑谈,计算机学院的学生在家学习压力丝毫未减。如果说OS还少了课上,那站在学生的角度,OO基本就没有受疫情的影响了。每周照样爆肝,该熬的夜一夜不少,该掉的头发照样掉。特别对于我这种倾向于自学的学生来说,线上学习更是没有什么不适应的地方。不过比较遗憾的是没有了在宿舍一起爆肝的融洽气氛,这么一想还有点怀念去年计组呢(远目)。

这一学期来,我的收获很大,真的很感谢助教和老师的辛勤付出,这门课的课程组做出的努力大家都是有目共睹的。我可以自信地说:我爱这门课。


这样,BUAA2020的圣杯战争便划上了句号。结局?谁知道呢(笑),那是全AK大佬们战(nei)斗(juan)的地方,和我等混子又什么关系。

posted @ 2020-06-16 01:58  kumo  阅读(205)  评论(0)    收藏  举报