在提高程式碼能力這事上,沒有銀彈


合抱之木,生於毫末;九層之臺,起於累土;千裡之行,始於足下。 - 《道德經》轉眼間女兒到了學琴的年齡。我對樂器,純是葉公好龍,家裡擺著鋼琴,小提琴,手風琴,自己...

- 2017年12月07日04時00分
- 知乎專欄

合抱之木,生於毫末;九層之臺,起於累土;千裡之行,始於足下。
- 《道德經》

轉眼間女兒到了學琴的年齡。我對樂器,純是葉公好龍,家裡擺著鋼琴,小提琴,手風琴,自己卻連五線譜也不識,所以無法督促丫頭練習,於是這重擔落在了老婆身上。老婆是個虎媽,嚴厲起來毫不含糊,說練不完琴不許吃飯,就不許吃飯,丫頭撒潑打滾,哭天搶地,姥姥紅著眼圈在旁勸阻都無濟於事。這種時刻,我自然是於心不忍,明面裡卻必須和老婆保持高度一致,所以只能默默地滾到一邊,安安靜靜扮個風輕雲淡的土肥圓 ——心裡還是會忐忑:這麼搞法,不會把娃兒的興趣折騰沒了吧?

然而我的擔心是多餘的。丫頭週六學琴,往往週六和週日最苦,哭嚎也是這兩天最甚。這是因為學了新的曲子,她還不熟,經常彈錯,彈錯就要重彈,老師佈置的作業要彈很久很久才能過關。到了週二週三,她漸漸熟絡了,指下生風,哭嚎聲越來越少,週四週五就遊刃有餘了,多數情況都能開開心心地彈完。因為媽媽的嚴厲,她起初吃了不少苦頭,但漸漸苦盡甘來,嚐到了那種「直掛雲帆濟滄海」的爽快。在最痛苦的時候,她大哭著叫喚「媽媽我再也不想彈老師佈置的作業了」,可在一月一度的「家庭演奏會」上,她還是會喜滋滋地,滿滿成就感地向遠在國內的親人們展現她的能耐。

好多同學在後臺問我,程式碼的能力怎麼練就。其實是一樣的理兒。多練,多讀,多寫。

軟體開發的教育作為一門非常年輕的學問,僅僅走過了幾十年,和鋼琴教育數百年的歷史相比,是滄海一粟。鋼琴有成熟的培訓和認證體系,軟體至今還是撞大運。其實想想鋼琴和軟體有很多相通之處:學鋼琴需要先學習一門指法,和一門語言(五線譜);學程式碼也需要先學習一門指法,和一門語言(比如 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)上。

所以還是那句話,多練,多讀,多寫,撒一層土,夯實,再撒一層。工作給不了你的,臺上沒工夫練的,你要在業餘時間,在臺下,把它找補回來。這才是程式碼能力提升的奧義。

謝謝欣賞。

科技

立刻分享


最新發布內容

熱門閱讀