如何成為一個卓越的程序員

jopen 10年前發布 | 21K 次閱讀 程序員

        英文原文:How-to-be-a-great-software-developer

        作者是 Rails/Angular 開發者,企業家& YC alum。早先創建了 Clickpass.com 網站并出售。目前擔任 Brojure.com 的 OTO(唯一O(only)TO),兼職 entrepreneur first

        免責聲明這是一篇非常長的文章,比我通常會寫的主題要長得多。我編輯文章并發給朋友評審,直到他們都覺得文章沒有一字需要刪改的。我希望你也這么認為。

        如果有一件事是開發者都關心的,那就是成為更優秀的開發者。那你應該從哪里開始呢?你是否應該積累一些附加的賣點:比如專研 Node 知識和 no-sequel?或者你應該死記硬背專業的網關問題答案,并能按要求立即寫出冒泡排序算法和短連接算法嗎?或者有其他更基本和關鍵的東西更值得你投 入?

        我相信,作為一個程序員的資歷和價值并不是以你所知道的東西來衡量的,而是通過你做出多少成就來衡量的。這兩者是相關的,但又有本質的不同。你 的價值是你如何推動項目前進,如何鼓勵你的團隊也這樣做。在我十五年的開發生涯中,我從來沒有需要實現一個冒泡排序算法和短鏈算法。不過,我花費了成千小 時來編寫和重構賬戶管理工具,編輯套件,緩存邏輯,郵件接口,測試套件,部署腳本,JavaScript 分層,分析架構和文檔。這些都是有價值的事情,完成了這些事情推動了我們的前進。

        那些微小的組件是構建項目的磚瓦和沙礫,需要成百上千小時的辛勞工作來組建。盡管它們被用來組裝復雜系統,它們本身卻不應該是復雜的。你應該將 簡化這些組件作為目標。多年來,我學會簡單可以通過假以時日的不斷工作和重構來達到,而這比純粹“靈感一閃”的思考更容易得多。

        簡單和卓越通過一些事情或者任何可以讓工作完成并從回頭重新審視這樣的過程來不斷完善,這是最可靠的路徑。這也是那些公司和 MVP 試圖深入我們意識觀念的真諦,軟件也是如此。從一些可工作但丑陋的解決方案開始,你不斷應用這個丑陋和怪異的方案,不斷重構它為最簡單的形式。簡單從工作 中比“靈光一閃”來得更為可靠。通過寫代碼比費力思索更加可預期。簡單來自努力。

衡量一個開發人員的價值,不是通過你能達到的某個點的高度值,而是在于你表現線下的面積值。— Peter Nixey (@peternixey) April 22, 2014

        對于聰明的懶人來說,他們可以輕易展現自己的卓越才華,亮瞎同齡人的雙眼,然而公司卻不能建立在這些人之上,產品也無法落實在那些“卓越的才 華”上。公司是由那些每天進出辦公室,提交良好的代碼,并且也讓其他人也干同樣的事情的團隊和個人。偉大的產品由勤奮的馭馬驅動,而不是由那些盛裝的舞步 馬推動的。

        多年之前,Joel 創造了“明星程序員”這個詞多,它依賴公司對需要這樣缺乏合作的極客來完成所有事情的誤解。的確存在擁有這樣特質的人,但是人數不多。你發現他們的聰明缺 乏規律——讓他們感興趣的事情表現得驚人的聰明,然而在和其他人協作或與團隊無縫合作時,又顯得無法抱有期望。

        他們的成果是無法預期的,但是他們的成就又讓人艷羨,而且更具傳染性。他們的傲慢可能傷及到團隊的其他人員。它大聲而且響亮地釋放這樣的信號: 如果你夠聰明,你可以選擇你何時工作和你干什么。你成為了一個“Developer in Residence”。你不但吸取了薪水,也扭曲了你周圍工作人員的價值。

        所以現實是,你和你的團隊更可能依靠或者說應該依靠于那些值得依靠并可靠工作的人,而不是那些自認為是“明星程序員”或者“編程忍者”的人。

        卓越的開發者不是那些上手就可以寫出冒泡排序或者短鏈接算法的人。他們是你一旦將其安排在項目中工作,就會不停推動和鼓舞周圍每一個人來做到一 樣的人。讓明星程序員滾蛋,雇傭那些可以駕馭的馭馬(Fuck Rockstars. Hire workhorses),下面一些方法值得借鑒:

        為你的函數和變量取個好名字(編寫見名知意的代碼)

        這是一個難以置信的簡單開始,但是我認為它是編程中最重要的技巧之一。函數命名是問題定義直接表現,坦白的說,是編程最難的部分。(編注:ITWorld 在 2013 年發起的一個投票,結果顯示:《程序員最頭疼的事:命名》)

        名字是你代碼的的邊界條件,命名是你應該解決的首要問題。

        如果你的命名是正確的,也解決了邊界條件,使用這樣的名稱,你幾乎不可避免編寫出了高功能的代碼。

        考慮這樣的函數:

