方法论、方法论——程序员的阿喀琉斯之踵
以前,我認為一個事物對我沒有直接用途的時候就不會去理會它,心理學上說我們都戴著自己的認知偏見的有色眼鏡去有選擇性地看待這個世界,紛繁的信息經過我們的認知圖式過濾之后便成為少量有序的事件,所以我們都在有強烈選擇性地關注一些事物和忽視另一些事物,然而,這樣可能會導致喪失一些很有價值的信息,而總是將知識面停留在自己的小世界中——當然這倒也不是說看到什么都要湊上去學一學。如何在這兩者中間取得折中,我覺得一個好的辦法是先簡略地想一下這是個什么東東,他的本質是什么,出現是為了滿足什么需求,等等比較“高層”的問題(即“What”和“Why”而不是“How”),這些問題應該是可以通過簡單的調研和思考得出結論的,至于背后的技術細節,如果你打算入行,就可以去學,如果不打算的話則可以免了,至少前面的思考和簡單的調研能夠一定程度上保證當有價值的信息或機會擺在你面前的時候你不會把眼睛蒙上走開,并且多做做這類思考對于思維的廣度也很有價值。最近我開始認為,最佳的學習方法就是先廣度優先遍歷(先弄清What和Why),然后擇最合適的分支深入(How)(算法牛人DD同學在TopLang上的一個帖子里面也提到類似的想法,剛進大學就能夠如此清晰地看清前方道路的走法,我對DD很佩服)。
方法論看似是個很抽象的東西,并且的確有一些方法論是抽象到 over-generalized (泛化過度)的地步,然而說實話在實踐當中我總是發現(正確的)方法論是再現實不過的東西,比如一個大家都明白的道理是:如果方向走錯了,那么做的功就基本全白費了(還有比如“如果方法對頭,就能事半功倍,反之可能多走很多彎路”)——然而現實中有多少人能夠真正實踐這個方法呢?絕大多數人都是只顧解決眼前問題,抓了這頭丟了那頭,更多人是不知道問題是什么,只管把頭腦中能聯想到的一個以前類似情況下的類似方案套用上來。以前我總是覺得一個公司里面,CEO/CTO 這樣的角色是基本擺設,但我現在不這樣想了。在 How 層面把事情做好,做成一個精鉆的程序員,那頂多就是能把鉗子使好,這樣的事情很多人都能做到,熟能生巧嘛。換句話說程序員基本上是去解決一個定義好的問題,去實施一個定義好的方案。然而決策問題就不一樣了,決策問題是需要去定義問題是什么,以及權衡最佳方案是什么,不管是決策技術架構還是決策商業策略,都是非常復雜的思維過程,需要綜合和權衡大量的信息,這種能力就不是簡單楞著頭搞下去能練出來的了,很多時候需要抬起頭來看,免得只見樹木不見森林。(以上也是為什么我在討論組里面一篇帖子(什么是算法?為什么學習算法?以及學到什么程度?)中提到我覺得學數學學到精通未必就會思考日常決策問題的原因——數學幾乎總是去解決一個定義好的問題,用的也都是定義好的嚴密的邏輯推導。然而現實中的問題是一個復雜系統,諸多變量互相影響,如何權衡最佳方案實際上是一個復雜的統籌規劃。更重要的是,你往往甚至都不知道問題是什么,能夠從紛繁的信息中抽象出問題,是一種極大的能力。這里推薦《你的燈亮著嗎?》和《失敗的邏輯》)
當然,我自己還沒能到這個層面,尚需要不斷實踐和總結,所以只能稍微的談一點感受,再往下扯只怕就會流于空泛了。這一點上我還是舉一個程序員們喜聞樂見的例子吧,在程序員眼睛里面,做一個項目,也許首先想到的是用什么語言,什么框架,什么庫,在這個方向上那就是什么看上去牛B用什么,恨不能都用 haskell、lisp 來寫才爽,用 Java?那多沒意思啊,Java 那坨弱智語法我小學的弟弟都能掌握,也沒啥牛B的語言特性,忒沒成就感(只可惜真正判別弱智與否的并非用什么語言技術,而是做出什么產品滿足什么需求)。這就是屬于只考慮單個孤立因素的簡單(或者說 Naive 的)決策,這個因素就是——只要讓我自己感覺爽——只可惜并不是讓自己感覺爽的做法就是真正解決問題的做法,始終要弄清問題是什么,在后者意義上,一些對于技術型程序員往往沒有吸引力的話題其實有著極其重大的價值——比如什么時候設計,什么時候重構,什么時候集成,再往上一層其實這些又都是次級問題,首要的問題還是這個產品滿足什么需求,有什么市場(即這件事情值不值得做),有一句話想必很多人常聽說,如果不知道要做什么,套上十二層架構也無濟于事,方法永遠不是因,而是果(我在以前的另一篇文章“Failing to see the Big Picture – Mistakes we make when learning programming”中也闡述了類似的觀點)。
再舉個例子,如果我想給我的網站做一個 feature ,我認為這個 feature 技術上很牛很強大,而且剛好有機會使用一下我最近修煉的某某 framework 和某某語言,而且這玩意很有挑戰性,還不是一般人能夠做得了的,綜合以上三點,我立時覺得心癢難耐摩拳擦掌。然而實際上這個問題應該怎樣分析呢?首先,考慮到以上三點,這將會是一個投入相當大的項目,那么其收益就必須要對得起這個投入,技術上很牛不代表商業上就牛,再牛再難做的 feature 如果不能帶來商業價值那就是負收益。總而言之,
1.?一件事情僅僅讓你感覺挺牛不代表這件事情就是值得做的;?
2.?一件事情僅僅讓你感到很有興趣并不代表這件事情就是值得做的。
這兩句話和我們日常的認識并不沖突,其實我們幾乎總可以找到既有價值、又有趣、又有足夠挑戰性的工作。舉個例子,本科數學學得精純無比的同學有沒有偶爾也會覺得盲目呢?做這些題目到底有什么實際用途呢?這就像是你總是在磨一把刀,磨得閃閃發光鋒利無比,你可以向別人炫耀自己的刀很牛B,但是刀是為了沖鋒陷陣血濺五步的,你也不想讓它折戟沉沙吧,不管是將數學用在數學物理上還是用在人工智能、機器學習、密碼學、通信上,都是既讓人有成就感,同時又有意義和價值的事情。對我們程序員來說,你把一門語言玩得很精通,不僅知曉它所有的語法細節,陷阱和缺陷,還了解它的底層實現模型是如何。你覺得很牛很有成就感——的確,我們都會為一件自己做到了別人做不到的事情而感到自豪,然而反問一句,除了情緒價值之外,這樣的事情在本身的價值上有沒有你感覺到的那么牛呢?如果你只是在削鉛筆,那么何必磨一把倚天屠龍劍來?反之,如果你做的是一個本身功能很牛很創新很有價值的軟件,那么語言技術其實完全是次要的,并不是看上去越眩越好,關鍵是選擇各個方面綜合考慮起來最合適的工具即可,瑞士軍刀也許很丑,但對于叢林冒險很實用就行。拿著一把屠龍寶刀去野外生存,同樣也不靠譜。
編程語言是為了實現軟件的,軟件是為了服務于人的。誠然,了解一門語言的方方面面能夠使你更有效地使用它,然而另一方面,如果結果發現這門語言并不何時來解決你手頭的問題呢?受到投入的沉沒成本的影響你一定覺得很不甘心吧?同理,由于你對一門工具投入了很多的精力,這門工具已經和你的情感掛上了鉤,于是如果讓你來決策用什么工具來完成一個任務的時候,你幾乎會毫無疑問地想到使用你最熟悉而喜愛的那個,這就是“當你手頭拿的是一個錘子,任何東西看上去都像釘子”這句話的一個解釋。原先的問題是使用一門技術使得能夠性價比最高地實現要完成地產品,然而到你那里問題就悄悄地變成了“使用一門技術讓我感覺最爽”,問題的所有其他需要綜合考慮的因素都被選擇性忽略掉了,所以如果你是一個語言技術 fans ,那么幾乎毫無疑問你會成為一個糟糕的決策者。最近,在學習和研究的方法論上我已經聽到不止一個人(參見《失敗的邏輯》和這里——一位諾貝爾獎得主的忠告(引言如下))忠告我們,不要為了工具而工具,忘記了工具的目的是什么。
…我們前面提過的顯微攝影專家,擅長于拍矽藻的照片,動物學家著迷于昆蟲貝殼跟有美麗羽毛的鳥類。我們的愛書狂最高興的事情,就是讀最新書和專論,他認為這些東西很重要,而且很能夠刺激頭腦,可是別人沒辦法,找到另外一本同樣的書。我們博學的模范,經過這種策略,讓他的朋友驚奇,讓他的朋友佩服…
…沒有效率的科學家中,有一小類就是所謂的崇拜研究儀器的狂人,他們對金屬的閃爍非常著迷,就像是夜鷹對它在鏡里的反影著迷一樣。他們非常仔細照顧所崇拜的東西,把儀器拭擦得雪亮,可以當鏡子使用,而且把它擺飾在最崇高的地方,就好像在教堂里面的圣壇…
CodingHorror?的作者最近在博客里面跟著?Steve Yegge?同學宣稱,如果有一件事情是他想教給程序員同學們的,那就是 Marketing 。無獨有偶,有一次吃飯的時候鮑志云同學也提到: Marketing Sense 是很重要的。其實也就是不要總想著寫牛代碼,用牛語言技術,不要落入為技術而技術的怪圈,而是首先想明白做的事情有什么價值,先弄清做什么,為什么做,再去想怎么做,這樣后面的功夫才花的有價值。
You won’t– you?cannot– become a better programmer through sheer force of programming alone. You can only complement and enhance your existing programming skills by branching out. Learn about your users. Learn about the industry. Learn about your business.
當然,最后必須聲明的是,不要矯枉過正,誤會以上的觀點,以上觀點并不是說學生時代做的基本功是不需要的,一些非?;镜墓Ψ?#xff08;如計算機體系結構、數據結構和算法、兩個主要流派(命令式和聲明式)的編程語言都使用了哪些主要的編程范式、對主流語言的優缺點和適用場合的了解等等)是有必要掌握牢靠的,因為一方面我們并不是都能去做判斷與決策,碼農總是一個可靠的職業。另一方面對技術大方向的把握也是決策的基礎知識,只是不要掉進無盡的技術漩渦,成為技術追星族。此外也許還有一個小小的好處就是如果被老板逼著用一門不熟悉的語言時不會很不痛快,因為真正重要的事情是你完成的產品,而不是用的語言。
一個有趣的附錄
我們的思維有很多很多的弱點,前文講的其實就是這樣的弱點,更多更系統一點總結可以看下這里,和這里。我一向認為,正確的思維方式,是一切高效學習的基礎。比如參見如下2個例子,錯誤的思維方式得到的結論有大得多的可能性是謬誤。
[1] 人總喜歡沿襲以往習得的經驗,并通過類比來進行外推。我第一次在一個地鐵終點站坐地鐵的時候,看著從遠方開來的地鐵,我心生疑惑——“這車每節車廂都這么長,待會怎么調頭呢(我心說沒看到鐵軌終點有一個大大的供調頭的U形彎啊)?”,當車開始開的時候我終于意識到原來車是可以往兩頭方向開的。
[2] 人喜歡從關聯當中尋找因果,有一次我我老婆去銀行取款,到了 ATM 室的自動門口,我開玩笑地拿著手頭的飯卡去刷了一下,然后——門居然開了。我頓時來了勁,立即得出一個結論:這個刷卡裝置不安全,至少不是能夠專門識別銀聯的卡的。我甚至飛快地泛化出了一個更具一般性的理論來解釋這個現象:即可能所有帶有磁性的卡都可以用來開門。老婆看我得意洋洋,就潑過來一盤冷水:不一定是你的卡刷開的啊,你不刷卡試試看。我不信,說怎么可能呢,心想我刷卡,門就開了,還有比這更明顯的因果關系嘛。但出乎我意料的是,我走出門,這次沒刷卡,門也開了——原來是感應門——原先這個 ATM 室的確是刷卡門,但后來改成了感應門,刷卡的那個裝置只不過沒拆掉殘留在那里而已。
[3] 《失敗的邏輯》里面從認知心理學的角度系統介紹了我們在復雜情況下的判斷與決策是如何出錯的,非常值得一讀。
from:?http://mindhacks.cn/2008/10/29/methodology-for-programmers/
總結
以上是生活随笔為你收集整理的方法论、方法论——程序员的阿喀琉斯之踵的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [BetterExplained]书写是
- 下一篇: C++11(及现代C++风格)和快速迭代