《整潔程式碼之道》讀書筆記
阿新 • • 發佈:2019-01-05
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. 類與系統的設計
- 遵循面向物件設計原則