编程,更多?更好?更快?

最近,读到一个故事,是下面这样的。

在一次陶艺课上,老师在第一堂课时说,他会把班上同学们分成两组。教室左边这组,他们这门课的成绩将会以最终完成的陶器作品数量来评定,而右边那组,则会以最终完成的陶器品质来评定。

进一步说明,其评定过程是这样的:这门课的最后一天,老师会带来一杆天平称,用来称量 “数量” 组的成果。如果 50 磅及以上,得 A,40 磅及以上得 B,30 磅得 C,如此类推。而 “品质” 组只需要提交一件(仅一件)他们组认为最 “完美” 的作品即可,如果老师也认为很不错,就可以得 A。

时间很快过去,到了该交作业的日子。一个很有趣的现象出现了,“数量” 组如预期一般拿出了很多作品,但质量最好的作品却也全部是由 “数量” 组制作出来的。按 “数量” 组的评定标准,他们似乎应该忙于粗制滥造大量的陶器,但他们每做出一个垃圾作品,都会吸取上一次制作的错误经验教训,再做下一个作品时得到改进。而 “品质” 组一开始就追求完美的作品,他们花费了大量的时间从理论上论证如何才能做出一个完美的作品,而到了最后拿出来的东西,似乎只是一堆建立在宏大理论上的陶土。

更多

当我读完这个故事,陷入了沉思,感到编程和制作陶艺是如此类似。《黑客与画家》书里讲,编程和画画近乎异曲同工,其实很多这种类似工匠型的技艺都有其相似之处。

很多人小时候都画过画,是的,我小时候也爱画画。看见一幅图,拿上一只笔就可以开始临摹。后来有了美术课,开始写生,看见了,就能画出来。但现在我却不再画画了,为什么?因为,现在我再回头看曾经画过的画,简直就是一坨 “狗屎”。后来,长大了,成年了,读完书、考上大学,工作后,再想拿起笔去画时,发现还不如小时候画的,所以我不再画了。

为什么那时候(小时候)明明画得不好,却可以不停得去画。也许这个问题有很多答案,但我想其中之一必然是:那时候,我们并没有给自己施加任何的限制,没有追求完美的作品,没有追求画画的意义,而仅仅是在探索与学习。一幅接一幅的画,仅仅是这一次比上一次有所进步,我们就会开心的大呼小叫。

某一天,我们长大了。我们知道了,画画是一种技艺,甚至是一种艺术。我们见过了真正可以称之为艺术的画作,我们也知道了如何才算是正确的画画,所有这些让我们感到,曾经的那支画笔已经重到让我们不敢再轻易去拿起。

那些成名画家的作品,如果按时间顺序来排列展示,我们会发现每幅画所用的技巧,都是建立在上一幅作品学到的东西之上。如果某幅作品特别出众,你往往能在更早期的作品中找到类似的版本。

而编程这门技艺,也完全是一个类似的过程。我很庆幸我在初学编程时,就像我小时候刚拿起画笔,我只是在不断通过编程训练来解答一个又一个书本上得来的困惑。后来,则是不断写程序来解决一个又一个工作中的问题。那时,看到书上探讨各种优雅的代码之道,编程的艺术哲学,我却完全不知道如何通往这座编程的 “圣杯”,看着自己写出的蹩脚代码,然后继续不断重复去制作下一个丑陋的 “陶器”。

而过去十多年的编程经验印证了开头的故事,在通往「更好」的路上,必然要经过「更多」这条路。

更好

编程路上,如果一开始就像 “品质” 组的同学那样去追求完美,也许我们就会被定义 “完美” 的品质所绊住。

编程的问题是,一开始我们并不知道什么是编程的正确方法,无论我们在开始动手编程时看过多少有关的编程理论、方法、哲学与艺术的书。这样反而让我们没有什么约束,只管去盯住你要用编程解决的问题,把问题解决,把任务完成。

曾经,还在学校学习编程时,有一个期中课程设计。我很快完成了一个这个课程设计中的编程作业,而另一位同学,刚刚看完了那本经典的设计模式书。他尝试在用书里学到的新概念来设计这个编程作业,并且先又用 UML 画了一大堆交互和类图,去推导设计的完美与优雅。然后兴致勃勃的向我(因为我刚好坐在他旁边)讲解他的完美设计,然后我若有所悟,觉得里面确实有值得我改进的地方,准备吸收一些我能听明白的东西,重构一遍已经写好的作业程序。

