您當前的位置:首頁 > 詩詞

長日無痕

作者:由 陳天 發表于 詩詞時間:2013-09-18

題記:這是我知乎上的第一篇專欄,不知道寫什麼,於是就把最近的一篇部落格搬過來。用慣了medium,自然在這裡編輯起來也得心應手。可惜這裡不支援markdown語法,將其改成富文字也著實耗了一些精力。

(一)

又是一個悶熱的週六,灰霾就像粘在天空一樣,依舊籠罩著這個城市。帶著小寶,我們三人遊蕩在藍色港灣的兒童城中,為小傢伙的未來打算著。老婆和丈母孃穿梭於一個又一個玩具店,而我,因為推著童車,不便走來走去,就帶著小寶靜靜地欣賞樓下冰場裡玩耍的孩子們。很快,我們的注意力就被冰場上兩個正在進行對抗訓練的小男孩吸引住了。小寶快樂地隨著冰球轉動脖子,雙眼緊緊地捕捉著黑色的冰球,不時發出愉悅的『喝彩』;而我,默默地看著兩位『男子漢』一次次跌倒,又一次次爬起,對抗雖然異常激烈,但任何一方都沒有髒動作,這足以讓真正的冰球賽場上的成年人汗顏。

連日來,對環法腳踏車賽興奮劑醜聞的追蹤報道,讓曾經的英雄們紛紛落馬。成人世界裡,人們對於名利的渴望,對成功的追逐已經遠遠超出了能力或是道德的底線。我們不得不承認,這個世界正變得越來越浮躁。會爬的恨不得立即會走,踉踉蹌蹌走著的,又恨不得能撒腿就跑。前兩天我在卓越亞馬遜上隨便查了查『小時學會』和『天學會』,結果發現分別有65條和157條結果之多。『Java程式設計24小時輕鬆掌握 』,『21天學會javascript』,『30天學會Visual C++』,。。。看著那列出的一大堆需要花很大力氣學習和使用的語言,我不得不感慨這種浮躁已經無處不在。

小寶還在咯咯地樂。那種發自內心的,如雪花般潔淨的快樂讓我由衷地羨慕。如果不是上週日LP跟我嚴肅地討論了一下在未來我如何更好地履行父親的責任,此刻(週六的下午)我應該端坐在辦公室裡思考某段程式碼該如何去寫,而不是在這樣一個放鬆的環境下,任由我的思想翱翔。

我們討論的結果是,一週裡大禮拜我能不去公司工作就不去,並且工作日最好有兩天趕在七點前回到家,這樣,可以大大增加我在家中陪伴小寶的時間,提升她對『父親』這個角色的認知。在北京這樣一個擁擠到幾乎處於崩潰邊緣的城市,以公司到我家長達三十五公里的距離來算,晚上七點前回到家就意味著至少提前兩個從公司出發,還得祈求一路上 1)沒有事故(小機率事件),2)沒有管制,3)沒有幽靈堵車。兩個小時的車程對很多北京人來說還在忍受的極限內,但對我來說,開車上/下班的時間超過一小時我就已經渾身難受,更遑論兩小時這一讓人絕望的數字。所以,我決定在提前回家的那兩天搭乘地鐵,這樣,只消花一個半小時,我就能回到家中;而且,在地鐵裡,我可以暫時遠離程式碼和網際網路,翻幾十頁和技術毫不相干的書。巧的是,上週不開車的兩天上下班時間裡,我翻的書是《長日留痕》——一本我買了很久,翻了幾次卻都沒看進去的小說。史蒂文斯先生,書中的主人公,利用一次旅行的機會回顧了他漫長的管家生涯。在整部書中,他始終在回憶過去的人生,並且不斷地探討一個嚴肅的問題:一位傑出的男管家究竟是什麼樣子的?

感謝這本書,讓我開始嚴肅地回顧我自己的職業生涯。這思考斷斷續續遊走了好幾天,很多時候乾脆藏身在潛意識中,以至於每每我工作累了,對著窗外中關村東路和成府路交叉的路口發呆時,它就會蹦出來,讓我暫時從繁重的工作中解脫出來,在回憶中盡情徜徉。

(二)

