“老僧三十年前未参禅时,见山是山,见水是水。及至后来,亲见知识,有个入处。见山不是山,见水不是水。而今得个休歇处,依前见山只是山,见水只是水。大众,这三般见解,是同是别?有人缁素得出,许汝亲见老僧。”
——青原惟信禅师 《五灯会元》卷十七
一)见山是山,见水是水——背菜谱阶段
学习都是从模仿开始的。如果想学习炒豆芽,一定要先找本菜谱,或者是视频的更好,严格按照每一步,一丝不苟地进行模仿。
可是这样好挫折哦。难道想干成一件事,就一定要先找对书才行么?就像在武侠小说里面,一个少年书生,无意之中机缘巧合得到了绝世武功的秘笈,练个一年半载,哪怕只练成了五、六成,也足以在武林之中扬名立万,收获成功了。而那些运气不好的,只因跟错了师傅,纵使自己再努力,苦练几十年,遇上那个运气好的少年书生,一样被打得落花流水,满地找牙。我好不平啊,为什么一定要练别人写的武功秘笈呢?难道写武功秘笈的人是特殊材料制成的?难道我们自己就不能悟出武功秘笈出来?
答案是,能——如果在你之前从来没有过任何武功秘笈的话。这虽然令人沮丧,却是事实。武功秘笈确实也是人写的,但却不是一个人而是几代人逐步积累的。一个人即使再聪明,可时间精力却有限,境遇也各不相同,到最后结果一定是苦悟几十年,也只是小学生水平。
所以,要成功就必须多读书。可是书里说的就一定对么?不是说“尽信书,不如无书”么?这方面,我比较倾向于“先接受,再批判”的做法。也就是说,一定要先经过一个“尽信书”的过程,在经过实践之后,再反思、质疑,然后再实践。
有一次跟沦落为神喝酒的时候,聊到XP(极限编程)。我说,我的一个同学所在的团队正在尝试XP,他们遵循了XP的大部分,却唯独不使用结对编程,因为本来人手就少,受不了结对编程的成本。沦落为神笑道,其实结对编程绝对能大幅提高效率!我不解。他解释说,你想,我们平时是怎么工作的?是不是开着QQ和MSN,一边聊天一边敲代码?再看会儿新闻,逛逛猫扑,看看视频,没准还在淘宝上逛个没完没了。就算公司不让上网,也一样可以看小说玩游戏。这效率能高吗?可如果有个同事坐在你身边,你还能好意思这么干吗?(而且你的搭档没等混熟呢就换了)所以人家大师既然建议这么干,是有道理的,只不过人家没明说罢了……
我想说的是,半信半疑,不如不信。在实践之前,就因为自己的主观猜测而改变菜谱是不对的。譬如菜谱上写着“先放油,再放入葱花……”,你想着“少放几片葱花不会影响结果吧?”,那么就永远没法知道放了葱花的炒豆芽是什么味道了。
好消息是,现在是充满阳光的新社会,武功秘笈不再躲在人迹罕至的山洞中,而是等在书店里,几十块钱就能拥有它,而且不会因为拿着它而莫名其妙地挨上几刀。坏消息是,没有哪一本能够让我们立刻成为高手,我们只能一本接一本地读下去。读得懂要读,读不懂就先背下来,留个印象也是好的。
在圣诞节收到锤子做礼物的孩子会发现每样东西都需要敲打。
——锤子法则
我们应该接受迅速失败,而不是缓慢失败,最不该接受的则是没有失败。如果有人从不犯错误,那只能说明他们努力不够。失败的结果是试图去尝试其他可能。
——比尔·盖茨
每读完一本书,我们都像得到了一把崭新的锤子似的兴奋不已,这时每样东西都开始变得特别像钉子。这样虽然幼稚,却是必须经过的过程。可当你迫不及待地想要在项目中实践它(也应该如此),你的项目经理却报以轻蔑的目光,同事们也对你的热情并不感冒,怎么办?如果你本人就是项目经理,你自然可以在项目里运用新东西,可是新东西必然带来新问题,有一天你发现当初的决定是错误的,而且是致命的错误,怎么办?
我又不得不说我们程序员真是太幸运啦!如果我们是学物理的,就会发现做一个实验动辄几万、几十万。而作为程序员,要想实践一下新想法,只需要动动手指头而已。所以,桌面软件也好,小游戏也好,做网站也好,跟着兴趣走吧,尽量使用新东西吧,尽情地犯错吧!
读书会让人失去自信。书读得越多,就越发觉得写书的人如此伟大,知识如此浩瀚,自己如此渺小。每本书都自成体系,十分有道理。可是书和书之间却有不少矛盾的地方,我们该信谁?我们迷惑了,对任何事都不敢确定了。
实践让人获得自信。在实践中成功,在实践中失败。在无数的成功和失败之后,我们获得了自信——知道在什么条件下可以获得怎样的成功;或者失败,以及失败的后果是什么。
实践太重要了,一定要想办法参与到大项目中去,哪怕只是堆砌一个又一个的页面也好。要独立思考,可以尝试自己实现一个框架。同时也要学习下市面上流行的成熟框架。最好再看看理论书籍,例如《企业应用架构模式》一类的。三方印证,才最有效率。
二)见山不是山,见水不是水——分解、抽象阶段
每一次炒豆芽,我们都会想,为什么要先放肉,再倒酱油呢?为什么要用大火而不是小火呢?于是我们开始尝试颠倒一些步骤,替换或增加一些材料,改用不同的锅子,改变加热的方式……通过假设->实验的方式,我们逐步了解到每个步骤对菜品的影响是什么。
通过横向比较几百种不同菜式的相似之处,我们总结出典型的搭配——即模式。例如糖醋模式、爆炒模式、清蒸模式、麻辣模式等等。
我们开始对菜谱背后的原理感兴趣。我们会读一些讲解原则、原理的书籍。例如《深入浅出设计模式》、《大话设计模式》、《深度探索C++对象模型》、《T-SQL 程序设计彻底研究》(感谢包包的推荐)、《CLR via C#》、《人月神话》等等。
我们会觉得炒豆芽不再是菜谱上的那个炒豆芽了,它是活生生、香喷喷、热腾腾的炒豆芽,它的色泽、香气、味道,我们都知道是怎么来的。
我们会发现处理“根据不同的类型使用不同的算法”不一定非得使用多态或策略模式。只要运用得当,使用表、字典、if else也可以同样优雅而有效。
三)见山只是山,见水只是水——知行合一、灵活运用阶段
某天早上一醒来,发现对于最近接触的事物有了新一层的认识,似乎什么都不会了,却好像什么都理解了——就像张无忌练太极剑,不求剑招,只求剑意。
——Jeffrey Zhao 《我们到底该怎么学技术?》
如果说“见山不是山”是因为处在了痛苦的量变积累的过程之中的话,那么“见山只是山”则是在量变基础上发生了质的变化。
要达到“见山只是山”的境界,需要两个条件:
1)在“见山不是山”阶段有了足够多的积累,知识渊博、技巧纯熟、理解深刻,外加心态平和、人品不错。
2)形成了简单而深刻的、超脱于具体技术之上的统一理论和模型。
在实践的过程中,我们会越来越强烈地感觉到,理论并不是孤立地存在着,似乎总有更高抽象级别的法则控制着世间万物。不断重构的结果,似乎总会形成似曾相识的模式;模式又会符合某些设计原则,设计原则可以满足设计目标……有了更高级别的抽象理论,一切的存在似乎都有了新的意义。那些被我们分解得支离破碎的世界又还原成了一个整体。那迷雾缭绕的山也突然变得前所未有地清晰、自然、可爱……
但是没有条件1的基础,就算有人告诉我们条件2里面的理论也是没有什么用处的。例如,我在软件工程第一堂课里面就被老师告知:“软件设计很简单,只要达到低耦合、高内聚”就可以了”。可是这有什么用呢?我又不能像哈利菠菜那样,挥舞着魔棒,反复念着“低耦合呀低耦合~高内聚呀高内聚~”,然后荧光一闪,奇迹就出现了。同样,“后发制人,先发制于人”对于我们来说只是一句似乎有那么点道理的话而已,但是当杨过听到这句话的时候却犹如醍醐灌顶一般。特别地,由于杨过当时已经对天下武学融会贯通,并且有极强的轻功和深厚的内力,所以才能够做到后发先至。要是换了我们,在打架的时候,要是不先出手一定会吃亏的。
对于到达了这个境界的厨师来说,炒豆芽只是炒豆芽——就是把豆芽炒熟而已。不过,你会发现他每次炒出来的豆芽全都不一样。因为吃豆芽的客人不同、季节不同、地域不同、食材不同、天气不同、用来盛食物的盘子也不同,所以他炒出来的豆芽自然也不同。所有这些细微、精妙的变化,对于他来说却如呼吸般自然。而这自然、轻巧的一瞬,却是千锤百炼的结果。
创造性和合理性是这个阶段的显著特点。对于不断遇到的新环境、新困难,他们总能创造出新的解决方案。他们的设计也许不总像教科书那样中规中矩,却总能在复杂度和灵活性之间取得很好的折中。他们经常被迫在信息不足的情况下作出判断,而这些判断在事后多数会显得正确无比。
人类在学习的过程中,会很自然地对所学知识进行归纳、抽象。人类想要获得大统一理论的愿望几千年来从未间断过。我们在学习的过程中,总会感到似有一层窗户纸怎么也捅不破,似有一层迷雾在眼前,让人看不到尽头,这挫折感便是这愿望的表现。在这种时候,我们可以寻求一些讲解哲理和思考方法的书的帮助。不过哲学书有点太过抽象,推荐温伯格和爱德华·德·波诺的书。
不论处在哪个学习阶段,都可以有意识地让思维在抽象和具体之间来回移动,这是思考问题的非常有效的技巧。关于这个技巧可能会在后面的文章里进行更为详细讨论。