夫天地者,万物之逆旅也;光阴者,百代之过客也。而浮生若梦,为欢几何?古人秉烛夜游,良有以也。况阳春召我以烟景,大块假我以文章。会桃花之芳园,序天伦之乐事。群季俊秀,皆为惠连;吾人咏歌,独惭康乐。幽赏未已,高谈转清。开琼筵以坐花,飞羽觞而醉月。不有佳咏,何伸雅怀?如诗不成,罚依金谷酒数。
—— 李白《春夜宴从弟桃花园序》
一、第四单元总结
1.1 总论
这个单元最大的主题其实跟第三单元是一样的,就是怎么糊弄怎么来。第三单元是因为操作系统的压力,第四单元因为是烤漆,所以多有糊弄,也是没有办法的事情。除了烤漆压力外,其实题设方面也是给足了糊弄的空间,主要有以下几个方面:
- 题目设计上完全脱离了整体架构,用接口约束改成了一道道的算法题。
- 去掉了互测,所以是没有人绞尽脑汁搞别人的。
- 不再卡 TLE,所以算法的需求就变成了要跑得稳,而不是跑得快。
- 博客要求也减少了,要不我怎么敢随便胡咧咧。
但是是不是糊弄就不好了,我觉得肯定不是的,很多时候,糊弄也要有糊弄的手法,没人要求自己的 1000m 跑得要跟博尔特一样快,即使是自己的最佳状态。更何况不是每个人都喜欢跑步,都愿意跑出好成绩,糊弄才是人们做事情的常态。我个人理解的是,我们既要学习如何把一件事情做到精益求精,也要学习如何糊弄而且还能弄得差不多。而且尤其是做团队合作,本来就不能控制和要求别人去全心全意的投入,所以学会糊弄不仅是自己的事情,更是合作的事情。
接下来讲几个糊弄的要点,都是我认真踩过坑以后总结出来的,大致上是十分有用的。
1.2 知识与题目
这个单元名义上是 UML
解析器,然后我和身边的小伙伴就去看指导书了,看完指导书还不够,还要看课程组提供的手册,在看完如此晦涩的手册后,还要意犹未尽地看官方的手册。然后这些都看完,结果一做题,发现根本不沾边。
那么我们来分析一下这个错误哈,这个错误可以归结为“我对于第四单元太重视了,我要好好弄”这种自我陶醉的理由。不过其实呢?我觉得程序开发最重要的就是面向需求开发,那么到底什么是需求,需求有什么特点。那么其实可以分析一下:这个单元的背景是 UML 官方文档,然后的背景是出题人是一组人。这种背景最容易推导出来的结论就是:每个人都会对官方文档有自己的看法,他们甚至不能将一个人对于官方文档的理解出成题目,最后的题目的逻辑肯定是极其简单的,简单到让所有人没法质疑。
换句话说,这个单元的开发任务就不再是“结合 UML 知识做题”,而变成了“结合出题人搭建的框架做题”。那么显然死扣知识就变得没意思了,因为本来需求就不是知识,而是出题人搭建的模型。
我已经学了一个学期的面向对象了,居然这点没有考虑到,可谓是基本功不扎实啊。
1.3 官方包与读代码
那么确定了第一点以后,那么糊弄的解法就出来了,只看指导书和官方包,可以最快的理解出题人的模型。然后就会遇到另一个坑点。就是这回的官方包是一个冗余的包,它不仅可以用来解析标准的输入内容,它好像还可以直接解析 .mdj
文件,然后还会有一些其他的功能,这就导致这个包里真的是,啥东西都有。有的时候费劲马哈的看完一个文件,然后一看,真的是没啥用。
关于这点,我到觉得是自己的问题,毕竟以后很大概率都不能自己掌握全局,很多时候都是面对一个大项目,自己耳聋眼瞎就得写代码了。这种问题我之前也想过,然后从理智中推导出几种方法来:
- 顺着调用顺序看,比如从输入函数开始看,看输入的东西变成啥了(一般都变成比较容易管理的数据结构了),然后看这些新的东西又经过怎样的处理变成输出了。
- 按照数据结构的组织顺序看,比如先看一个管理其他数据结构的内部,然后看它管理的东西的结构,这样一级一级,一个 BFS 就看完。
- 按照题目的要求看,比如从一开始的
UMLElement
看,然后一步一步的,巴拉巴拉 - 按照包的含义看,不同的包体现了不同的逻辑思维,然后一个包下的事物一般具有某些相似性,可以很有逻辑的看出来。
然后当我逐个应用的时候,发现虽然确实自我感觉很好,觉得自己是在像一个有逻辑的人一样看代码。但是真的好慢,这些策略不是在帮我提高看代码的效率,而是在帮我特别慢的看代码速度下不着急的。
幸亏之前在 U3 的时候就犯过这些错误了,到 U4 的时候我改成了“通篇浏览 + 跟人聊天”的方式。真的是超级快。首先通篇浏览一下整个项目的结构,不用看得很细,但是最好要有笔来记录一下,然后记录完成以后就去找已经完成的人聊天,不用聊框架之类虚的东西,就直接问他怎么求解,然后聊几句大致就可以明白出题人的思路了,然后就开始实现就好了,实现的过程中不断的去矫正,基本上就没有问题。
为什么这种方法更好呢?我个人觉得是因为人们理解一个东西,其实是把各种信息在脑子中抽象出一个结构来。然后上面旧的方法就是整个将整个结构全都理解了(他们顶多算是优化了理解的速度),然后再开始动笔。但是新的方法则是需求推动的,接近于语言或者新生儿探究世界的方式,是一种顺序化的,逐步的输入,难度梯度比较平缓,所以更加容易。
1.4 评测
不出意料,又要搭建评测机了,同时又不出意料,我又搭不出来。不过经过了一个学期的打磨,我已经准备好了一套应对办法。首先,手里拿住一个最好的自动化器,然后为其名曰“合作”,骗到一个贼好用的数据生成器,然后基本上普通测试就搞定了,然后再建一个特殊样例的提交平台(不用实际建,就是到处跟别人说有好样例发给我呀,我这里有一大堆好样例,大家共享啊),这样基本上强一点的数据就搞定了。
这中间一定要就事论事,具体问题具体分析。比如面对大佬,可能资源的共享的诱惑力就没有这么大,因为大佬永远都握有资源,这个时候就需要抱大腿,乌漆嘛黑,天昏地暗地舔就完事了。对于同为菜鸡的同学,就一定要认真负责,一定要勇于分享,一定要积极检讨,一定要把评测机的难度一降再降。这样才能团结群众,充分发挥群众的力量。
1.5 算法实现
这个坑经过第三单元的训练,我这回是一点也没有踩。很多时候,算法不是复杂度越低就越好的,因为越低的算法复杂度,一般就意味着越高的空间复杂度和实现难度,就意味着很难拓展(因为很多算法的提高都利用了具体问题具体分析的办法)。
不过这回因为官方放海了,所以只要意识到“不会卡时间”这一个点,那么就可以很好的解决问题了。
1.6 架构设计
其实于哥哥在讨论区已经说得很清楚了,主要是将三种图的功能分别拆到三个类中去实现,可以有效的避免 500 行的限制。但是我看见有的人对于每个 Element
,都自己实现了一个类,那么就显得有些冗余。其实有的时候,为了实现的更快捷一些,可以考虑一些摆烂的方法,比如对于 Endpoint
可以和 Lifeline
当成一个类,InitState, State, FinalState
可以是一个类。其实这样是我在第一单元,一定不会开心的,因为这是展示继承和多态的大好机会。但是怎么说呢,我已经不是一个哪里哪里都要用面向对象来解决的菜鸟了。我觉得很多时候不是“好”最重要,而是“适合”最重要。
二、OO 课程总结
2.1 傲慢与偏见
必须承认,我在学这么课程之前就已经有了很多的其他东西。当我听到“设计模式,需求分析,博客,架构”的时候,勾起了很多我的年少轻狂。因为这门课程很多时候都是在讨论概念,讨论设计,讨论架构,讨论分类,讨论信仰。可能这对很多同学来说是很好的事情,因为可能是第一次接触,而且大家都年轻气盛,又有几人不想挥斥方遒,指点江山,乘风破浪呢?我看到很多人沉迷于架构设计,沉迷于评测机,沉迷于论道,沉迷于刀人。真的,客观的说,OO 一定是最受六系学生欢迎的课程,无论大家学得好不好,最后的博客感想都是十分感人的。
可能只有我是一个异类吧,上面说的这些东西,在我很小的时候就接触到了。我小时候是美术生,从小就是在各种架构设计中度过,每天就是琢磨出甲方的需求和怎么应付甲方。之后就是当生竞生,每天沉迷于动物分类,植物分类,对于人类尝试给毫无因果的东西分出类这种事情习以为常,每天就是写总结。
反正这就导致我对于很多事情没有那股子新鲜劲儿,反而对于很多事情无聊的一面深有体会。所以很多时候面对课程,是有很大的傲慢与偏见的。尤其是我早年的经历并没有完成,当美术生当了半截子,当生竞生也是没有登峰造极,导致我对于很多问题的思考全都停留在愤世嫉俗的地步,没有更进一步学会和解。
所以我个人总结是,OO 可对于我不是尝鲜的课,而是一个去解决自己的傲慢与偏见的课。
2.2 大宗师
“大宗师”是我最大的体验,有的时候,不是“穷人力”即可以达到的。可以看下面这句话
泉涸,鱼相与处于陆,相呴以湿,相濡以沫,不如相忘于江湖。与其誉尧而非桀也,不如两忘而化其道。
好了,装逼的话说完了(其实我也不知道这些话啥意思),我觉得最大的领悟就是我们的设计目标不永远是“最好”,或者永远不是最好。很多时候,程序开发是一个权衡的东西,在程序内部,时间要和空间权衡,可迭代性要和实现难度权衡,架构设计要和具体实现权衡,面向对象要和面向过程权衡。当一个方面变得更好,必然会有一个方面变得更差。
我没学这门课之前,脑子里想的都是为什么不能更好了,比如画画的时候,明明起稿的铅笔软一点,效果会更好,或者学生物的时候,在某些分类上,放弃一些传统的标准去做分类,会有更好的效果。这就导致我在画画的时候,谁都不服,就服分数,学分类学的时候,谁都不服,就服 DNA 相似度分类。但是其实呢?很多时候是没有一个固定标准的。
比如第一单元,既然没有卡时间,那么自然不用考虑什么样的顺序可以化简的更短,直接暴力的每个都尝试一遍就好了。我的第一单元,醉心于架构的优雅,而输在了不肯接受实现的丑陋。
再比如第二单元,在明明知道没有办法优化性能的前提下,执意优化性能,在知道标准模式很好的时候,却非得探究多线程与面向对象的冲突,输在了沉迷于自己学习的幻想中无法自拔。
再比如第三单元,在明明知道时间紧,任务重的情况下,依然认真完成任务,而且完全是一种自我感动式的完成,对于真正的时间的复杂度的需求视而不见,沉迷于 JML
的数学形式和跟人辩论中无法自拔。
其实只有第四单元是好的,在这个单元里,虽然我没有做出想第一单元那么优美的架构设计,也没有第二单元那疯魔成活的调度优化,也没有第三单元纵观全局。但是它很自然,虽然丑陋,但是自然,是符合“大宗师”理念的。
回顾下来,虽然课程让我开心的事情有很多,但是最让我骄傲的,就是完后了第四单元,因为从这个单元开始,我从一个幼稚的人,向着一个成熟的人迈进。
2.3 对象
那么到最后,我完成突破了吗?
其实没有,很多时候不是道理想通了,事情就办成了这么简单。我无论比别人在认识上面多走了多少,在很多时候还是不如别人。哪怕不与别人相比,与我自己相比,也是这样,你说我想出了新的道理了吗?想出来了,做出新的改变了吗?做出来了。但是真的有多少进步吗,没有。
其实就是两手空空,毫无所依而已。不过其实事情大部分都这样。我听过一个故事,大致就是讲一个小男孩拿着一个曲别针,先用曲别针换了饮料,又用饮料换了帽子,反正最后经过一系列的价值不等的交换,最后换到一个别墅。我小时候就想,这故事不具有美感,最好这个小孩再用别墅换回曲别针,或者一个小姑娘的笑容,这样在别人都为他丢失一栋别墅而烦恼的时候,酷酷的留下一句“嗨,反正不过损失一个曲别针”。
在我敲完了这四千多字的博客的时候,我对于 OO 的看法尘埃落定,这课是好课,我来的时候连曲别针都没有,我走的时候却认识了很多朋友,发生了很多故事。
最关键的,这门课程叫做“面向对象”,哪怕强如杰哥,兼具“得意门生,最佳性能,最狠狼人,暖心分享”四项大奖,他也有很大的不足,那就是他没对象啊。我就算各种强测各种寄,各种互测各种被刀,各种装逼各种被打脸,各种坑全都踩了一个遍。但是我在课程学习的过程中,真正做到了“面向对象”啊,我的代码都是“面向对象”编写的,我对象就坐我对面。这,你说说,有什么办法呢?强烈建议课程组给我这种贯彻课程基本精神的人满分以滋嘉奖。
最后我想说:
我跟 OO 有过对象般的争吵,我也希望和对象有 OO 似的美好。
2.3 尾声
一气呵成之后看了看要求,发现没有提意见,我真觉得 OO 绝世好课,故提一下建议:
- 可以考虑优化指导书的渲染系统,个人感觉做的还可以更漂亮,尤其是斜体和数学公式。
- U3 或者 U4 开放一些架构设计的部分,连着两个单元没有架构设计,有点怀念。
- 研讨课可以考虑不加分,这样大家的分享会比较理想。身边有很多不太擅长演讲的人为了这个很难过。
最后,诚挚感谢吴际老师的教诲,战晨曦,吴家焱等助教的指导,冰哥亲人般的关怀,jjj, lsz, zkg, wxz,wxg, cjj, ghy, cnx 等人的帮助。爱你们。