1. 程式人生 > >《整潔程式碼之道》讀書筆記

《整潔程式碼之道》讀書筆記

1. What?

正如Jack Reecves所發表的《原始碼就是設計》:原始碼就是最好軟體設計文件,而其他非程式碼性的文件只是原始碼的輔助。本文並非為了討論程式設計與軟體設計的關係,只想藉以說明原始碼的重要性。

簡單講,整潔程式碼行雲流水如同閱讀精美好文,程式碼能夠儘可能的自解釋;具體講,整潔程式碼具備如下特性:

  • 變數、函式、類、包、模組命名合理有意義
  • 程式碼結構(格式)清晰
  • 必要的合理的註釋資訊:程式碼能自解釋只是理想,該註釋的地方還是免不了
  • 合理的異常處理機制
  • 有效的日誌資訊
  • 遵循面向物件設計原則

2. How?

我們寫文章都是先構思再下筆,但一般不可能一氣呵成。都是先出初稿再調整、使用精美詞句慢慢打磨。寫程式碼同寫文章一樣,也是一個不斷調整修飾的過程(修改名稱、分解函式、消除重複等操作不斷重複)。只要你有一顆寫出整潔程式碼的初心。

2.1. 有意義的命名

  • 名副其實,必免誤導:在給變數、函式等取個合適名字其實是很花時間的事,對於已有的變數等,如果想到更合適的名字則請記得馬上換掉,必免誤導其他開發人員。
  • 遵守編碼規範中的命名相關部分。

2.2. 清晰的程式碼結構

  • 問題分解、模組職責劃分
  • 編碼前需要有最基本的設計思路,不管是何種設計粒度(系統、模組、類),其核心骨架、流程都必須成竹於胸。
  • 函式儘量精簡,精簡的函式不代表行數就一定是很少;只要保證一個函式只做一件事,這裡的“一件事“比較抽象,不同人有不同的解讀;我的區分原則為:有利於函式複用與閱讀。
  • 函式引數越少越好,這樣能省很多測試用例;引數儘量只用於輸入,通過返回值進行函式結果輸出,引數儘量不同時承載輸入與輸出資訊(多執行緒開發時除外)
  • 函式要麼做查詢操作,要麼做設定操作,不要同時都做。

2.3. 註釋

2.3.1. 合理的註釋

  • 註釋是為了彌補程式碼無力表達程式意圖時的一個有效補充。
  • 程式碼能自我表達固然是擼碼的最高境界,但現實總是殘酷的,當有段程式碼你發現需要寫註釋時,你需要先反省下是否程式碼寫得太差以致於無法自解釋。註釋並不能美化糟糕的程式碼。
  • 需要明白註釋是有維護成本的,如果不及時更新就容易引起混亂
  • 外部服務介面/API都需要提供必要的註釋資訊,有一定的維護成本,但一定不能省。
  • 潛在的坑也需要註釋以警告其他開發人員,最常見的是FIXME、為了解決出現執行緒不安全問題的程式碼邏輯(不寫清楚無經驗的同事可能會亂改而引入BUG,如SimpleDateFormat)

2.3.2. 不好的註釋

  • 個人覺得JavaBean的Getter/Setter方法是不需要註釋的
  • 對程式碼的修改不需要寫一些日誌式的註釋、不寫廢話式註釋
  • 能用函式名或變數名自解釋的,儘量不寫註釋
  • 不需要在控制語句的花括號結尾加代表語句結束的註釋,類似} // while
  • 也不需要寫一大段的註釋,如果出現這種情況,肯定是功能函式拆解不合理導致。

2.4. 格式

  • 遵行編碼規範中的格式部分
  • 合理使用空行
  • 聯絡緊密的程式碼儘量靠在一起
  • 一個團隊使用同一套格式規則

2.5. 物件與資料結構

  • 認真對待抽象,不是簡單的寫個介面,加幾個方法就算是抽象
  • 對像隱藏資料,暴露操作;資料結構暴露資料,不提供操作函式
  • DTO,DDD中的充血模型,類JavaBean的失血模型,個人專案中我更傾向於使用充血模型,所以書中所謂的混雜我是不太同意的。

2.6. 錯誤處理

  • 面向物件設計中,嚴格實行快速拋異常原則,而不是返回錯誤程式碼,而不應該吃掉異常。
  • 對於儘量不丟擲Checked型別的異常這一說法,個人持保留態度
  • 對於外部複雜的異常層次結構可做必要的封裝以減少重複程式碼
  • 儘量不使用null作為返回值、引數等,因為null可能引起歧義

2.7. 對第三方庫的處理方式

  • 建議對第三方介面進行包裝,便於後續適配多個提供方
  • 團隊協作中,如果依賴的其他子系統的介面未定義,但我們已明確我方的需求,我們可以先定義介面並提供一個Mock類,這樣可以保證我們的模組穩定性及可測試性
  • 如果依賴的第三方介面在本系統中使用得比較多,也建議統一再包裝一層以適應外部介面變化
  • 包裝的目的是遮蔽外部不確定性、增加魯棒性

2.8. 類與系統的設計

  • 遵循面向物件設計原則