這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。Fred Brooks(《人月神話》的作者)最早在他的論文“沒有銀彈——軟體工程的本質和偶然性(No Silver Bullet - Essence and Accidents of Software Engineering)”中提出了“10x程式員”的概念。技術社區對於這個概念呈現出兩級分化的觀點。Redis之父Salvatore Sanfilippo(antirez)列出了9種特質,他認為,如果一個程式員同時具備了這9種特質,那麼就可以說他是一個10x程式員。以下內容已獲得antirez的翻譯授權。
一個10x程式員,在相同條件下,可以完成十倍於普通程式員的工作。這裡所說的“普通程式員”,是指那些能夠勝任自己工作的程式員,只是他們不具備10x程式員的神奇能力。普通程式員代表了這個領域所有專業程式員的平均水準。
對於是否存在10x程式員這種“神獸”,編程社區的觀點呈現出兩級分化:有人認為根本不存在所謂的10x程式員,有人則認為不僅存在10x程式員,如果找對了門路,甚至能找到100x的程式員。
如果說編程是一項“線性”的工作,那麼很明顯,10x程式員是不可能存在的。一個跑步運動員怎麼可能跑得比另一個快上十倍?在相同時間內,一個建築工人建造的東西怎麼可能是其他人的十倍?不過,編程是一項很特別的設計工作。雖然程式員可能不會參與程式的架構設計,但程式的實現仍然涉及到一些設計工作,而這部分需要程式員去完成。
如果說程式的設計和實現不是線性,那麼在我看來,經驗、編碼能力、知識和去偽存真的能力就不僅僅是線性優勢,它們在編程過程中相互交織,成倍地發揮效能。當然,如果程式員能夠同時勝任設計和實現工作,那麼這種現象就尤為明顯。任務越是具有目標導向性,程式員就越是能夠以更少的付出達成相同的目標,從而體現10x程式員的潛在能力。如果手頭的工作很死板,而且限定了可使用的工具和實現方式,那麼10x程式員事半功倍的能力就會大打折扣。不過,在不改變大前提的情況下,程式員仍然可能通過局部的設計最佳化來改進工作,包括在項目的某些部分不按常理出牌。所以,他們可以少付出很多卻能達成幾乎相同的目標。
在我的二十年程式員生涯中,我與其他程式員一起工作,作為同事,或者由我指導他們達成目標,為Redis和其他項目貢獻代碼補丁。在工作過程中,我仔細觀察他們。與此同時,有很多人說我是一個高能的程式員。不過我不認為自己是一個工作狂,我只是編碼速度比較快而已。
下面列出了我認為可以用於區分程式員生產力高低的重要特質。
編程裸技能:完成子任務
從處理編程子任務可以看出一個程式員的短板和長處,比如實現一個函數或者一個演算法。但從我的經驗來看,擅於應用基本的編程技能來高效完成任務的程式員並非如人們所想得那樣普遍存在。有時候,團隊裡有些不是很稱職的程式員,他們甚至不知道該怎麼寫一個簡單的排序演算法,但比起那些看似稱職卻缺乏實戰經驗的程式員,這些不稱職的程式員卻能完成更多的工作。
經驗:模式比對
我認為,經驗就是一系列解決方案,它們已經被證實可以用於處理一些重複性的任務。經驗老道的程式員知道該如何處理各種子任務,這樣不但省掉了很多設計工作,而且避免了很多設計錯誤,而設計錯誤是簡潔性最大的敵人。
專註:實際時間和假設時間
花在編碼上的時間不僅要看數量,也要看品質。造成注意力不集中的因素既有內部的,也有外部的。內部的因素包括拖延、對手頭的項目不感興趣(一個人總是做不好自己不喜歡的事情)、缺乏練習、缺乏睡眠。外部因素包括頻繁的會議、不固定的工作環境、同事的打擾,等等。集中注意力和避免被打擾對於提高編程效率來說是至關重要的。有時候,為了集中注意力,需要採取一些極端的手段。例如,我會時不時地查看郵件,但大部分郵件先不做回複。
設計權衡:用5%換取90%
項目的非根本性目標在很大程度上導致了設計的複雜性,或者導致無法達成其他更重要的目標,因為根本性功能和非根本性功能在設計上存在競爭關係。如果意識不到這點,複雜性就會隨之而來。實現全面的設計並不是件輕而易舉事,付出與回報之間不能通過簡單的比例來衡量。對於設計者來說,意識到這一點是很重要的。如果項目要最大化產出,那麼就要把精力集中在重要的事情上,並在合理的時間內完成。例如,在設計Disque(一個分布式訊息佇列)時,我發現對訊息進行排序之後,項目的其他方面就會得到實質性的改進:可用性、查詢和用戶端互動、簡潔性和效能。
簡潔性
簡潔性是成敗之間最為明顯的分界點。理解複雜性的產生過程有助於理解什麼是簡潔性。我認為,不願意做出設計權衡和設計錯誤的累積是導致複雜性的兩個主要因素。
在設計過程中,每次走錯一條道,就離最優的方案越來越遠。一個初始的設計錯誤,如果沒能被糾正過來,那麼可能導致一條道走到黑,最終得到的是一個複雜的系統,而不是對原先系統的重新設計。項目會因此變得更加複雜和低效。
程式員可以在腦子裡進行“概念驗證”,從大量簡單的設計想法中選擇可行性最高且最直接的方案,從而達成簡潔性。在後續的改進工作中,個人的經驗和設計能力開始發揮作用,為子任務找到更加明智的解決方案。
不過,如果系統複雜性不可避免,那麼在放棄掙紮之前也要盡量想辦法降低系統複雜性,甚至嘗試採取完全相反的設計。
完美主義(為了偏袒設計而放棄生產力)
完美主義可以分為兩種:一種是追求程式極致效能的工程文化,另一種是個人特質。不管是哪一種完美主義,它們都會對程式員實現快速交付造成阻礙。完美主義和對外部評判的恐懼會導致設計上的偏袒,程式員根據主觀的心理因素和無關緊要的衡量參數做出設計決策,卻忽略了健壯性、簡潔性和及時交付。
知識:理論有益
在處理複雜任務時,具備一些理論方面的知識會對設計產生重要影響,比如資料結構方面的知識、瞭解計算能力的局限性和一些重要的演算法。我們沒有必要成為無所不知的超級專家,但至少要知道一些問題的潛在解決方案。例如,在給一個給定流統計單一元素的個數時,我們可以在設計上做出權衡(接受一定程度的錯誤),並結合機率集合的基數估計(cardinality estimation)演算法,避免設計出複雜、緩慢、低記憶體效能的解決方案。
底層:理解機器原理
程式的很多問題都是源於對電腦工作原理的誤解,即使是使用進階語言開發的程式也不外乎如此。這種情況可能導致一個項目需要重新設計和實現,因為項目所使用的工具和演算法出現了根本性的錯誤。精通C語言,知道CPU的工作原理,瞭解系統核心的行為以及系統調用的實現原理,做到這幾點可以挽救你於危難之中。
調試技能
尋找和解決bug經常會佔用我們大量的時間。尋找引起bug的問題根源,在合理的步驟內修複bug,以簡單的方式編寫包含較少bug的代碼,對於程式員來說,做到這幾點可以顯著提升效率。
一個程式員如果具備了上述幾點特質,那麼他們的產出將會有10倍的提升,對此我一點也不感到驚訝。綜合這些特質,從一個可行的模型開始,實現更簡單更好的設計。我認為簡潔性就是一種“投機取巧的編程”。簡而言之,就是在開發的每個階段選擇性地實現一些功能,以最小化的付出為使用者帶來最大化的影響。