整潔代碼之道 17 味道和啓發

對整本書中提到的優化手段做了一系列總結

17.1 註釋

17.1.1 不恰當的信息

  1. 註釋只應該描述對應代碼和設計的技術信息,不要說廢話

17.1.2 廢棄的註釋

  1. 廢棄的註釋會遠離它們曾經描述的代碼,更有可能這些代碼早已經不存在了

17.1.3 冗餘註釋

  1. 註釋應該描述代碼本身無法描述清楚的信息,不要重複的描述

17.1.4 糟糕的註釋

  1. 如果要編寫一條註釋,就應該花時間保證寫出最好的註釋

17.1.5 註釋掉的代碼

  1. 如果你現在認爲這段代碼沒用了,請直接刪掉
  2. 版本管理工具會幫你記住這段代碼,所以完全沒必要讓它留下,這隻會帶來混淆

17.2 環境

17.2.1 需要多步才能實現的構建

  1. 構建系統應該是單步的小操作
  2. 應該能夠用單個命令導出系統,並用單個指令進行構建

17.2.2 需要多步才能做到的測試

  1. 應該能夠用單個操作就可以運行全部的單元測試

17.3 函數

17.3.1 過多的參數

  1. 函數的參數數量應該儘可能少
  2. 三個以上的參數應該儘可能避免
    • 這個我目前還很難做到

17.3.2 輸出參數

  1. 輸出參數是一種違法直覺的行爲
  2. 參數應該只用來輸入,而不是輸出
  3. 如果函數一定要改變輸入參數的值,用來給後續步驟使用,那麼應該改爲用返回值

17.3.3 標識參數

  1. 一個函數應該只做一件事,而布爾值參數的傳入就表明這個函數做了不止一件事

17.3.4 死函數

  1. 永遠不被調用的方法就應該被丟棄

17.4 一般性問題

17.4.1 一個源文件中存在多種語言

  1. 理想的源文件應該只包括一種語言

17.4.2 明顯的行爲未被實現

  1. 如果明顯應該實現的行爲沒有被實現,那麼函數的名稱就相當於沒有真實表達代碼的含義

17.4.3 不正確的邊界行爲

  1. 不要依賴直覺,追蹤每種邊界條件,並編寫對應的測試

17.4.4 忽視安全

  1. 很多程序員習慣性的忽視 IDE 給出的 WARNING 警告,這非常危險,應該盡其所能消滅所有文件中的警告信息

17.4.5 重複

  1. 依據 DRY 原則( Don’t Repeat Yourself )

17.4.6 在錯誤的抽象層級上的代碼

  1. 將較低層級的概念放在派生類中,將較高層級的概念放在基類中
  2. 良好的軟件設計要求分離位於不同層級的概念,並將它們放在不同的容器中

17.4.7 基類依賴於派生類

  1. 基類需要依賴派生類,這顯然是本末倒置的

17.4.8 信息過多

  1. 設計良好的接口提供的函數不會需要依賴其他函數

17.4.9 死代碼

  1. 在設計改變時,死代碼不會隨之更新,雖然它還是能通過編寫,但這段代碼對程序本身已經沒有用處,應該毫不猶豫的刪除

17.4.10 垂直分隔

  1. 變量和函數定義的位置應該離它們被使用的位置儘可能的近一些

17.4.11 前後不一致

  1. 遵循 最小驚異原則 ,做到從一而終

17.4.12 混淆視聽

  1. 沒有用到的變量,從不調用的函數,沒有信息量的註釋,都應該被刪除

17.4.13 人爲耦合

  1. 不互相依賴的東西不該產生耦合
  2. 兩個沒有直接邏輯關聯的模塊不應該存在耦合

17.4.14 特性依戀

  1. 類的方法只應該對自身類中的變量和函數感興趣

17.4.15 選擇算子參數

  1. 使用多個函數,比向單個函數中傳遞布爾參數來選擇函數行爲要更清晰

17.4.16 晦澀的意圖

  1. 代碼要儘可能具有表達力

17.4.17 位置錯誤的權責

  1. 軟件開發者做出的最重要決定之一:這段代碼應該放在哪

17.4.18 不恰當的靜態方法

  1. 通常應該傾向於選用非靜態方法
  2. 如果的確要使用靜態方法,請確保這個方法後期不會有多態的需求

17.4.19 使用解釋性變量

  1. 只要把計算過程打散成一系列良好命名的中間值,就算是不透明的模塊也會變得透明
  2. 但在這之前需要考慮爲什麼這段計算過程會不透明

17.4.20 函數名稱應該表達其行爲

  1. 如果必須查看函數的實現才知道其用途,說明應該換一個更好的函數名

17.4.21 理解算法

  1. 編程是一種探險,在開始使用某個工具實現功能之前,先儘可能瞭解這個工具能夠做到的事情
  2. 不要盲目的用自己當前掌握的知識直接解決問題,請先閱讀文檔
  3. 通常工具中的實現會比你自己想的要更好

