通常,不同的公司里有著不同的編碼規範,主要是從代碼得準確性、穩定性、可讀性等地方著手制定,以提高團隊成員之間的協作效率,這裡主要是列出一些常見的編碼規範。 ...
命名規範
命名長度
命名的原則以準確達意為目標,其長度以遵循此原則為主,並且是越短越好。
- 對於公認、熟知的詞,可以在項目內部統一成縮寫
- 對於作用域較小的變數,可以使用較短的命名
- 對於作用域較大的變數,推薦使用可達意的較長的命名
命名上下文
命名時可以根據上下文來簡化命名,如在 User 類中,就不需要對類中的成員變數添加 user
首碼,而是直接命名如 name
、password
等名稱。
在使用時,開發者也可以藉助上下文明確變數的含義。
可讀性
可讀性指的是不使用特別生僻、難發音的英文單詞來命名,同時也不要使用一些無意義、隨意搭配的單詞。
可搜索性
命名可搜索性指的是,使用 IDE 開發的時候,可以很方便地使用“關鍵詞聯想”功能快速補全。
這個原則指的是,最好能在項目、團隊內部統一命名方式,如都使用 selectXXX
表示查詢,而不是既有 selectXXX
,也有 findXXX
或 queryXXX
等多種命名方式表示查詢。
介面、抽象類
對於介面的命名,通常有兩種比較常見的方式:一種是介面加首碼 I
表示 Interface,如 IUserService
;另一種是實現類加尾碼 Impl
表示 implements,如 UserServiceImpl
。
對於抽象類的命名,也有兩種常見的方式:一種是帶上首碼 Abstract
表示抽象類,如 AbstractConfig
;另一種是不帶首碼。
無論是介面還是抽象類,選擇哪個命名方式都可以,最重要的是能在項目內部統一。
註釋規範
註釋內容
註釋的目的是讓代碼更容易看懂。
註釋的內容主要是包括三個方面:做什麼、為什麼做、怎麼做。對於複雜的介面或類,還需要補充“如何用”。
註釋多少
註釋本身有一定的維護成本,並非越多越好。
類和函數一定要寫註釋,而且要寫得儘可能全面、詳細,函數內部的註釋要相對少一些,一般可以通過好的命名、提煉函數、解釋性變數、總結性註釋等方式來提高代碼可讀性。
代碼風格
類和函數的行數
對於函數代碼行數的最大限制,網上有一種說法:最好不要超過一個顯示屏的垂直高度。
對於類的代碼行數的最大限制,有一個間接的判斷標準:
- 當一個類的代碼讀起來比較困難
- 實現某個功能時不知道該用哪個函數
- 想用哪個函數的時候需要找很久
- 只用到一個小功能的時候要引入整個類
一行代碼的長度
總體遵循一個原則:一行代碼最長不能超過 IDE 顯示的寬度。
需要滾動滑鼠才能查看一行的全部代碼,顯然不利於代碼的閱讀;但是太小的限制也會導致很多稍長點的語句被折成兩行。
分隔單元塊
對於比較長的函數,如果邏輯上可以分為幾個獨立的代碼塊,但是又不方便將這些獨立的代碼塊抽取成小函數的時候,可以使用總結性註釋的方式分隔代碼塊。
除此之外,還可以通過使用空行分隔代碼塊。如類的成員變數和函數之間、靜態成員變數和普通成員變數之間、各函數之間、甚至是各成員變數之間。
類成員的排列順序
在 Google Java 編程規範中,依賴類按照字母序從小到大排列、類中先寫成員變數後寫函數、成員變數之間或函數之間先寫靜態成員變數或函數(按照作用域大小依次排列)。
常用技巧
善於提煉函數
對於邏輯比較複雜的代碼,通常是建議提煉出類或者函數,但也避免提煉出的函數只包含兩三行代碼,以增加閱讀成本。
避免函數參數過多
通常函數的參數超過 5 個時候就會影響到代碼的可讀性,使用起來也不方便。
出現函數參數較多的情況,通常有兩個解決辦法:根據單一職責原則拆分成多個函數;將函數的參數封裝成對象。
勿用函數參數控制邏輯
切勿在函數內部根據函數的參數來控制內部邏輯,如根據 isVip = true
時走 VIP 的邏輯、isVip = false
走非 VIP 的邏輯。
針對於這樣情況,通常是根據需求將其拆分成多個函數,拆分之後的函數職責更明確。
函數設計要職責單一
不只是針對類、模塊而言,對於函數的設計,更要滿足單一職責原則。
移除過深的嵌套
代碼嵌套最好不超過兩層,超過兩層之後就要思考一下是否可以減少嵌套,以避免難以理解和代碼縮進過多。
解決代碼嵌套過深的方法有以下幾種思路:
- 去掉多餘的
if
或者else
語句 - 使用編程語言提供的
continue
、break
、return
關鍵字提前退出嵌套 - 調整執行順序來減少嵌套
- 將部分嵌套的邏輯封裝成函數調用,以此來減少嵌套
- 使用多態來替代
if-else
、switch-case
條件判斷
使用解釋性變數
使用解釋性變數可以提高代碼的可讀性,常見的情況有以下幾種:
- 使用常量取代魔法數字
- 使用解釋性變數來解釋複雜表達式
函數錯誤返回
函數的運行結果可以分為兩類:正確情況下輸出的預期結果,異常(出錯)情況下輸出的非預期結果。
在異常情況下,函數返回的數據類型非常靈活,可以針對不同的場景和特點選擇不同的返回值。
返回錯誤碼
C 語言沒有異常這樣的語法機制,返回錯誤碼是最常見的出錯處理方式。
而 Java、Python 等比較新的編程語言,大部分情況下,都用異常來處理函數出錯的情況,極少會用到錯誤碼。
返回 NULL 值
在多數編程語言中,使用 NULL
值表示“不存在”這種語義。
對於查找函數來說,數據不存在並非一種異常情況,是一種正常行為,所以返回表示“不存在”語義的 NULL
值比返回異常更加合理。
返回空對象
返回 NULL
值有各種弊端,對此有一個比較經典的應對策略,那就是應用空對象設計模式。
當函數返回的數據類型是字元串類型或者集合類型的時候,可以用空字元串或空集合替代 NULL
值,來表示不存在的情況。
拋出異常對象
最常用的函數出錯處理方式是拋出異常。異常可以將正常邏輯和異常邏輯的處理分離開,這樣的代碼可讀性會更好。
對於拋出的異常對象,通常有以下幾種處理方式:
- 直接吞掉,如在捕捉之後只記錄日誌,不做任何處理
- 原封不動的重新拋出,如在調用的函數外部重新拋出相同的異常
- 包裝新的異常重新拋出,如在捕捉之後拋出另一個的異常