本節書摘來自異步社群《編寫可維護的javascript》一書中的第1章,第1.1節,作者: 【美】nicholas c. zakas 譯者: 李晶 , 郭凱 , 張散集 更多章節内容可以通路雲栖社群“異步社群”公衆号檢視。
編寫可維護的javascript
“程式是寫給人讀的,隻是偶爾讓計算機執行一下。”
——donald knuth。1
當你剛剛組建一個團隊時,團隊中的每個人都各自有一套程式設計習慣。畢竟,每個成員都有着不同的背景。有些人可能來自某個“皮包公司”(one-man shop),身兼數職,在公司裡什麼事都做;還有些人會來自不同的團隊,對某種特定的做事風格情有獨鐘(或恨之入骨)。每個人都覺得代碼應當按照自己的想法來寫,這些通常被歸納為個人程式設計嗜好。在這個過程中2應當盡早将确定統一的程式設計風格納入議題。
我們會經常碰到這兩個術語:“程式設計風格”(style guideline)和“編碼規範”(code convention)。程式設計風格是編碼規範的一種,用來規約單檔案中代碼的規劃。編碼規範還包含程式設計最佳實踐、檔案和目錄的規劃以及注釋等方面。本書集中讨論javascript的編碼規範。
為什麼要讨論程式設計風格
提煉程式設計風格是一道工序,花再多的時間也不為過。畢竟每個人都有自己的想法,如果一天當中你有8小時是在寫代碼,那麼你自然希望用一種舒服的方式來寫代碼。剛開始,團隊成員對新的程式設計風格有點不适應,全靠強勢的項目組長強制推行才得以持續。一旦風格确立後,這套程式設計風格就會促成團隊成員高水準的協作,因為所有代碼(的風格)看起來極為類似。
在團隊開發中,所有的代碼看起來風格一緻是極其重要的,原因有以下幾點。
任何開發者都不會在乎某個檔案的作者是誰,也沒有必要花費額外精力去了解代碼邏輯并重新排版,因為所有代碼排版格式看起來非常一緻。我們打開一個檔案時所幹的第一件事,常常不是立即開始工作而是首先修複代碼的縮進,當項目很龐大時,你會體會到統一的程式設計風格的确大幅度節省了時間成本。
我能很容易地識别出問題代碼并發現錯誤。如果所有代碼看起來很像,當你看到一段與衆不同的代碼時,很可能錯誤就産生在這段代碼中。
毫無疑問,全球性的大公司都對外或對内釋出過程式設計風格文檔。
程式設計風格是個人的事情,隻有放到團隊開發中才能發揮作用。本書的這部分給出了javascript編碼規範中值得關注(推薦)的方面。在某些場景中,很難說哪種程式設計風格好,哪種程式設計風格不好,因為有些程式設計風格隻是某些人的偏好。本章不是向你灌輸我個人的風格偏好,而是提煉出了程式設計風格應當遵循的重要的通用準則。本書附錄a中給出了我個人的javascript程式設計風格。
有用的工具
開發編碼指南是一件非常困難的事情—執行是另外一回事。在團隊中通過讨論達成一緻和進行代碼評審(code review)時,每個人都很關注編碼風格,但在平時大家卻常常将這些抛在腦後。工具可以對每個人實時跟蹤。這裡有兩個用來檢查程式設計風格的工具,這兩個工具非常有用:jslint和jshint。
jslint是由douglas crockford建立的。這是一個通用的javascript代碼品質檢查工具。最開始,jslint隻是一個簡單的查找不符合javascript模式的、錯誤的小工具。經過數年的進化,jslint已經成為一個有用的工具,不僅僅可以找出代碼中潛在的錯誤,而且能針對你的代碼給出編碼風格上的警告。
crockford将他對javascript風格的觀點分成了三個不同的部分。
“javascript風格的組成部分(第一部分)”,包含基本的模式和文法。
“javascript風格的組成部分(第二部分)”,包含一般性的javascript慣用法。
“javascript程式設計語言的編碼規範”,這個規範更加全面,從前兩部分中提煉出了程式設計風格的精華部分,同時增補了少量的程式設計風格指引。
jslint直接吸納了很多crockford所提煉的程式設計風格,而且很多時候我們無法關閉jslint中檢查程式設計風格的功能。是以jslint是一個非常棒的工具,當然前提是你認可crockford關于程式設計風格的觀點。
jshint是jslint的一個分支項目,由anton kovalyov建立并維護。jshint的目标是提供更加個性化的javascript代碼品質和程式設計風格檢查的工具。比如,當出現文法錯誤的時候,jshint幾乎可以關掉所有程式設計風格檢查,這樣你可以完全自定義消息提示。kovalyov非常鼓勵大家通過github上的源代碼庫參與jshint項目并為之貢獻代碼。
你可以将這些工具中的一種內建到打包過程中,通過這種方式推行編碼規範是一個不錯的方法。這種方法同時可以監控你的javascript代碼中潛在的錯誤。
程式設計風格指南的核心是基本的格式化規則(formatting rule)。這些規則直接決定了如何編寫高水準的代碼。與在學校學習寫字時所用的方格紙類似,基本的格式化規則将指引開發者以特定的風格編寫代碼。這些規則通常包含一些你不太在意的有關文法的資訊,但對于編寫清晰連貫的代碼段來說,每一條資訊都是非常重要的
關于javascript編碼風格,我們首先要讨論的是(幾乎所有的語言都是如此)如何處理縮進。對這個話題是可以争論上好幾個小時的,縮進甚至關系到軟體工程師的價值觀。在确定程式設計風格之初應當首先确定縮進格式,這非常重要,以免工程師後續會陷入那個老生常談的打開檔案時二話不說先重排代碼縮進的問題之中。來看一下這段代碼(為了示範,這裡故意修改了示例代碼的縮進)。
快速讀懂這段代碼并不容易。這裡的縮進并不統一,一眼看去else是對應到第1行的if語句。但實際上這個else和代碼第5行的if語句相對應。罪魁禍首是多位開發人員在同一段代碼裡應用了不同的縮進風格。這恰恰說明了統一縮進風格的重要性。如果有适當的縮進,這段代碼将變得更加易讀。
堅持使用适度的縮進是萬裡長征的第一步—本章在下面将提到這種做法可以帶來其他可維護性方面的提升。
對于大多數程式設計風格來說,代碼到底應該如何縮進并沒有統一的共識。有兩種主張。
使用制表符進行縮進
每一個縮進層級都用單獨的制表符(tab character)表示。是以一個縮進層級是一個制表符,兩個縮進層級為兩個制表符,以此類推。這種方法有兩個主要的好處。第一,制表符和縮進層級之間是一對一的關系,這是符合邏輯的。第二,文本編輯器可以配置制表符的展現長度1,是以那些想修改縮進尺寸的開發者可以通過配置文本編輯器來實作,想長即長,想短可短。使用制表符作縮進的主要缺點是,系統對制表符的解釋不一緻。你會發覺在某個系統中用一款編輯器打開檔案時看到的縮進,和在另外一個系統中用相同的編輯器打開檔案時看到的不一樣。對于那些追求(代碼展現)一緻性的開發者來說,這會帶來一些困惑。這些差異、争論會導緻不同的開發者對同一段代碼有不同的看法的,而這些正是團隊開發需要規避的。
使用空格符進行縮進
每個縮進層級由多個空格字元組成。在這種觀點中有三種具體的做法:2個空格表示一個縮進,2個空格表示一個縮進,以及8個空格表示一個縮進。這三種做法在其他很多程式設計語言中都能找到淵源。實際上,很多團隊選擇4個空格的縮進,對于那些習慣用2個空格縮進和用8個空格縮進的人來說,4個空格縮進是一種折中的選擇。使用空格作縮進的好處是,在所有的系統和編輯器中,檔案的展現格式不會有任何差異。可以在文本編輯器中配置敲擊tab鍵時插入幾個空格。也就是說所有開發者都可以看到一模一樣的代碼呈現。使用空格縮進的缺點是,對于單個開發者來說,使用一個沒有配置好的文本編輯器建立格式化的代碼的方式非常原始。
盡管有人争辯說應當優先考慮使用一種縮進約定,但說到底這隻是一個團隊偏好的問題。這裡我們給出一些各式各樣的縮進風格作為參考。
. jquery核心風格指南(jquery core style guide)明确規定使用制表符縮進。
. dauglas crockford的javascript代碼規範(douglas crockford’s code conventions for the javascript programming language)規定使用4個空格字元的縮進。
. sproutcore風格指南(sproutcore style guide)規定使用2個空格的縮進。
. goolge的javascript風格指南(google javascript style guide)規定使用2個空格的縮進。
. dojo程式設計風格指南(dojo style guide)規定使用制表符縮進。
我推薦使用4個空格字元為一個縮進層級。很多文本編輯器都預設将縮進設定為4個空格,你可以在編輯器中配置敲入tab鍵時插入4個空格。使用2個空格的縮進時,代碼的視覺展現并不是最優的,至少看起來是這樣。
盡管是選擇制表符還是選擇空格做縮進隻是一種個人偏好,但絕對不要将兩者混用,這非常重要。這麼做會導緻檔案的格式很糟糕,而且需要做不少清理工作,就像本節的第一段示例代碼顯示的那樣。