教練一聲哨響,把我暫時拉回。此時此刻,兩個小傢伙開始了一攻一守的對抗,場面也變得好玩起來——兩個小愣頭青從場地的兩端以幾乎相同的路線滑向中圈,砰的一聲,重重地撞到了一起,一同倒地。教練上前,把攻方的小傢伙拉到一旁耳語幾句,並比劃了幾下,隨即恢復了比賽。兩人從場地的兩頭快步衝向中圈,守方將重心控制地很低,高速滑動中,目不轉睛地盯著冰球。就在兩人要接觸的一剎那,攻方一個急停,然後迅速切向斜前方。由於撲得太猛,守方來不及調整,無奈讓攻方輕鬆繞過自己,打進一球。不知是看懂了比賽,還是單純開心,小寶揮舞著雙手,發出歡暢的尖叫聲。

這就是教練的作用。他們告訴你什麼是基本功,如何應對局勢,以及一名優秀的球員應該具備什麼素養。在一個人職業生涯的早期,一位好的導師比什麼都重要。一晃我的程式設計師生涯已經過去了十年,在這十年裡,我一直在不斷探索

一位優秀的程式設計師究竟該具備什麼素養

,如果當時有個教練能給予我指導,給予我探索的方向,那該多好啊。

可惜沒有。軟體行業沒有教練,也沒有拜師學藝的傳統。也許曾經有,但自從程式設計師從手工藝人變成了工程師,教練或者師傅就不再重要。你基本不需要像手工藝人那樣具備從無到有做出點什麼的技術,你需要的僅僅是解決某個或者某些特定問題的能力 —— 某種意義上說,這和流水線上的工人並無二異。這也導致了那些速成的圖書的暢銷,因為它們試圖讓你學習到的是

如何完成任務,而非如何程式設計。

當然,網際網路正在粉碎這一切,程式設計師似乎又在迴歸手工藝人的傳統,這很好。

雖然沒有教練,但每個軟體公司基本都會為新員工指定一名資深的同事提供『象徵』意義上的 “mentor”。我說『象徵意義』,並不是否定mentor的作用,而是說這些mentor並非職業化的mentor,『傳道授業解惑』的為師之道,mentor們勉強在解惑上提供了些許幫助。當然,對於公司來說,mentor最重要的作用是成為一個榜樣(Role Model),透過他們的工作態度,工作習慣,工作能力,對新員工,尤其是處在職業生涯早期的員工產生潛移默化的影響。

我職業生涯起始的公司是神州數碼網路公司(DCN)。如果將google或者twitter定義為『優秀』公司,那麼,DCN顯然處在平庸公司的行列。好在DCN繼承了老聯想的底子,還有一批有理想的做系統的牛人。Z君就是這樣一個人。碰巧我被分在了他所在的團隊。當我把『一位優秀的程式設計師究竟該具備什麼素養』這樣的問題拋給我的mentor,即將離職的X君時,他讓我多看,多學Z君。之後,有意無意地,我都會多去勞煩Z君,他總會拋開手頭的事,爽快地為我答疑。為了解決某個問題,他經常工作到深夜;跟他討論程式碼如果沒揪到根上他絕不善罷甘休。拿code review來說,當你看到一堆邏輯上無比正確但寫作上WTF的程式碼時,即使想罵娘,但屈服於release的壓力或人情世故,你總會妥協。但Z君不太會妥協。他會笑眯眯地,毫不留情地指出你程式碼上十多處毛病,讓你整改。很多人認為程式碼邏輯對了就足夠,但Z君期待程式碼(演算法)在時間空間上的合理(和諧),以及是否做到了SoC。工作之外,他又是個吊兒郎當的人,經常爆發出的爽朗的笑聲,渾身濃重的煙味,讓你即使在很遠的地方,也能感受到他獨特的氣場。

從Z君身上,我找到了一直追尋的問題的第一個答案:

真心喜愛你所做的事情。

真心喜愛你所做的事情。之所以斟酌出這個句子,是因為我覺得諸如『敬業』,『有韌勁』,『鑽研』,『愛學習』等詞語或多或少都被它涵蓋,或者說,是它的自然而然的結果。

那時對我而言,『真心喜愛』就意味著每天超過12個小時泡在公司裡努力搞明白遇見的每一個技術問題。很快,我搞透了OSPF,填補了X君走後OSPF上的空缺,之後又獨立開發了IGMv3,SNTP,接著完成了極其重要的linux 2。4 kernel的移植。

(三)

由於工作的原因,我逐漸與另一個團隊的S君打交道很多。S君興趣很廣,他幫著公司內部搭建了團隊的wiki,使得資訊的交流,知識的分享大大地系統化。以前我們知識的交流以郵件為主,這很被動,當下有用的,還是無用的知識,都一股腦成了一封封亟待開啟的郵件。開啟看吧,浪費時間;不開啟吧,以後需要時都不知道自己的郵箱裡還有這麼份東西。在S君的推廣和維護下,團隊的wiki大大提高了大家獲取知識的效率。

