高效能程序員的七個習慣
昨天收到一個讀者留言,問作為程序員,有什么學習和工作上的好習慣可以借鑒?想了想,干脆附庸風雅一下,總結個『高效能程序員的七個習慣』吧。Disclaimer:一家之言,可不信,但不可全信。
擁抱 unix 哲學
每個程序員入門的第一堂和第二堂課應該是和 unix 哲學相關的內容,簡言之就是:做一件事,做好它。具體點:
- 小即是美。
- 讓程序只做好一件事。
- 盡可能早地創建原型。
- 可移植性比效率更重要。
- 數據應該保存為文本文件。
- 盡可能地榨取軟件的全部價值。
- 使用 shell 腳本來提高效率和可移植性。
- 避免使用可定制性低下的用戶界面。
- 所有程序都是數據的過濾器。 </ul>
再具體一些(TL;DR):
In [1]: import this The Zen of Python, by Tim PetersBeautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. Unless explicitly silenced. In the face of ambiguity, refuse the temptation to guess. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than right now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those!</pre>
選一個樣板,follow 之
每個 NBA 新秀都有自己的樣板,我們也總習慣稱某足球新星為『小羅』,『小小羅』。樣板為你提供了可模仿可追趕的對象,同時也讓你審視自己究竟想成為什么樣的程序 員。我的樣板是 Greg Pass 和 Werner Vogels,雖然我這輩子可能也達不到他們的高度,可這并不妨礙向著我心目中的明星一步步靠近。
寫代碼,而不是調代碼
寫軟件最糟糕的體驗恐怕是邊寫邊調,寫一點,運行一下,再寫一點。是很多程序員都會這么干。原因有二:1. 不熟悉相關的代碼(類庫),需要邊寫邊運行保證代碼的正確。2. 現代編程語言的 REPL (Read-Evaluate-Print-Loop,就是語言的 shell)能力助長了這一行為。
寫系統軟件的人很少這么做。他們手頭糟糕的工具讓邊寫邊調的行為成為效率殺手 —— 如果稍稍改動,編譯就要花去幾分鐘,甚至更長的時間,你還會這么干么?所以他們往往是寫完一個模塊,再編譯調試。(由此看來,高效的工具有時候是把雙刃劍啊)
我覺得寫代碼就跟寫文章一樣,構思好,有了大綱,就應該行云流水一樣寫下去,一氣呵成,然后回過頭來再調整語句,修改錯別字。如果寫完一段,就要回溯檢查之前寫的內容,效率很低,思維也會被打散。
靠邊寫邊調做出來的代碼還往往質量不高。雖然局部經過了雕琢,但整體上不那么協調,看著總是別扭。這就好比雕刻,拿著一塊石頭,你先是精修了鼻子,然后再一點一點刻畫面部。等修到耳朵的時候,鼻子可能過大或過小,即便再精美,它也得不到贊賞。
聰明地調試
軟件總會出問題。遇到問題,很多程序員就會用 IDE 在各種可能的地方加斷點調試,如果沒有 IDE,那么各種 print/log 手段一齊拋出,有棗沒棗打一桿子再說。
優秀的程序員會在撰寫代碼的時候就考慮到調試問題,在系統關鍵的節點上注入各種等級的調試信息,然后在需要的時候打開相應的調試級別,順藤摸瓜,避免了不靠譜的臆測。這是調試之『道』。
很多問題打開調試開關后就原形畢露,但有時候靠調試信息找到了初步原因,進一步定位問題還需要具體的工具,也就是調試之『術』,如上文所述之斷 點調試。有些時候,遇到靠類似 gdb(如 python 的 pdb)的工具無法解決的問題時(如性能問題),你還需要更多的調試工具做 runtime profiling,如 systemtap。
使用標記語言來寫文檔,而非 word/power point
不要使用只能使用特定軟件才能打開的工具寫文檔,如 word/page 或者 power point/keynote。要使用『放之四海而皆可用』的工具。
java 的市場口號是:『一次編寫,到處運行』,對于文檔,你也需要這樣的工具。Markdown (md) / Restructured Text (rst)(以及任何編輯語言,甚至是 jade)就是這樣的工具。通過使用一種特定的文本格式,你的文檔可以被編譯成幾乎任意格式 (html,rtf,latex,pdf,epub,...),真正達到了『一次編寫,到處運行』。最重要的是,由于邏輯層(文章本身)和表現層(各種格 式,字體,行距等)分離,同樣的文檔,換個模板,就有完全不一樣的形象。
除非必須,我現在所有的文檔都是 md 或者 rst 格式。
一切皆項目
程序員的所有產出應該項目制。軟件自不必說,文檔和各種碎片思想也要根據相關性組織成項目。舉一些我自己的例子:
- 我的博客是一個名叫 jobs 的 github 項目
- 我的微信文章全部放在 craftsman 這個項目中
- 我學習某種知識的過程(比如說 golang)會放在一個或若干個項目中
- 我工作上每個項目的各種產出(包括會議紀要)會按照項目對應生成 git repo </ul>
- 系統級(realtime):C (可能以后會是 rust)
- 系統應用級(realtime):erlang(養成中)
- 系統應用級(非 realtime):golang(養成中)
- 應用級:python
- Web 后端:python,nodejs,golang
- Web 前端:javascript
- 設備端:Android Java(暫無計劃) </ul>
項目制的好處是具備可回溯性。每個項目我可以用 git 來管理,這樣,幾乎在任何一臺設備上我都可以看到我之前的工作。想想你三年前寫的某個文檔,你還能找到它么?你還能找回你的修改歷史么?
項目制的另一大好處是可以在其之上使能工具。比如說你看到的這些微信文章,我隨時可以
make publish YEAR=2014
來生成包含了 2014 年我所寫文章的 pdf。
心態開放,勇于嘗試
在程序員社區里,語言之爭,系統之爭,軟件思想之爭幾乎是常態。python vs ruby,go vs java vs erlang vs rust,scala vs cljure,OOP vs FP,iOS vs Android。其實不管黑貓白貓,抓到老鼠的就是好貓,非死book 還用 php 呢。程序員應該用開放的心態去包容新的技術,新的思想,勇于嘗試,而不是立即否定。這個世界最悲哀的是,手里有把錘子,看什么都是釘子(或者說,眼里就只 能看見釘子)。
我接觸 mac 時間不過三年。可這三年時間,我從對 mac 不屑,到深深熱愛,最終成為 mac 的一個重度用戶。很多東西用過才知道,不嘗試不接觸我可能永遠活在自己下意識構筑的無形之墻的另一邊。
最近的兩年里我學習了 erlang,golang,scala,還看了一點點 clojure 和 rust。目前我熱衷于 golang 開發,但并不妨礙我繼續擁抱 python 和 nodejs。每個程序員要在不同的層級上有一門主力語言,比如說我:
這個列表你不必參考,我只是想用此來說明心態越開放,你看到的世界就越大。
<span id="shareA4" class="fl"> </span>