軟件重構

重構這個話題是老生常談的了,無論對於C、java亦或Python程序員來講,只要項目有一定的代碼量,重構就是無可避免的。正好這段時間我正在給一個android應用項目(下文統稱項目X)做重構,這個項目原本是由一個完全不會寫代碼的人寫的,可以說項目沒有任何可讀性,邏輯也沒有很清晰。本文我會結合自己的實踐和一些參考資料談談我對重構的一些理解。

什麼是重構?
重構是在保證不改變外部行爲的前提下,對內部結構進行改變,使之易於修改和理解。
——————Martin Fowler

換句話說,重構就是保證我們的程序對於外部使用者來說是一致的,但是內部的代碼做了優化。

爲什麼要重構?
這個問題其實很簡單,就是代碼寫的不好。當然了,代碼寫的不好也是不可避免的,再nb的程序員寫出來的再nb的項目也會有可優化的地方,Linus Torvalds寫的項目會不會一點問題都沒有?不會。有時候可能一個變量含義不清,一個函數的功能不明確,類定義有部分耦合,Linus Torvalds不是神,這些或大或小的問題總會出現的。

需要重構的情況和解決方法?
下面就簡單說說那些情況下我們就需要重構代碼了,你也可以對照着這些情況重新審查自己的代碼是不是有類似問題。

違反了基本的代碼規範
基本的代碼規範包括但是不限於如下:

命名採用駝峯式,命名是有意義的,而非類似temp、data之類,private和protected命名前加m,靜態變量加s,靜態常量全部大寫等等,這裏不過多寫了
魔鬼數字,將魔鬼數字定義爲靜態常量,並給他詳細的註釋,這個習慣一定要保持
可能有人說這些不屬於重構範圍,因爲代碼邏輯根本沒改,但是,一個壞的變量命名和一個好的變量命名給維護的程序員的感覺是完全不同的,好的命名根本不需要註釋就能知道這個變量是做什麼的。

重複的代碼
這個我覺得是一個最顯而易見的問題,一旦你發現有段代碼是複製粘貼到另一個類中的時候你就應該想想,怎麼樣能夠複用這段代碼,Don’t Repeat Yourself!

怎麼樣能複用同段代碼,最簡單的就是抽出來作爲一個公共靜態方法,但是很多時候這些方法不應該是靜態的,這時候可以建一個helper或者delegate之類的類,兩邊都用這個代理函數去處理同一個邏輯。當然,我這邊只是一個例子,並沒有包含大多數情況。

而如果兩個函數基本類似,僅僅是其中的一些變量不同,那就把這兩個函數合併,通過重載的方式,以函數參數來區分。

冗長的子程序
比如在java裏面,一旦你發現有個函數特別長,那肯定是不正常的(這裏說的有點絕對,不過基本上是這樣)。在google針對java的代碼規範裏有這麼兩條:

保證函數的功能單一性
一個函數的代碼不要超過X行(這邊的數字每個公司可能不一樣),我所在公司規定是不超過一個屏幕,大概30行左右。
依照這個規範來講,函數太長應該這兩點都不會符合。

解決方法就是分拆函數,把過長的函數分拆爲幾個函數,每個函數的功能保證單一性,併爲之取一個功能明確的函數名。如果幾個函數都是邏輯類似的,你也可以單獨拎出來作爲一個類處理。

我在給X項目做重構的時候就遇到一個上傳任務單這種函數,其實每個任務單表在後臺會包含若干表,由於X項目沒有接口層,所以客戶端都是直接與後臺數據庫接觸的,這樣,上傳任務單的一個功能就可以分拆爲幾個功能:上傳任務單的人員信息,上傳任務單的環境信息,上傳任務單的參數信息等等,分拆爲若干函數之後整合爲整個上傳任務單函數(這個函數裏僅僅包含分拆的幾個函數),這樣每個函數的行數保證了不超過一屏幕。事實上,這樣分拆的好處不僅如此,因爲其他的上傳功能也會交叉的有上述分拆函數,所以也解決了代碼複用問題。

循環過長,嵌套太深
我認爲沒有程序員會喜歡看超多的if else,動輒十幾個大括號的嵌套可能會讓你很有成就感,事實上,這樣的代碼不可讀且不好維護,此時的你成就感爆棚,一個月後呢?一年之後呢?我覺得,好的代碼應該是一年之後你再次看到自己寫的代碼的時候,雖然不知道是自己寫的,但也同樣容易修改維護。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章