從S君那裡得知,他使用了一個叫mediawiki(wikipedia使用的軟體)的開源軟體。我開始把玩mediawiki,進一步,我接觸了LAMP,並且逐漸意識到像linux,Mediawiki這樣的開源軟體的重要性。如果說林則徐魏源是近代中國開眼看世界的第一人,那麼他也許是DCN內部擁抱更廣闊的世界的第一人。做system的,很少關注application的動向,有種天朝藐視番邦的傲嬌;而做application的,則放低姿態謙卑地注視著system的變化。現在隨便拉一個做路由器的人,你問問他對web application的看法,十有八九還停留在對LAMP的認知上;而做web application的人已經把觸角伸向了user space data plane。究其原因,是做system越做越掌控一切,傾向於封閉;而做application越做越依賴生態圈,所以擁抱開放。

S君讓我認識到了開源的力量和開放的社群的偉大之處。懷著對mediawiki的敬畏,我開始學習PHP,進而在他的影響下,學習據說是『聰明的程式設計師』使用的Python。我想我已經是『真正的程式設計師』了,如果能成為『聰明的程式設計師』,何樂而不為?

在這個過程中,我找到了第二個答案:

擁抱開源和自由軟體,擁抱社群。

大學期間,我曾經是一個堅定的微軟主義者:凡是微軟推出的,我都擁護;凡是微軟反對的,我都反對。直到畢業時,我還天真的認為C#就是我們這代程式設計師的終極武器。S君及時把我從這種盲從中拉了出來,讓我看到了一個不一樣的世界。現在稜鏡門事件的熱度在漸漸褪去,但是,它讓人們開始意識到Richard Stallman的思想的重要性:

開源軟體關乎著人類的自由。

遺憾的是(也許我不該這麼評價),我的兩任僱主,對開源軟體的貢獻要遠小於其索取。

PHP和Python對於我所做的開發任務似乎毫無幫助,學習它們地目的是為了瞭解更廣闊的世界,瞭解為什麼最流行的軟體會被用這樣的語言開發出來。為了更好的實踐我的所學,我用PHP和Python做了一個工具:開發人員可以透過一個PHP撰寫的web頁面提交一項測試任務,後臺的python指令碼拿到這個任務後會拉下指定版本的程式碼,編譯,並將編譯好的image傳到直連的交換機上,然後開始執行測試團隊提供的regression指令碼。我的工具帶來的效率的提升引起了老闆的重視,我被批准使用一臺PC和兩臺交換機,組成一個完整的環境,供開發團隊踐行CI(Continuous Integration)。

在這個過程中,我發現了第三個答案:

能夠透過自身所掌握的技術,不斷提高自己和團隊的效率。

容我再解釋兩句。一個真正的程式設計師,在那些每天重複低效的幹活方式展現在你面前時,很難抑制住利用自己的技能做點什麼改變現狀的心情。工作中(當然生活中也是),這樣的低效比比皆是。比如說從X系統中定期匯出一些資料到excel中做報表,比如說一級一級收集weekly report進行工作彙總。

這種低效在我工作過的第二家公司,Juniper,也廣泛存在。

回顧我目前的整個職業履歷,我在DCN工作了兩年零兩個月,在Juniper China R&D(CNRD)工作了五年半,在途客圈作為創始人和CTO工作了兩年,然後回到Juniper CNRD工作至今。所以,作為僱員,我總共就工作過兩家公司,因此,是否每家軟體公司都存在類似的低效,我不得而知。但我覺得,工作中的低效場景無處不在,問題在於有沒有被發現,發現後值不值得為此做點什麼。

(四)

冰球場上的對抗結束了,小傢伙們離場休息去了。我鬆開手上的童車腕帶,把腦袋湊過去,輕喚小寶的名字。小寶顯然還全神貫注於冰場,被我這突然的舉動嚇了一跳。當她惶恐地轉過頭來看到是我,便放下心來,微微笑了笑,又回過頭去欣賞冰場上的運動。循著她的目光,我看到冰場上一個也就六七歲大的小女孩一個人在認真地練習花滑。她的動作如此純熟,姿態那麼優美,讓你幾乎忘了她的年齡。我想,她大概這麼練了有很長一段時間了吧。

