編寫可讀代碼的藝術
- 代碼應該易於理解
- 代碼的寫法應當使別人理解它所需的時間最小化
表面層次的改進
把信息封裝到名字裏
- 選擇專業的詞,避免使用“空洞”的詞
- 找更有表現力的詞,清晰和精確
- 避免像tmp和retval這樣泛泛的名字
- 循環迭代器
- 用具體的名字代替抽象的名字,一個變量名就像是一個小小的註釋
- 帶單位的值
- 附帶其他重要屬性
- 名字應該有多長
- 在小的作用域裏可以用短的名字
- 一個標識符有較大的作用域,那麼它的名字就要包含足夠的信息
- Alt+/在idea中補全單詞
- 首字母縮略詞和縮寫,可能很難理解
- 利用名字的格式來傳遞含義,有目的的使用大小寫和下劃線
不會誤解的名字
- 這個名字會造成其他含義嗎?
- 使用min和max來表示(包含)極限
- 使用first和last來表示包含的範圍
- 使用begin和end來表示包含/排除範圍
- 給布爾值命名
- 與使用者的期望相匹配
審美
-
使用一致的佈局,讓讀者很快就習慣這種風格
-
讓相似的代碼看上去相似
-
把相關的代碼進行分組,形成代碼塊
-
重新安排換行來保持一致和緊湊
-
用方法來整理不規則的東西
-
在需要時使用列對齊
-
選一個有意義的順序,始終一致地使用它
-
把聲明用塊組織起來
-
把代碼分成段落
-
一致的風格比“正確”的風格更重要
該寫什麼樣的註釋
-
不要爲那些從代碼本身就能快速推斷的事實寫註釋
-
記錄你的想法
-
爲代碼中的瑕疵寫註釋
- TODO:我還沒有處理的事情
- FIXME:已知的無法運行的代碼
- HACK:對一個問題不得不採用的比較粗糙的解決方案
- XXX:危險!這裏有重要的問題
-
給常量加註釋
-
站在讀者的角度
寫出言簡意賅的註釋
- 讓註釋保持緊湊
- 避免使用不明確的代詞
- 潤色粗糙的句子
- 精確地描述函數的行爲
- 用輸入輸出的例子來說明特別的情況
- 聲明代碼的意圖
- “具名函數參數”的註釋
- Connect(/** timeout_ms = / 10, /* use_encryption = */ false);
- 採用信息含量高的詞
簡化循環和邏輯
把控制流變得易讀
-
“自然”
-
條件語句中參數的順序
- 比較運算符的左側:變量;右側:常量。
-
if/else 語句塊的順序,不要讀起來很彆扭
-
?:(三目運算符)條件表達式:最簡單直接的情況下使用,否則可以用if/else來替換
-
避免do/while循環
-
從函數中提前返回
-
最小化嵌套,通過提早返回來減少嵌套,循環中與提早返回相同的是continue
拆分超長的表達式
-
代碼中的表達式越長,它就越難以理解
-
引入一個額外的變量
-
總結變量,將表達式的結果給一個變量,對變量進行判斷
-
使用德摩根定理
-
濫用短路邏輯
-
拆分巨大的語句
變量與可讀性
- 減少變量
- 沒有價值的臨時變量
- 減少中間結果
- 減少控制流變量
- 縮小變量的作用域
- 只寫一次的變量更好
重新組織代碼
抽取不相關的子問題
- 純工具代碼
- 創建大量通用代碼
- 項目專有的功能
- 簡化已有接口
- 按需重塑接口
- 過猶不及
一次只做一件事
- 任務可以很小
- 從對象中抽取值
把想法變成代碼
- 清楚地描述邏輯
- 瞭解函數庫是有幫助的
少寫代碼
- 別費神實現那個功能——你不會需要它
- 質疑和拆分你的需求
- 保持小代碼庫
- 熟悉你周邊的庫