def process_text string   …
end

        它幾乎沒有透露它準備做什么或者是怎么實現的,但是:

def safe_convert_to_html string   ...
end

        它告知了接下來會發生什么,通過這個函數你可以預期它會完成什么,并且你可以多大程度重載這個函數。

        開發者可能會很高興重構一個“process_text”函數,同時將字符串轉換為 HTML 標簽并自動嵌入視頻。不過,這在一些使用這些函數地方時可能是完全不期望的。一旦你改動了它,你就制造了 bug。一個清晰的名稱,不但保住函數會做什么,也表明了它不會做什么。

函數名稱為函數和調用它們的代碼之間創建了契約關系。好的命名定義了好的架構。http://t.co/6JMyGvGuzl

— Peter Nixey (@peternixey) April 22, 2014

        一個好的函數,承諾了它會交付什么并如期望地交付了。好的函數和變量名稱,不但使得代碼更加清晰易讀,也為你縱橫交錯的代碼庫建立了成千上萬的約束。草率的命名意味著草率的約束,缺陷,甚至建立在它們之上更加草率的契約。

        不僅僅是函數命名可以衡量你的代碼質量,變量命名也應該加強。有時為了簡化,值得創建一個變量名來自注釋代碼邏輯。

        以下面的內容為例:

if (u2.made < 10.minutes.ago) 
   && !u2.tkn 
   && (u2.made == u2.l_edit)
  ...

        糟糕的變量名稱使得你很難弄清楚到底正在發生,甚至哪怕你這樣做了(成功了),你也難以保證 100% 清楚原作者意圖是做什么。它什么也沒告訴你。

        “and not”聲明經常讓人困惑(請永遠不要編寫“and not”與名稱結尾的代碼),如果你的工作是重構這樣的代碼,你不得不做一些復雜的猜測來推斷它原始的含義。

        不過:

if (new_user.created_at < 10.minutes.ago) 
  && !new_user.invitation_token 
  && (new_user.created_at == new_user.updated_at)

        我們將這些變量修改為一些更有意義的名字,代碼的含義立馬就變得更清晰了:

user_is_recently_created = user.created_at < 10.minutes.ago
invitation_is_unsent = !user.invitation_token
user_has_not_yet_edited_profile = (user.created_at == user.updated_at)
 if user_is_recently_created 
  && invitation_is_unsent 
  && user_has_not_yet_edited_profile
  ...

        我們還可以進一步要求對 if 語句聲明中的每一部分進行分離,命名組件并做文檔注釋。

        需要一些勇氣來寫像“user_is_recently_created”的變量名,因為這樣的命名邏輯模糊。不過我們時不時這樣做了,并且承認這告知了代碼閱讀者你做了什么假設。

        注意,這些方法比使用注釋要更加有效。一旦你改變了代碼邏輯就會要求你改變變量的命名,而使用注釋卻無法強制這一點。我很認同 DHH,注釋是危險的并且容易腐朽——最好是編寫自注釋的代碼。

        代碼自注釋越充分,其他人就更可能按照其初始的意圖來實現它,代碼也會有更好的質量。記住,在計算機科學中只有兩類問題最難:緩存失效、命名和 off-by-one 錯誤。(我懷疑作者是寫錯了,這是三個…)。

“如果你想成為一個偉大的開發者,請確保你寫的代碼讓人見名知意:也就是說代碼精確地完成了它名字告訴的東西” http://t.co/6JMyGvGuzl

— Peter Nixey (@peternixey) April 22, 2014

        在學習廣泛之前先精深某一方面——從里到外學習你選擇的技術棧。

        只有非常少的編程問題是真正新的。很多公司所做的技術工作,是之前的許多團隊已做過的。在 Stack Overflow 上吸引眼球的問題很少沒有在其他地方遇到過。

        因為這個確切的原因,你正在努力做的大部分事情,已經被你當前使用的技術棧解決過了。我有一次使用了 Rails 自帶的簡單而強大的方法,將其他人寫的 60 多行 Rails 代碼重構為一行語句,

大多數程序浪費了大量的時間,用于重新實現那些現有的功能。http://t.co/6JMyGvGuzl