17.4.22 把邏輯依賴改爲物理依賴

  1. 如果某個模塊依賴於另一個模塊,這種依賴應該是物理的,而不是邏輯的

17.4.23 用多態替代 if / else 或 switch / case

  1. 對於給定的選擇類型,不應該有多個 switch 語句
  2. 如果有多個,請使用多態

17.4.24 遵循標準約定

  1. 每個團隊都應該遵循基於通用行業規範的編碼標準

17.4.25 用命名常量代替魔術數

  1. 魔術數不僅僅是說數字,這是泛指任何不能自我描述的符號

17.4.26 準確

  1. 表達意思含糊或不準確的代碼,要麼優化,要麼刪除

17.4.27 結構甚於約定

  1. 使用強制的結構太替換脆弱的命名約定

17.4.28 封裝條件

  1. 應該把條件判斷語句中的複雜表達式,抽離成方法

17.4.29 避免否定性條件

  1. 否定式比肯定式難理解,儘可能將條件表示爲肯定形式

17.4.30 函數只該做一件事

  1. 遵循單一權責原則

17.4.31 掩蔽時序耦合

  1. 譯者又開始文縐縐的讓我受不了了,什麼掩蔽?直接說隱蔽不好嗎???
  2. 如果代碼存在調用順序上的耦合,就應該明確表示,放着出現因爲調用順序出錯而導致的報錯

17.4.32 別隨意

  1. 構建代碼需要理由,而理由應該和代碼結構相吻合

17.4.33 封裝邊界條件

  1. 邊界條件難以追蹤,所以應該把處理邊界條件的代碼集中到一起,不要散落在代碼中

17.4.34 函數應該只在一個抽象層級上

  1. 當根據抽象界限對函數進行拆解時,經常會發現隱蔽在之前的結構中的新抽象界限

17.4.35 在較高層級放置可配置數據

  1. 可配置的數據通常具有通用性,放置在較高層級則可以保證其通用性

17.4.36 避免傳遞瀏覽

  1. 模塊本身不要了解太多協作者的信息,而應該讓協作者提供給模塊所需要的全部服務

17.5 Java

17.5.1 通過使用通配符避免過長的導入清單

  1. 現代 IDE ,例如 IDEA ,已經可以做到自動優化導入清單

17.5.2 不要繼承常量

  1. 別利用繼承來使用常量,例如將常量放置在基類中
  2. 應該直接使用常量類實現靜態導入

17.5.3 常量 vs 枚舉

  1. 如果你感覺某個地方需要一個常量,請使用枚舉

17.6 名稱

17.6.1 採用描述性名稱

  1. 事物的意義隨着軟件的演化而發生變化,所以要經常對變量、方法的名稱進行重新評估

17.6.2 名稱應與抽象層級相符

  1. 類和方法的名稱應該能體現當前的抽象層級

17.6.3 儘可能使用標準命名法

  1. 使用名稱基於現存的約定,會更容易理解
  2. 與項目直接相關的名稱越多,後來接收代碼的人就可以更快的理解

17.6.4 無歧義的名稱

  1. 選用不會混淆方法或變量的名稱

17.6.5 爲較大作用範圍選用較長名稱

  1. 名稱的長度應該和其作用範圍成正比

17.6.6 避免編碼

  1. 不應該在名稱中包含類型或作用範圍信息,例如 m_score

17.6.7 名稱應該說明副作用

  1. 名稱應該說明函數、變量或類的一切信息

17.7 測試

17.7.1 測試不足

  1. 一套測試應該測到所有可能失敗的情況
  2. 只要還有沒被測試過的條件,或是還有沒被驗證過的計算,就說明測試不足

17.7.2 使用覆蓋率工具

  1. 覆蓋率工具可以直觀的彙報測試不足的模塊、類和方法

17.7.3 別略過小測試

  1. 小測試易於編寫,其文檔上的價值高於編寫成本

17.7.4 被忽略的測試就是對不確定事物的疑問

  1. 如果因爲需求不明確而不能確定某個行爲細節,可以用註釋掉的測試來表達疑問

17.7.5 測試邊界條件

  1. 特別注意測試邊界條件,算法的中間部分正確,但邊界判斷錯誤的情況很常見

17.7.6 全面測試相近的缺陷

  1. 缺陷趨向於扎堆,在某個方法中發現一個缺陷時,最好全面測試那個方法

17.7.7 測試失敗的模式有啓發性

  1. 通過找到測試用例失敗的模式來診斷問題所在

17.7.8 測試覆蓋率的模式有啓發性

  1. 查看沒有被測試過的代碼,通常可以發現其他測試代碼失敗的線索

17.7.9 測試應該快速

  1. 慢速的測試是不會被運行的測試

17.8

  1. 專業性和技藝來自於驅動規程的價值觀
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章