看到這裡我不禁想起在Juniper曾經跟Y君討論過我們招人的準則。我不解為何我們不給年輕員工,甚至應屆畢業生一些機會。Y君認為我們需要的是專家,而某個領域的專家,根據研究,需要經過10000個小時的培養。我算了一下,假使每週四十個小時,一年五十週撲在某個或者某些特定的領域,那麼,五年的時間就可以造就一個專家。這也是為何很多公司對於senior的職位,都要求至少五至七年的相關工作經驗。但現實是,在面試中,很多五年,甚至十年工作經驗的人都未必對得起自己逝去的年華。我曾經遇見過一個工作了8年之久的程式設計師,在提供了vim,gcc等編輯編譯環境的情況下,連一個非常簡單的連結串列操作的程式都無法正確完成。這是怎麼回事?

我查了查“10,000 hour rule”的原文,是這麼說的 —— “it takes approximately 10000 hours of deliberate practice to master a skill”。

問題出在了

"deliberate practice"

上。

何謂“deliberate practice”?鋼琴考級有九個等級,每個等級都有要求的技法和曲譜。這是一系列刻意設計的練習,每一個級別都比上一個難度大一些,但經過努力還是可以掌握的。當你對車爾尼駕輕就熟後,可以嘗試一點巴赫,也許也可以是貝多芬,但絕不能倒著來,也不能跳著來。跳著來意味著你當前的水平和期望的結果之間的鴻溝太大,也許已經超過了單憑努力就可以到達的境地。

可惜軟體行業鮮有這樣的“deliberate practice”,學校和培訓機構也沒有類似的體系。所以這個社會能夠批次造就鋼琴9級獲得者,卻無法批次培養出合格的程式設計師。很多擁有五年工作經驗的人,摺合成有效的經驗,也許就只剩一年,剩下的四年只不過在重複自己第一年的收穫。這就好比一個人掌握了車爾尼《鋼琴簡易練習曲》後,還在刻苦反覆練習相同的內容,即使練到脫離曲譜信手拈來,又有何用?

想想我們的境地,挺悲慘的。沒有合適的導師指引方向,沒有成型的體系來培養專家。但是我們還得不斷地學習,不斷地更新知識。對於那些還尚未『開竅』的程式設計師來說,職業生涯就像《富爸爸窮爸爸》所謂的老鼠賽跑,在蹉跎中耗盡光陰。

所以自我救贖的最好方法就是不斷地給自己增加挑戰,讓自己脫離舒適區域。具體方法是:用那些剛好超過自己能力的任務挑戰自己,build(嘗試) - measure(分析) - learn(學習總結)。然後不斷重複。這是lean startup一書中建議的精益創業模式,同樣也適用於這個場合。

不要去看那些多少小時或者多少天就能掌握XYZ的書。生命苦短,多讀讀大師的著作和文章,他們能讓你跨越到新的臺階;多寫程式碼,多寫能讓你有徵服感的程式碼。

這就是我找尋到的第四個答案:

不斷跳出舒適區,有目的地挑戰自己。

讓我倍感欣慰的是,在Juniper的這五年半時間裡,公司提供了各種機會讓我在三個不同的team裡學習和掌握data plane,kernel,以及application。託L君rellocate到US的福,我還有機會lead一支團隊,來踐行我在leadership上所學的理論知識。

冰場裡依舊人聲鼎沸。怕寒氣把小寶凍著,我不敢在此過度停留,我把車推著往裡靠了靠,坐在一張椅子上稍稍休息。小寶舉著雙手似乎在抗議,但當她發現從她坐著的角度依舊能看到冰場的一角時,就漸漸安靜下來,雙手自然搭在童車的護欄上。

說來好笑,就在我離開Juniper的前夕,L君主持了一場小規模的英文演講訓練,以此來提高manager們用英文當眾發言的能力。我的主題就是“Move yourself out of comfort zone”。後來偶然的機會,我遇到了同樣也離開Juniper的L君,他說他那時就感到我要離開。我問為什麼。『因為CNRD對你而言已經成為一個confort zone,你只需不犯錯誤,靜靜等待,就能一點點向上爬,而這又和你的性格,尤其是你的演講傳達出來的感覺不同。』L君回答道。

想想也真是。我的性格里流淌著不安分的血液,它源自我的父親。一九九三年,父親隻身前往海南和廣東,像那個時代的所有朝氣蓬勃的年輕人一樣,希望能夠在改革開放的最前沿,尋找工作機會,瀟灑走一回。和其他人不同的是,父親當時已接近不惑之年,有家有口,還捧著醫生這樣一個金飯碗。如今我已過而立,晉升為爺爺的父親年逾古稀,在這個本該安享天年的時刻,仍然奮鬥在第一線,業餘時間還以編者的身份出了個人的第一部書,同時正在緊張地編撰第二部。父親就是我的榜樣,能夠全面超越他是我的一大理想(當然這也是一個達爾文主義者必須做到的,總不能一代更比一代差吧^_^),可惜至今我還未能完成這一理想。