— Peter Nixey (@peternixey) April 22, 2014

        這不僅浪費了他們的時間,而且他們新構建的代碼冗長且含有很多錯誤。新的代碼需要新的文檔注釋,新的測試來檢查,也讓代碼充滿噪雜,并且難以閱讀。和其他新代碼一樣,也容易產生 bug。使用技術棧經過嚴謹測試并且實際驗證的代碼,很少產生 bug。

        如果你是一個 Ruby 的開發者,請花時間好好學習 Ruby,尤其是數組的那些驚人多的方法。如果你是 Node 的開發者,請花時間了解它的架構、方法及理念體系。如果你是一名 Angular 的開發者,你應該敢于挑戰,并理解正由核心團隊錘煉的那不可思議的架構背后的邏輯。在你重新發明之前先詢問。你行走在巨人的陰影下,花費一些時間找到他們 的蹤跡,然后你會對他們已經建立的東西感到驚嘆。因為,如果你不這樣做,你只是把問題推給了后面的人,別人會指出為什么你偏偏選擇了你自己的小路走。

        學會辨識糟糕的代碼

        有時候,我注意到一些程序員挺不錯的,只不過他們趨于安逸,并沒有意識到他們的代碼其實可以寫得更好。這對于你個人的發展是一件極為糟糕的事 情,在你知道如何改進之前,先要知道什么是需要改進的。知道好的代碼應該是怎么樣的,壞的代碼長得怎么樣。據說,象棋大師比普通棋手花費多得多的時間,來 學習其他優秀棋手的如何下棋。我非常確信這對于開發者來說也是對的。

        能覺察到代碼異味,是提升你能力的重要的武器之一——哪怕只是有一點點異味或者聞起來可能有點異味。異味代碼,你可能不知道為什么,僅僅是覺得哪里不對的代碼。

        你可能做某件事情用了 60 行代碼感覺這很簡單,這也可能讓你覺得應該交由語言本身來處理卻被程序員手動處理了的感覺,也可能是你覺得這段代碼糟糕透頂且難以閱讀。這就是代碼異味。

        這不是件容易的事情,但是經過一些年,你會發現哪些代碼存在異味,漂亮的代碼應該是怎么樣的。你會開發出對代碼的審美觀,對于丑陋事物所帶有的丑陋理論會讓你感覺很不舒服。簡單即是美,而簡單正是我們所需要的。

        真理是,真實有時候是丑陋的,但是你應該不斷地追求美麗,并且當你感覺丑陋無法避免,你知道如何優雅地展示它。如果你不能編寫出優雅的代碼,最 少創建一個史萊克式的代碼,而在這之前,你需要培養出對代碼異味的感覺能力。如果你不知道好的代碼是怎么樣的,壞的代碼看起來是怎么樣的,那你怎么會想到 去改進它呢。

        編寫可讀性良好的代碼

        我有一次聽 Joel Spolsky 說,Stack Exchange 不是針對提出問題的人進行優化,而是對閱讀答案的人進行優化。為什么呢?因為相較于提出問題的個人,有多得多的人會去查看答案——應用最大化原則應該對讀者進行優化,而不是提問的人。

        我覺得你可以同樣的方式對待代碼。它可能只是由你一個人寫一次。但是它可能被其他許多人閱讀和編輯。你的代碼具有兩個功能:其一是滿足你當前的工作,其二是面對在你之后的每一個人,因此代碼應該始終對可讀性和可理解性進行優化。

        “代碼編寫一年后,從原作者眼光來說,也是全新的代碼 — Peter Nixey

如何成為一個卓越的程序員

        你代碼里面假定什么?你的方法實際返回什么?這個四層嵌套的 if/else if and not/unless 聲明究竟是在區分什么?

        有時候你需要的不僅是好的變量名,你也要圍繞著代碼進行測試,看它究竟需要什么,并使得代碼經久耐用。有效的代碼是可以工作的代碼,并且始終工作,即使被公司里每一個人都改過,都還能如常運行。

        寫的每一行代碼,其讀者會是那些對此不感興趣的,或者時間緊迫的團隊成員,他們可能要在接下來一年時間擴展這些代碼。請記住,那個不感興趣,或時間緊迫的人,或許就是你自己。

        根據代碼的生命周期來評估特性價值,而不是它的實現成本。

        新的開發者總是喜歡探索和發揮。他們喜歡最新最炫的東西。無論是 Nosql 數據庫,還是高并發的移動服務,他們想盡快了解和掌握所有這些東西,用完這些玩具,就撇下一堆垃圾給下一個開發人員來擦屁股。

