1. 程式人生 > >影響程式碼可閱讀性的常見問題

影響程式碼可閱讀性的常見問題

含混不清的命名

命名問題是很嚴重的問題,我見過有些系統用大量拼音縮寫命名,有些縮寫長達5-6個字母以上,這種除非是長期維護系統的程式設計師,其他人看了都是一臉懵逼。

命名最好用英文加上駝峰命名法,比如getAccount,userName。對於英文單詞的選擇,由於我們是非英語國家,即使在英語國家裡面,同一個含義可能也對應多個單詞,最好團隊建立一個常用英文單詞庫,比如性別都叫:gender,而不是有的用sex,可以建立團隊內部Wiki解決。

清晰的命名,應該讓其他人一眼看去就知道這個東西大概是幹什麼的。我很不喜歡的一種命名是類成員都加上m開頭,如mUserName,這個毫無必要。介面前面也不必加上I,另外以下劃線開頭的習慣我更覺得是一種干擾。

過長的函式

一般過長的函式表明這個函式承擔了太多責任,可以用Extract Method將部分責任分給其他更小的函式。責任太多的函式將很難閱讀,閱讀者由於很多計算的干擾而看不清你的主線。一般函式控制在20行以內,10行以內更好。

過大的類

過大的類和過長的函式類似,不過是一個類可能承擔了太多責任。可以把部分責任擴充套件為新的類,用委託的方式實現。

濫用的繼承

我曾經碰到有個系統,有多達5-6層的繼承,最底層的實現,又一路用super呼叫到最上層的類。當你檢視某一個功能的程式碼時,你不得不開啟N個視窗,在不同的類之間跳來跳去。

除了一些特殊情況,如Template模式,要謹慎使用繼承。如果可以使用聚合,就不必去使用繼承。如果僅僅是為了共享部分程式碼而用繼承,這個就完全沒有必要。

魔鬼金字塔

魔鬼金字塔是指多層的向右縮排,就像金字塔一樣。有說法人類的大腦只能暫存3層棧,如果多層巢狀,大腦將很難記住前面的巢狀到哪裡了。解決辦法是將部分程式碼Extract method組成新的方法,保持主方法比較乾淨。

Callback hell

這是另外一種反模式,我曾經看到過3-4層甚至以上的Callback巢狀,當時的程式設計師即使是很有經驗的,也差點崩潰了。Callback在某些情況下是提高了效率,不過不可濫用,一般來說我覺得一層就足夠了。

設計模式濫用

設計模式是好東西,在某些環境下,設計模式為了解決某些特定問題是非常好的。設計模式的基礎是面向抽象程式設計,只要你遵循面向抽象程式設計,就不必非要到處硬套設計模式。一個系統裡面有幾個地方使用設計模式挺好,如果到處都是設計模式,你就要崩潰了。

過多的配置

有些系統外面用了太多檔案對系統進行配置,以至於光看程式碼,你根本不知道他們怎麼組合在一起的(這也是我不太喜歡早期Spring用XML進行裝配的原因)。Java有了Annotation後,把程式碼和配置寫在一起,一定程度上解決了這個問題。

濫用註釋

註釋是好東西嗎?可能有些地方是。但最好的註釋我認為是對函式、變數、成員、類的良好命名,讓人僅僅看名字就能理解程式碼而不是靠註釋。如果程式碼中有過多註釋,還影響程式碼的閱讀。我看到有些開源庫,註釋多到你找不到程式碼在哪裡!

註釋還有個最大的問題是和程式碼的同步性,有些程式碼改了,註釋卻未必同步了。這樣註釋程式設計沒用的甚至是錯誤的,這帶來更大問題。

函式過多引數

函式引數如果過多(超過3個),在呼叫的地方就很難弄清楚順序,為了弄清楚就不得不跑到宣告的地方看一看,這時候可以用個類把這些引數聚合起來。

現在有些IDE如intelij idea的最新版本,可以在呼叫的地方標出引數名稱,這個很有幫助,不過還是儘量不要太多為好。

反覆修改的臨時變數

在函式中宣告一個臨時變數,最好宣告為final的(除了一些迴圈因子如i),在第一次賦值即不允許改變。一個允許變來變去的臨時變數,將給閱讀帶來很多困擾。

在函式中修改入參

呼叫一個函式,如果會對入參帶來副作用,比如對傳入的一個List進行操作,對呼叫方將比較困擾。如果你確實需要,寧可返回一個新的List。幸好Java中只允許值傳遞,你對入參賦值不影響呼叫方,否則更麻煩。

一個函式多個責任

我曾經遇到一個Bug,一個人有多個名字:暱稱、別人給你的別名、通訊錄中的名字,不同的地方顯示的名字不同。然後開發人員把這些setter方法,裡面又加了程式碼對物件進行操作,導致最後完全搞不清誰會修改程式碼。解決辦法是把setter都恢復乾淨,然後另外寫了一個讀取showName的方法。