后来,这位同学在动手实现他的完美设计时,发现程序越写越复杂,交作业的时间已经不够了,只好借用我的不完美的第一版代码改改凑合交了。而我这在第一版代码基础上,又按领悟到的正确思路重构了一次,交了作业。而巧的是我的第一版代码,又流传到了另外几个同学手上,几乎也就改个名字就当成作业交了。但是,我们那门课的老师有一个专门识别类似作业程序代码的程序,检查出了相似度极高的那几个同学的作业,都是我的第一版代码,结果所有人都被打回重做了一遍,而我暗自庆幸,还好我又重构一次。

编程,其实一开始哪有什么完美,只有更好。之后,工作了,我做了大量的不大不小的项目,然后发现这些项目都有很多类似之处。每次,即使项目上线后,我也必然重构项目代码,提取其中的可复用代码,然后在下一个项目中使用。循环往复,一直干了七、八年。我想,很多程序员都有类似的经历,而把这件事干得最有名且极致的是江南白衣的 SrpingSide(一个以 Spring Framework 为核心的,Pragmatic 风格的 JavaEE 应用参考示例,是 JavaEE 世界中的主流技术选型,最佳实践的总结与演示。) 开源项目。

在这个过程中,我渐渐成型了属于自己的编程价值观:没有完美的解决方案,任何方案总是有这样或那样一些因子可以优化。一些方案可能面临的权衡取舍会少些,而另一些方案则会更纠结一些。但所有的方案,我都做了取舍。

好不是完美,好是一个过程。

更快

当做了足够多,并且到了足够好的时候,自然能做到更快。

影视作品里,总是用一种敲击键盘的快来表达黑客高手编程的快。但实际编程最大的瓶颈在头脑,而非手指。如前,程序员反复提取、重构与优化的代码,最后就成了自己专属的工具箱和脚手架。遇到类似的问题、场景,要么直接就能复用,要么稍微改改也能使用,这样才能做到快。

所以,为什么会有不要重复发明轮子的说法,我们要把宝贵的思考力用在更新的问题上,而非已经解决的问题上。为什么需要尽早并经常性的重构代码,扔(重构删除)掉一些代码,就是扔掉负担,然后走的更轻松,留下(重构复用)另一些代码,让未来走得更快。

有时,好几年后,我还会看几年前的代码。刚开始几年,我老是骂自己太蠢,怎么当年写这么蠢的代码。再过了一些年,偶尔我会惊喜的暗赞当年还是有聪明的时候,对于一些当时就思考理解得很费力的地方居然留下了注释,还有故意写了一些看起来很 “蠢” 但是很容易阅读和理解的代码,而不是写一些 “聪明”(不聪明的普通人不太看得懂)的代码。当时的这些 “蠢” 反而让后来去改进、修复和重构时能更快。

吴军在一篇介绍世界十大博物馆的文章里写到西班牙马德里的普拉多博物馆,其中有戈雅的两幅玛哈像 ——《裸体的玛哈》和《穿衣的玛哈》。

画中的玛哈是一位公爵的情妇,公爵请戈雅为这位美女画像。这位美女颇为风骚,就对戈雅讲,“给我画一幅裸体的吧”。戈雅就认认真真画起来,当然画得很好,快画好时,这位公爵提出要看一眼情妇的画像。吓得戈雅把那幅裸体的赶快藏了起来,一夜之间凭着想象又画了一幅穿上衣服的。于是就有了裸体的和穿衣的两个版本。当然,由于前者是很长时间精雕细琢出来的,后者是一夜赶出来的,因此从水平上讲,《穿衣的玛哈》远不如裸体的版本。

通常,对于一个匠人,像戈雅这样的大画家,你能做得很好,一般也能做得很快,这取决于你追求的是好的极致,还是快的极致,或者二者的平衡(又快又好)。

...

编程路上,多是好与快的前提,而好或快则是你的取舍。


写点文字,画点画儿,记录成长瞬间。
微信公众号「瞬息之间」,既然遇见,不如一起成长。

posted @ 2017-09-03 18:19 mindwind 阅读(...) 评论(...) 编辑 收藏