狗不是為圣誕節準備的,特性也不是為下一個發布版本準備的。— Peter Nixey (@peternixey) April 22, 2014

        功能和架構的選擇,會影響所有你在這之上構建的東西。一旦抽象泄露,你在抽象中陷得越深,就有越多的東西會被玷污,或者這個泄露導致很多東西都“中毒”。

        實驗性的架構和某些很炫的特性應該極為謹慎采用。優先添加你需要的功能,而不是你想要的功能。同時請注重架構。把一些實驗玩具留給邊緣項目。你 創建的每一個組件,每一個前沿模塊合并到你的項目,會快速地改變你的軟件,也會讓你的項目受傷或直接破壞項目。如果你不希望在項目后期除了止血而干不了其 他事情,請不要首先將上述應用到你的項目中。

        了解和評估技術債務

        技術債務是你寫的代碼但沒有達到最優化或你想要的。它包含一些錯誤,雖然煩人,不過還是可以用的。它可能是一個單應用程序,不過你知道它可能發展為面向服務的程序,也可能是一個 20 分鐘的計劃任務需要被重構為 20 秒。

        這些成本不僅僅是累加的,而且是復合累加。愛因斯坦曾經說過:宇宙中沒有什么比復利更強大的力量了。同樣,在大型軟件開發中,也沒有什么比復合 技術債務更具破壞性的了。我們見過或構建的大部分項目,哪怕最小的改變也會花費數月的時間。針對碼基(code base),人們已經放棄了編寫更好代碼的想法,只是希望在修改的時候不至于導致站點整個崩潰。

        技術債務是項目中一個可怕的負擔。

        除非沒有技術債務。

和所有其他債務一樣,應用合理的話,技術債務也會給你帶來巨大的杠桿效應。— Peter Nixey (@peternixey) April 22, 2014

        不僅是這樣,技術債務可能是世界上最好的債務,因為你不一定每次都需要償還。當你開發一個功能結果發現它是錯誤的,或者當你開發一個產品結果不 能正常工作,你可以丟棄掉它們然后繼續。你可能丟棄功能相關的所有優化,測試和重構。因為這些不是必須的,那就不要去寫這些。這個時候就應該最大化你的杠 桿,留個空白,避免錯誤,僅僅為你需要的測試而進行測試。

        在一個產品和功能的早期,很可能你現在做的是錯誤的。你還處在探索階段。你要同時以產品和技術實現為核心。這期間可以大量借用技術債務。這不是修改零星錯誤和進行大量重構的時候,這時候你應該集中火力猛攻直到你達到(成果的)另一邊。

        不過當你發現,你確信你已經到了正確的位置并走出了另外一邊,這個時候需要進行梳理,并加強你的地位。把事情做得足夠好來推動你前進,償還足夠的技術債務來進入下一個階段。

對于初創公司來說,技術債務和其他許多事情一樣是一場跨越式的游戲。初始的代碼是試探性的代碼,它應該讓你快速前進,發 現問題和解決方案,給你恰當的空間來建立營地。你呆的時間越久,營地系統就需要更多內容,而你需要構建更大更強來支撐它。如果你僅僅只需要停留一周時間, 不要浪費時間來構建一個可以支持十年的基礎設施。

        檢查,再檢查你的代碼,你的問題由你來修復。

        “把代碼扔過籬笆”的工程師都是可怕的工程師。你應該保證你的代碼是可以工作的,這不是測試人員或者你同事的工作,這是你的工作。懶洋洋寫就的代碼會拖延你,延遲周期時間,產生 bug,有讓每個人惱火。

如果你一直提交破壞性的代碼,那么你就在對團隊其他成員不斷征稅。— Peter Nixey (@peternixey) April 22, 2014

        不要拿自己不當回事,覺得你只是個負擔,問題應該自己解決。

        每天至少(只)花 4 個小時做實際工作

        對于討論自我進步,關注和使用在開發者之間流行的生活技巧,簡單的真理是:你不需要做大量的工作,就可以實現高效。真正重要的是,你能持續地做到這一點。每天花費最少完整 4 個小時來做恰當(proper)的事情,日復一日,你會成為團隊中最有貢獻力的成員。

        不過,每天都抽出 4 個小時來工作比看起來要難得多。

        恰當的工作意味著沒有郵件,沒有新聞,沒有會議,沒有雜七雜八的瑣事。意味著一小時最少 45 分種的時間專注于(你正在做的事情)。一天 4 小時的工作意味著一天沒有會議,沒有漫長的午餐和休息時間討論足球。我相信,一天扎實工作八小時幾乎是不可能的。每天四小時也意味著你應該瞄準工作五或者 六個小時,這樣你才可能得到四小時的認真工作時間。

        這也意味著你可以擁有豐滿人生的同時,成為團隊中一個卓有成效的貢獻者。這意味著你不需要在 HN 上發表一個自我放棄“我忙死了,快來幫幫我”的帖子,這意味著你只要持續工作,你就能被重視和獲得尊重。

        軟件團隊并不因為人們每天工作四小時而比工作七小時的團隊進展慢(持續這樣的方式是非常瘋狂的)。他們慢下來是因為人們幾周都沒有找到方向,或 者那些響亮而空乏的嗓子,決定花費時間討論 google vs 非死book 的獲取策略而導致的無止境的咖啡休息時間。

        只要能工作就好,不要在乎你的進步看起來是如何緩慢或平庸…

