在提高代碼能力這事上,沒有銀彈
合抱之木,生於毫末;九層之台,起於累土;千里之行,始於足下。 - 《道德經》
轉眼間女兒到了學琴的年齡。我對樂器,純是葉公好龍,家裡擺著鋼琴,小提琴,手風琴,自己卻連五線譜也不識,所以無法督促丫頭練習,於是這重擔落在了老婆身上。老婆是個虎媽,嚴厲起來毫不含糊,說練不完琴不許吃飯,就不許吃飯,丫頭撒潑打滾,哭天搶地,姥姥紅著眼圈在旁勸阻都無濟於事。這種時刻,我自然是於心不忍,明面里卻必須和老婆保持高度一致,所以只能默默地滾到一邊,安安靜靜扮個風輕雲淡的土肥圓 —— 心裡還是會忐忑:這麼搞法,不會把娃兒的興趣折騰沒了吧?
然而我的擔心是多餘的。丫頭周六學琴,往往周六和周日最苦,哭嚎也是這兩天最甚。這是因為學了新的曲子,她還不熟,經常彈錯,彈錯就要重彈,老師布置的作業要彈很久很久才能過關。到了周二周三,她漸漸熟絡了,指下生風,哭嚎聲越來越少,周四周五就遊刃有餘了,多數情況都能開開心心地彈完。因為媽媽的嚴厲,她起初吃了不少苦頭,但漸漸苦盡甘來,嘗到了那種「直掛雲帆濟滄海」的爽快。在最痛苦的時候,她大哭著叫喚「媽媽我再也不想彈老師布置的作業了」,可在一月一度的「家庭演奏會」上,她還是會喜滋滋地,滿滿成就感地向遠在國內的親人們展現她的能耐。
好多同學在後台問我,代碼的能力怎麼練就。其實是一樣的理兒。多練,多讀,多寫。
軟體開發的教育作為一門非常年輕的學問,僅僅走過了幾十年,和鋼琴教育數百年的歷史相比,是滄海一粟。鋼琴有成熟的培訓和認證體系,軟體至今還是撞大運。其實想想鋼琴和軟體有很多相通之處:學鋼琴需要先學習一門指法,和一門語言(五線譜);學代碼也需要先學習一門指法,和一門語言(比如 python)。鋼琴的 hello world 是 「哆來咪發咪到來」,軟體的 hello world 是,額,hello world。練好了鋼琴的基本功,你可以按照某些需求,創作出曲子來;練好了代碼的基本功,你也可以照著需求,寫出合適的代碼來。
可是寫代碼並不需要像練鋼琴那樣,講究把基本功練得諳熟,各種知名的不知名的曲譜練過一圈,一級一級打怪升級,直到所謂的鋼琴十級才算出師;往往一門語言或者一個框架,了解了如何使用基本的結構,程序員們就按捺不住,開始上手了。函數不會用,有 google 哩,代碼不會寫,找 stackoverflow!於是對代碼所服務的對象而言,寫代碼成了一項高風險的活動:我們極其依賴代碼的作者碰巧是個能力不錯的人,她能在一邊完成高質量創作的同時,還可以夯實自己的基本功。
比如說一個簡單的任務:遍歷一個 list,解析出裡面的 tuple,然後將其插入到 priority queue 中排序。
一個有多年經驗的軟體工程師的做法是(假設用 python 實現):
- 大致想想就開始擼袖子寫代碼;
- 囧,不大記得 map 的用法了,究竟第一個參數是 function 還是 iterator,讓我先在 ipython 里試試 —— oh,原來第一個參數是 function,看我這記性;
- tuple 用得少,如何取 tuple 裡面第二個元素,這我得 google 一下 —— ah,原來可以 destructure,贊!(順便鄙視一下 php)
- python 有 priority queue 的支持么?我沒用過噯,沒事,祭出 stackoverflow —— python 真心棒,連這個都有現成的 heapq,stackoverflow 這段代碼正好是我要的,才五六行而已,直接 copy & paste。一下子就寫完了,yeah!(順便鄙視一下 php)
憋笑,我敢打賭這是不下半數工程師的日常。事實上,這個例子並不是我瞎編的,而是我在過去一年的面試中,大多數所謂「資深軟體工程師」在面試中的表現:在很多基礎的函數上卡殼,不得不 google。這並不算太糟糕,我見過從第一行代碼一路 stackoverflow 到最後一行的。
我不知道文字行業是怎麼面試的,如果一個面試者現場寫段文字還要查字典,翻《古詩詞大全》,能過關么?
我們究竟該怎樣正確地寫代碼?
在「創作」新的代碼之前,我們就應該已經對如何寫代碼了如指掌 —— 語言的基礎知識,經常使用的類庫都不該成為障礙。整個撰寫代碼的過程是流式的,就像作曲一樣,思維飄到哪,手指就落在哪,一氣呵成。當然,這有賴於平日里刻意的練習:不知道如何使用 map?OK,分別給定一個 list,dict,tuple,用 lambda 和不用 lambda 將 map / filter / reduce 各處理一遍。
聽著很熟悉,是不?小寶的鋼琴作業老師就是這麼布置的:左手哆咪騷哆咪騷練十遍。這「哆咪騷」就像咱們的 map 函數一樣,是基本功。
那位說了,這麼做成材期長,成百上千的類庫,永無止境的版本升級,每個都練十遍咱程序員傷不起,不現實。
你看,程序員就這麼傲嬌,三個月培訓一下就能拿相對的高薪(矽谷的現實),還要讓我做這枯燥的練習,憑什麼?
那麼我們折中一下,當我們撰寫上述的代碼時,起碼把忘記了怎麼使用的函數在 REPL 里好好練習一下;再把從 stackoverflow copy & paste 的代碼自個寫一遍,裡面涉及的類庫,函數,在 REPL 里多多練習練習,以至於下次再遇到同樣的需求,不至於還要網上尋找答案,這不過分吧?
願意這麼做的依然是少數。
經常跑馬拉松的人往往以賽促練。能夠以賽促練的人,首先得有大量的訓練基礎,才能承受一輪又一輪相對密集的比賽。有了這個基礎後,比賽進一步將自己的身體調節到合適的節奏,夯實心肺,錘鍊肌肉,同樣起到了練兵的效果。如果拿跑馬拉松類比,我們在日常工作中做的每一個大 feature,都可稱得上一次比賽,如果平時不好好積澱,這時而過就顯現了:別人一個 sprint 高質量完成的東西,你兩三輪 sprint 還做得磕磕絆絆,代碼活脫脫是 stackoverflow 的剪輯冊。
從直觀的感覺來說,軟體開發應該比跑馬拉松更容易以賽促練,甚至,以賽代練 —— 你做的每一個 feature,都能幫助你夯實你的技能。當然,這個前提是你每周都有大量的代碼量來兜底。寫的代碼多了,總會重複使用一些重要的函數和類庫,於是,正確使用它們的能力得到了強化。可惜,對很多很多的軟體工程師來說,這是個偽命題:
- 你一周其實真實代碼量並不大。你的大部分時間被消耗在了維護一個大型系統上,平均一周寫不了兩三百行代碼(注意不是 diff)。別忙質疑這個數字 —— 我在 Tubi TV 兩年,從零到一做了三四個系統,node 和 elixir 合併在一起,滿打滿算也就是四萬行代碼,兩年一百周,平均每周撐死了四百行代碼。
- 即便你代碼量不小,如果你負責的 scope 很小的話,寫多了也是重複勞動 —— 就像練字,別人是一千個字每個練五十遍,你是一百個字每個字練五百遍,同樣是五萬的量,下的功夫一樣,效果卻大相徑庭:別人亡口月貝凡已經練得諳熟,你還在比劃個十百千萬。
在提高代碼能力這事上,沒有銀彈,有的只是像鋼琴訓練那樣的 deliberate practicing。沒有 practicing,你會敗在 1) 上;practicing 夠了,但不夠 deliberate,你會敗在 2) 上。
所以還是那句話,多練,多讀,多寫,撒一層土,夯實,再撒一層。工作給不了你的,台上沒工夫練的,你要在業餘時間,在台下,把它找補回來。這才是代碼能力提升的奧義。
謝謝欣賞。
推薦閱讀:
※如何解決敏捷開發與CMMI的衝突?
※你不得不知的幾個互聯網ID生成器方案
※2017就要結束了,再學點什麼呢?
※優秀的項目管理與糟糕的項目管理
※突破舊思維