程式設計師的工具

infoq發表於2014-03-11

 編碼工具

  編碼本質上來說是一種以鍵盤輸入操作為主的工作。因此,輸入程式碼速度的快慢很大程度上影響了一名程式設計師的效率。我是通過以下手段來提高輸入程式碼速度的。

  鍵盤佈局

  很多程式設計師都不知道我們使用的鍵盤佈局(就是指字母鍵,數字鍵和符號鍵的所處的位置)並非只有一種。絕大部分人使用的是標準鍵盤佈局,也被稱為QWERT鍵盤(以左手上方那排字母鍵命名的)。但是很遺憾,這種佈局的設計初衷其實並不是為了提高打字速度的。

  我大概從一年多前開始學習使用一種叫做“Dvorak”的鍵盤佈局。使用這種佈局輸入同樣一段文字時,手指在鍵盤上的移動距離要比標準佈局減少至少50%。在轉到Dvorak佈局之前,我使用QWERT鍵盤有20多年了,但是我實際只花了大概一個多月的時間來完成鍵盤佈局的切換。當然,在這一個多月的時間裡,我每晚都堅持練習打字一小時左右。

  其實,我現在使用的也不是標準的Dvorak鍵盤,而是一種叫Programmer Dvorak的鍵盤佈局。這種佈局在標準Dvorak的基礎上,根據程式設計師的需要對數字和符號鍵的位置及輸入方式做出了調整,目的就是提高程式設計師的輸入程式碼速度。舉例來說,使用Programmer Dvorak佈局輸入數字時,需要按Shift鍵,而輸入符號(如(), [], {}, =)時則不需要按Shift。寫程式碼時輸入這些符號的次數顯然要遠遠超過數字,這種變化對速度的提升效果不可忽略啊。

  根據網上找到的研究資料表明,Dvorak佈局對輸入中文同樣會提升速度。程式設計師每天畢竟還是有不少時間會花在其他事情上面(上網找資料,聊天,寫郵件等等),這些需要打字的事情效率提高了,同樣有幫助。

  程式碼編輯方式

  相信很多程式設計師都聽說過“Vi”這種文字編輯方式吧。可以說“Vi”就是為了編碼而設計的,比起使用記事本那樣的編輯方式要高效很多。我在所有的開發環境中(如Intelliji和Sublime)都會安裝Vim(Vi improved)的外掛。Vim可以快速定位,查詢和修改程式碼,另外還有很多非常強大的編輯功能。要學習Vim,除了網上查資料之外,還可以通過遊戲(http://vim-adventures.com/)和挑戰(http://vimgolf.com/)來練習。

  當然,我並不反對使用Emacs,只是自己還沒有時間學習,無法給出評價和比較。不過,網上有關Emacs和Vim孰優孰劣的討論,我都是無視的。

  開發環境和快捷鍵

  編碼時,我會盡可能使用快捷鍵,儘量不用滑鼠。編碼時使用滑鼠,可以說是程式設計師的效率殺手。因為使用滑鼠時程式設計師的一隻手就會離開鍵盤,導致輸入程式碼的間隔加長。其實,使用Vim和快捷鍵的道理是一樣的,就是為了讓雙手儘量少的離開程式碼輸入區(字母鍵,數字鍵和符號鍵)。如此說來,使用鍵盤的“上下左右”鍵也會影響效率,因為這些鍵通常在鍵盤的右下角且離開字母鍵區比較遠。

  常用的開發環境一般對快捷鍵的支援都不錯,除了預定義的快捷鍵之外,還可以自定義快捷鍵。另外,在Eclipse和Intelliji中有如mousefeed和key promoter這樣的外掛,他們會在程式設計師沒有使用快捷鍵的時候給出提示,或者提醒程式設計師為一些使用到但沒有對應快捷鍵的操作設定快捷鍵。

  我鼓勵程式設計師根據習慣來設定自己順手的快捷鍵,不要拘泥於開發環境預定義的那些。遇到自己的快捷鍵和預定義的衝突時,如果預定義的操作並不使用或很少使用,可以果斷解除原有設定,使用自定義快捷鍵。而要熟練掌握快捷鍵並沒有什麼竅門,堅持在程式設計練習和工作中多使用就可以了。去背誦那些快捷鍵手冊是沒有什麼用處的。

  我目前主要的開發環境是Intelliji社群版(針對Java和Scala)和Sublime(其他語言或者工具,如Ruby, Python, PLSQL, Robotframework等等)。他們都是免費的開發環境,可用的外掛很多。

 敏捷工程實踐相關的工具

  上面提到的編碼工具對效率的提升都很直接。下面我將要提到的工具,和程式設計師如何來寫程式碼和設計程式碼有關。

  單元測試框架

  測試驅動開發(TDD)是我推崇的程式設計和設計方法,可以幫助程式設計師寫出簡潔和設計合理的程式碼。而TDD中產生的單元測試,通常是用某個單元測試框架(UT框架)來執行的。UT框架這個工具並不是TDD所必須的,因為編寫和執行測試本身並不複雜。不過使用了UT框架之後,可以簡化單元測試編寫,執行和組織,對於測試的維護和管理還是有幫助的。

  我使用的UT框架包括JUnit(Java),Scala-test(Scala),RSpec(Ruby)等等。有些UT框架提供了一些強大的功能,在使用這些功能時要小心,因為用得不好可能會影響單元測試的可讀性。舉例來說,很多UT框架都提供了資料驅動測試的功能(Data Driven Test)。雖然說這個功能可以簡化單元測試的編寫,但是我使用後發現,如果大量使用資料驅動測試,會使得單元測試的可讀性下降。原因在於資料本身不一定能表達測試和設計的意圖,從而導致測試難以維護。

  重構工具

  重構指的是在不改變程式碼行為的前提下改善程式碼的設計,它是測試驅動開發中的重要一環。以Java為例,Eclipse和Intelliji都提供了很好的重構工具支援,可以大大減少重構的工作量。不過,在使用重構工具之前,程式設計師應該很清楚為什麼要做某個重構(如發現了程式碼臭味),以及要使用哪種重構方法。有些稍微複雜一點的重構(如移動方法),因為開發環境對其支援有限,無法通過工具來實現時,就需要程式設計師手工來完成。實際上,我建議每個初學重構的程式設計師一開始不要使用工具重構,而是手工重構程式碼。這樣對於學習如何小步重構,在重構中如何讓測試失敗的時間最小化,都是很有幫助的。

  由於程式碼的複雜性,有時即使是看上去很安全的重構(如重新命名),因為重構工具還不夠智慧(不同開發環境的表現也不同),還是可能出現修改之後的程式碼發生了行為上的變化。因此,即使使用工具來重構,也需要有測試來確保程式碼原有的行為沒有發生變化。切不可因為使用了重構工具,就在不寫測試的情況下面對程式碼進行修改。

  Mock框架

  Mock框架指的是在單元測試中使用的那些用來隔離被測程式碼依賴的工具。還是以Java為例,Mock框架其實很多,如EasyMock,JMock,Mockito等等。和UT框架及重構工具類似,使用Mock框架可以簡化在單元測試中隔離依賴的工作,避免手工寫隔離程式碼的麻煩。同樣和重構工具類似,我建議初學Mock的程式設計師先不要使用這類框架,而是手工來隔離被測程式碼的依賴並做相應的驗證。我遇到過很多會使用Mock框架的程式設計師,不會手工寫Mock的程式碼。究其原因還是他們並沒有理解在測試中到底要如何來隔離依賴,以及要如何來做驗證。

  有些Mock框架(如PowerMock)過於強大(比如可以隔離一些靜態或final方法),我並不推薦使用。原因在於隔離依賴的目的是讓被測程式碼的設計更加合理。如果在單元測試中要為被測程式碼隔離一些靜態或final方法,那麼用PowerMock固然很方便,但是這樣做會讓程式設計師忽略程式碼可測性差的問題。在這種情況下,只做到為了寫測試而去隔離依賴是不夠的。程式設計師應該考慮是否先調整程式碼的設計,使得測試更容易寫,並且依賴更容易隔離。實際上,如果改善了程式碼的可測性,一般的Mock框架也就夠用了。

  自動執行單元測試的工具

  我最早是不用這種工具的,因為通過手動執行單元測試(使用快捷鍵)體驗到測試驅動開發中的測試失敗和通過,是實踐和練習TDD非常重要的一步。後來習慣TDD之後,我嘗試了一個叫infinitest的工具(Eclipse外掛),可以在儲存程式碼的時候自動執行受影響的單元測試。一開始感覺不錯,但是我試用了一段時間之後,發現這個工具執行測試不太穩定,經常莫名其妙的出問題,而且有時還會執行很多不相關的測試。

  其實,在Eclipse和Intelliji中可以定義一個重複執行上一次單元測試的快捷鍵。只要恰當的設定,也可以做到一鍵儲存程式碼並執行測試的效果。而且,這樣還可以選擇需要執行測試的範圍,避免執行那些無關的測試。所以,這類自動執行單元測試的工具,我現在不推薦使用。

  小結

  上面介紹了不少與寫程式碼和設計程式碼相關的工具,相信大家已經發現了這類工具的一些共同之處。首先,使用這些工具前要明白相應實踐的目的和原理。其次,即便工具可以提高效率,以手工的方式來實現程式碼仍然是一種很好的學習方法。最後,現在很多工具都存在過度開發的問題,通常是因為忽略了它們自身所服務領域實踐或原則的本質目標。因此,在使用這些工具時,程式設計師要學會取捨,真正做到讓工具“為我所用”,而不是“為了工具而工具”。

 程式語言

  最後,我想說“程式語言”對程式設計師來說也是一種“工具”。我覺得討論程式語言的孰優孰劣沒有任何意義。我一直很反對網上各種有關語言好壞的所謂論戰,程式設計師為什麼只能學一門語言呢?如果你不會一門程式語言,你就無法理解那種語言解決問題的思維模式。我覺得一個程式設計師至少要學一門物件導向語言,一門函式式語言,以及一門動態語言,不然他的人生就是不完整的。可惜的是,我看到過很多程式設計師都只會一門程式語言(其中Java居多,而Java則是我見過“語法和語言特性”最弱的一門主流語言了),更有甚者還會鄙視或者拒絕學習其他語言。對於這樣程式設計師,我只想說“雖然你手上有一把榔頭,但這不表示世界上所有的東西就都成釘子了”。

  時至今日,很多語言都在相互學習和滲透。.Net、C++和Java陸續支援Lambda表示式(函數語言程式設計)就是一個很好的例子。我非常喜歡函數語言程式設計中的一些語言特性,如不可變數,高階函式等等。這些特性都可以幫助程式設計師寫出更加簡潔和可讀的程式碼來。另外,嘗試一下多語言程式設計,是件非常有趣的事情。我最近就試過用RSpec來測試驅動開發PLSQL的程式碼。說到底,專案或產品開發時,使用的程式語言也應該是“浮現”出來的。哪種語言解決問題最有效就應該用哪個。

  有些程式設計師說學語言要忌“多而不精”,這點我很贊同。不過,對於“精通一門程式語言”的定義,每個人的理解不盡相同。我自己的定義是(以Java為例),熟練使用所有可以簡化程式碼的語法,以及熟悉基本類庫的使用(比如資料型別和集合型別),其他一些類庫可以視需要再學習。另一方面,我覺得沒有必要強求“精通”了一門語言之後再去學下一門語言。畢竟對語言的精通程度是和你在練習和工作中使用這門語言的時間長短有關的,而且語言本身也是一個不斷髮展的東西。通常抱有這種想法的程式設計師,只是為了逃避學習新語言找藉口罷了。

 總結

  程式設計師的工具遠遠不止我上面提到的這些。很多開源的技術框架和工具軟體,我覺得都應該算進來。好的程式設計師其實都很“懶”,因為他們總是想著把複雜繁瑣的事情變得簡單快捷,可以花更少的時間達到同樣的效果,所以他們選擇了一些“工具”來提高效率。同時,好的程式設計師也很清楚使用這些工具背後的原因,只會根據需要來選擇合適的“工具”,不會“為了工具而工具”。對我來說,如果使用工具可以幫助提高工作的效率,就會考慮使用或試用。反之,如果降低效率,則堅決不用。如果提高效率不明顯,則要慎用並要持續關注效果。

  要用好工具都離不開練習和工作中的不斷使用,希望本文可以幫助程式設計師找到合適自己的工具,從現在開始,從“我”做起,為了提高效率而努力。

相關文章