每天工作四個小時,日復一日你會成為團隊中最優秀的人員之一。— Peter Nixey (@peternixey) April 22, 2014

        記錄已完成的事情,并和團隊成員分享

        不管你是如何記錄文檔,是通過類似 Copyin 的郵件列表,wiki 或者是代碼中的內嵌注釋,你應該花時間來解釋你的架構方法,和團隊其他成員一起學習。

        在安裝 Postgres 或者 ImageMagic 時遇到了問題?如果你覺得這解決起來比較困難,團隊的其他成員可能也會遇到這樣的困難,花費一些時間記錄下來并告訴團隊其他人你是如何做到的,節約他們下一次遇到問題時的時間。

        程序開發時最糟糕的事情是,整天和 bug 作戰或者處理安裝問題。如果你花費時間來記錄和分享你找到的方法,你可以從預先為你同事準備中贏得五倍你花費的這些時間。

        理解和欣賞處理太多測試和太少測試之間的微妙平衡

        測試是一個強大的工具。它允許你設置一個發布基準,你可以信賴你的發布,讓你不那么害怕制造它們。對發布的恐懼越少,你越這樣做你改進得就越快。

        不過,這也可能過頭。測試需要時間編寫,運行和更多的時間來維護。

可以想象測試是盔甲,你穿得越多你受傷的可能性就越小,不過也讓你更難進攻。— Peter Nixey (@peternixey) April 22, 2014

        你負重太多而無法前進,阻礙你彎曲四肢,無法移動。太少的話,第一次跨過混凝土地板的滑動就會傷到你,讓你流血。

如何成為一個卓越的程序員

        關于如何進行適量的測試,沒有直觀的答案,某些項目需要比其他項目更多的測試,測試是你專業化需要學習的一個全新的領域。

        花時間去理解什么是真正需要測試,如何編寫一個良好的測試。花時間去查看當測試添加值,或者最起碼你期望它們是怎么樣的。不要害怕進行測試,也不要害怕不進行測試。正確的處理方式是平衡,花時間去探索平衡點在哪里。

        讓你的團隊更出色

        這不同于其他點,這不是你可以獨自采取行動,也沒有明確的指標告知你其他行動是否有效。

        你的存在,是讓你的團隊變得更好還是更糟呢?你的代碼質量,你的文檔和你的技術有米有幫助到你周圍的人。你是否激勵和鼓勵你的隊友成為一個更優 秀的開發者?或者你就是那個導致 bug 的人,或者你堅持自己的觀點浪費數小時討論架構無關的廢話,因為它有助于掩飾你沒有做實際工作的事實?

        你應該讓你的團隊變得更好,總是有一兩種方法你可以讓你的團隊變得更好,通過你素養的熏陶而幫助其他人變得更強。然而,成為一個孤獨的“智者”可能是最缺乏價值的,或者說你能選擇的最有破壞價值。事實上,如果你選擇的維度并沒有讓你覺得厭煩,這可能不是一個好的選擇。

        It’s not who you are on the inside that defines you

        這是一個謙卑的智慧,在蝙蝠俠開篇就有這么一句,這句也一直伴隨著我。在電影的某個時間,蝙蝠俠在閑逛,表演著一個億萬富翁的花花公子。克里斯蒂安·貝爾懇求凱蒂·赫爾姆斯相信:他內在仍然是一個好人,她只是說了:不是你穿了什么,而是你做了什么展現你的價值。

        你作為一個開發者的貢獻,不是由你有多聰明或你知道多少來衡量的。這不是由你簡歷上的技術名稱縮寫,你工作的公司和你上過的大學決定的。它們暗示你能做什么,但是你的價值是由你做過什么,以及這些如何改變了項目和你周圍的人決定的。

        如果你想變得更好,請做好準備。

        翻譯: 伯樂在線 周昌鴻
        譯文鏈接: http://blog.jobbole.com/72457/

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!