重構筆記——代碼的壞味道(下)

本文是在學習中的總結,歡迎轉載但請註明出處:http://blog.csdn.net/pistolove/article/details/42083495


      在重構筆記——代碼的壞味道(上)中介紹了22種壞味道中的11種,本文將介紹其餘的11種壞味道。之所以將其分爲兩篇文章介紹,是因爲一篇文章介紹22種方法顯得篇幅太長,擔心讀者難以堅持看完。(PS:在對這些"代碼的壞味道“瞭解和熟悉後,我們就要開始有針對性地進行重構了,但是在進行重構之前,我們似乎還缺少點什麼!對了,我們還缺少測試環境!在開發的過程中,大多數程序員可能會忽視構築測試體系,但是殊不知編寫優良的測試程序,可以極大地提高程序員的編程速度,並確保程序相對“穩定“和”牢靠”。在下一篇文章中將會介紹:構築測試體系,提高編程速度)。

      其餘的11種壞味道如下所示。(如果你想堅持並學習重構,希望你能夠有耐心地看完本文)


(12)冗贅類

      你所創建的每一個類,都得有人去理解它、維護它,這些工作都是需要花錢的。如果一個類的所得並不值其身價,他就應該消失。項目中經常會出現這樣的情況:某個類原本對得起自己的價值,但重構使它身形縮水,不再做那麼多工作;或開發者事先規劃了某些變化,並添加一個類來應付這些變化,但變化實際沒有發生。

      不管是哪種原因,都應該讓這個類莊嚴赴義吧。如果某些子類並沒有做足夠的工作,我們可以嘗試“摺疊繼承體系”,將超類和子類合爲一體,那樣就會減少維護時間。對於那些幾乎沒用的組件,就應該將這個類的所有特性搬移到另一個類中,然後移除原類。


(13)誇誇其談未來性

      我們經常會說:“我想總有一天需要做這事”,並因而企圖以各樣的鉤子和特殊情況來處理一些非必要的事情。一旦這樣,壞味道就浮現出來了。誇誇其談未來的結果往往會造成系統更加難以理解和維護。如果所有的裝置都被用到了,那就值得那麼做;如果用不到,就不值得。用不上的裝置只會阻擋你的路,給你添亂,那就搬開它吧。

      如果某個抽象類其實沒有太大作用,可以將超類和子類合爲一體。將不必要的委託轉移到另一個類中,並消除原先的類。如果函數的某些參數未被用上,那麼就將參數移走。如果函數名稱帶有多餘的抽象意味,就應該對它重命名,讓它現實一些。


(14)令人迷惑的暫時字段

      有時候你會發現:類中的某個實例變量僅爲某種特定情況而設。這樣的代碼讓人難以理解,因爲你通常認爲對象在所有時候都需要它的所有變量。當變量在未被使用的情況下去猜測其當初設置的目的,會讓你發瘋的。

      可以使用提煉新類爲這個可憐的孤兒創造一個家,然後把所有和這個變量相關的代碼都放進這個新家。

      也許還可以使用“將Null值替換爲Null對象”在“變量不合法”的情況下創建一個Null對象,從而避免寫出條件式代碼。

      

(15)過度耦合的消息鏈

      如果你看到用戶向一個對象請求另一個對象,然後再向後者請求另一個對象,然後再請求另一個對象.....這就是消息鏈。這種方式意味着客戶代碼將與某些功能函數中的導航結構緊密耦合。一旦對象間的關係發生任何變化,客戶端就不得不做出相應修改。

      這時候我們可以隱藏“委託關係”,並在服務類上建立客戶所需要的所有函數。你可以在消息鏈的不同位置進行這種重構手法。理論上是可以重構消息鏈上的任何一個對象,但是這樣做往往會把一系列對象都變成“中間人”。通常更好的選擇是:先觀察消息鏈最終得到的對象是用來幹什麼的,再看看能否通過抽取方法把使用該對象的代碼提煉到一個獨立函數中,然後再將這個函數推入消息鏈。


(16)中間人

      我們都知道對象的基本特徵之一就是封裝——對外部世界隱藏其內部細節。封裝往往伴隨着委託。比如你對Boss說是否有時間參加一個會議,他把這個消息“委託”給他的記事本,然後才能回答你。但是,你沒有必要知道Boss到底使用傳統記事本或電子記事本亦或祕書來記錄自己的約會。

      人們可能會過度使用委託。你也許會看到某個類接口中有一半的函數都委託給其它類,這樣就是過度委託。這時候就應該移除中間人,直接和真正的負責人打交道。如果這樣“不幹實事”的函數只有少數幾個,可以將它們放進調用端。如果中間人還有其它行爲,可以把它變成實責對象的子類,這樣你既可以擴展原對象的行爲,又不必負擔那麼多的委託動作。


(17)狎暱關係

      有時候你會看到兩個類過於親密,花費太多時間去探究彼此的private成分。如果這發生在兩個“人”之間,我們無比做衛道士;但對於類,我們就希望它們嚴守清規。

      也許就像古代的戀人一樣,過分狎暱的類必須拆散。可以通過“移動方法”和“移動字段”幫它們劃清界限,從而減少狎暱行徑。如果兩個類實在是情投意合,可以把兩者共同點提煉到一個安全地點,讓它們坦蕩地使用這個新類。或者通過隱藏“委託關係”讓另一個類來爲它們傳遞相思情。


(18)異曲同工的類

      如果兩個函數做同一件事,卻有着不同的簽名,可以根據它們的用途重新命名。

      但這往往不夠,可以反覆將某些行爲移入類中,直到兩者的協議一致爲止。


(19)不完美的庫類

     複用常被視爲對象的終極目的。不過我們認爲複用的意義經常被高估——大多數對象只要夠用就好。但是無可否認,許多編程技術都建立在程序庫的基礎上。庫類構建者沒有未卜先知的能力,我們不能因此責怪它們。

      幸好我們有兩個專門應付這種情況的工具。如果你只想修改庫類的一兩個函數,可以使用“引入外加參數”來進行修改。如果想要添加一大堆額外行爲,就得運用“引入本地擴展(建立一個新類,使它包含這些額外函數。讓這個擴展品成爲源類的子類或包裝類)”來進行修改。


(20)純稚的數據類

      純稚的數據類是指:它們擁有一些字段,以及用於訪問(讀寫)這些字段的函數,除此之外一無長物。這樣的類只是一種不會說話的數據容器,它們幾乎一定被其它類過分細瑣地操控着。

      這些類早期可能擁有public字段,果真如此就應該在別人注意到它們之前將它們封裝起來。如果這些類內含容器類的字段,就應該檢查它們是不是得到了恰當的封裝;如果沒有,就把它們封裝起來。對於那些不該被其它類修改的字段,就應該去掉該字段的所有設值函數。


(21)被拒絕的遺贈

      子類應該繼承超類的函數和數據。但是如果它們不想或者不需要繼承,又該怎麼辦呢?它們得到了所有的禮物,但卻只從中挑選幾樣來玩!

      這可能意味着繼承體系設計錯誤。你需要爲這個子類新建一個兄弟類,再把所有用不到的函數下推給那個兄弟。這樣一來,超類就只持有所有子類共享的東西。你常常會聽到這樣的建議:所有超類都應該是抽象的。


(22)過多的註釋

      不要擔心,並不是說不應該寫註釋。從嗅覺上說,註釋不是一種壞味道,事實上它還是一種香味呢。常常還有這樣的情況:你看到一段代碼有着長長的註釋,然後發現,這些註釋之所以存在乃是因爲代碼很糟糕。這種情況出現次數多的實在令人吃驚。

      註釋可以帶我們找到本文先前提到的各種壞味道。找到壞味道後,我們首先應該以各種重構手法把壞味道去除。完成之後我們發現註釋已經變得多餘了,因爲代碼已經清楚說明了一切。

      如果你需要註釋來解釋一塊代碼做了什麼,試試將該代碼抽取爲一個單獨的函數;如果函數已經被提煉出來,但還是需要註釋來解釋其行爲,試着對其重新命名。當你感覺需要撰寫註釋時,請先嚐試重構,試着讓所有註釋都變得多餘。


      “代碼的壞味道”相關的兩篇文章主要是對常見的22種壞味道的瞭解和熟悉,以促使我們在開發過程中,能夠經常性地分析和思考程序,尋找已經散發出壞味道的地方並對其進行適當重構,使得代碼更加“漂亮”。在後續的文章中,會比較細緻地介紹由壞味道而引發的各種重構手法。每種手法會對應一篇文章,每一篇文章中會介紹壞味道的去除方法,並會列舉一些簡單的例子加以闡述,使得你能夠更加清晰地學習和理解。


      希望本文對你有所幫助。有問題可以討論、溝通。




重構筆記之前文章如下:

       重構筆記——入門篇

       重構筆記——代碼的壞味道(上



發佈了201 篇原創文章 · 獲贊 672 · 訪問量 67萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章