(五)

A language that doesn‘t affect the way you think about programming, is not worth knowing。 - Alan Perlis

離開Juniper,我選擇了創業,建立了途客圈。那是一段奇妙的旅程,一段讓我成熟很多的征途。有史以來第一次,我寫軟體,不是為了我的僱主,我的payroll,而是為了我的夢想。雖然這段旅程僅僅走了兩年我就不得不因為一些個人的原因選擇了自我放逐,但這兩年,如喬幫主所言,是我開始去連線那一個個“disconnected dots”。我的程式設計水平開始極大地發展,我的軟體開發思想在不斷走向成熟,我越來越覺得自己像是一個真正的程式設計師了。

重要的是,我開始學習新的語言了。你也許注意到,自從從DCN學習了PHP和Python後,在Juniper我就不再學習新的語言了,部分原因是我在夯實我這兩門語言的水平,尤其是Python的水平,但更關鍵的原因是我開始固步自封了。C讓我成為真正的程式設計師,Python讓我成為聰明的程式設計師,我似乎找不到繼續學習新語言的理由。

但是,創業改變了這一切。我不得不學習javascript,因為這是客戶端唯一的標準。儘管在十多年前我就接觸了javascript,並用它做過一些效果,但那時對javascript的使用,與其說是使用,不如說是誤用。在途客圈,我才真正重新認識這門prototype based language。另外,為了權衡究竟什麼樣的架構更利於未來的發展,我花了很多功夫深入瞭解ruby,在ruby和python之間進行對比。透過《松本行弘的程式世界》,我瞭解了設計ruby時的很多思想。儘管途客圈最終選擇了python/django,但這是一次非常有益的對比和思考,它讓我進一步找到了第五個答案:

學通超過一種程式語言,瞭解儘可能多的程式語言及其優劣,知道解決某個問題的可能的最佳路徑。

注意學通和學會是兩個概念。學會意味著你能夠使用這門語言,會寫程式,而學通則意味著更多:

瞭解語言被建立之出的動機,深刻理解語言背後的

思想

掌握如何線上除錯(online debugging)和事後分析(coredump analysis)。

掌握語言外延/周邊的技術。如JVM之於java,OS/CPU EABI之於C。

掌握如何提升關鍵程式碼的效率,如何能夠擴充語言的能力。如NIF之於Erlang。

。。。

很多在簡歷中號稱精通C的人不知道malloc背後都發生了什麼,精通Python的人卻無法用meta programming寫出乾淨漂亮的程式碼。這樣的精通其實也就是勉強學會。

按照這個標準,摸爬滾打了十年後,我在C語言上勉強算學通,Python和Javascript只能說學會,Erlang/Ruby剛算了解。

容我再解釋一下為何要了解儘可能多的程式語言極其優劣。比如說新開發的軟體併發模式要採用STM(Software Transactional Memory),如果在技術選型前,你知道clojure在語言層面,haskell在GHC層面實現了STM,那麼,你的選擇可能不會侷限於你之前所用的語言。

(六)

總而言之,現在完全不可能讓時鐘倒轉了。你不能永遠總是對過去也許會發生的事耿耿於懷。你應該認識到你與大多數人一樣地過得很好,或許還要好得多,那就應該心滿意足了。 - 《長日留痕》

Life is short,

[the] craft long,

opportunity fleeting,

experiment treacherous,

judgment difficult。

- Hippocrates

也許是之前的凝視耗費了太多的精力,小寶開始打著哈欠揉眼睛。她回過頭來,張開雙臂,滿眼期待地望著我。我知道,小傢伙想要抱抱了。

十年前我根本無法想象十年後我能如此幸運而又意外地擁有她,正如十年後我無法預料她會變成什麼樣子。我可以為我的職業生涯,還有她的人生做“deliberate”的打算,但我無法控制結果。過去的十年,我遇到了很多很多十字路口。就像《長日留痕》裡說的那樣,『你不能永遠總是對過去也許會發生的事耿耿於懷』。重要的是,我做出了選擇。我很高興我的人生經歷與大多數人一樣豐富,或許還要豐富得多,我很高興我有很多很多故事講給我的孩子聽。

哦,忘了說另外一個答案,也就是第六個 —— 當然,僅僅對非英語母語的人有效:

能用英文自如地閱讀,寫作和交流。

一位優秀的程式設計師究竟該具備什麼素養?

在用了近8年的vim之後,我決定,嘗試emacs。