歡迎光臨
每天分享高質量文章

代碼重構的場景總結

作者:翻滾吧李博

鏈接:https://www.jianshu.com/p/7e8bd46d37ba

核心思想:拆細 公用

重構可以是修改變數名、重新安排目錄這樣簡單的物理重構,也可以是抽取子函式、精簡冗餘設計這樣稍許複雜的邏輯重構。但均不改變現有代碼的功能。

瞭解敵人——醜陋的代碼

  • 臃腫的類
    開發者缺乏對最基本的編碼原則,即“單一職責原則”(SRP)的理解。開發者不去思考這些功能是不是應該放在這同一個類中,導致這些類會變得很臃腫,造成一個類幾千行,讓下一個接盤俠欲哭無淚。
  • 臃腫的方法
    好幾十上百行的一個函式堆在一塊,用面向過程的思想來寫代碼。
  • 函式引數過多
    函式引數過多會導致呼叫者對方法難以理解,引數弄混。想象一下一個函式連續傳5個int值引數,能分清誰是誰嗎?建議可以將引數組成一個物件傳入。
  • 層層嵌套的判斷
    如果邏輯不複雜儘量減少if-else的分支包裹,他人太難閱讀。比如不滿足條件了直接return,不走其他代碼,這樣可以減少一層嵌套。
  • 滿篇跑的常量值
    一個類裡面出現各種未命名的常量值。0,1,200等等鋪天蓋地。這種狀態碼意義改了,改代碼會把你改哭的。難道就不能先宣告一個統一的常量變數來使用嗎。
  • 模棱兩可的命名
    不能根據名字一眼看懂它的功能的命名不是一個好命名。當然生僻的單詞除外。模糊的,沒有功能意義的命名會給閱讀造成很大困難。

重構之道

  • 分拆大函式: Break Method
    當函式比較大了,就可以根據功能節點分拆成多個小函式,也許其中的小函式還可以公用。比如結算購物車,包括計算各類商品的總價,再計算折扣,再計算滿減優惠,如果一個方法執行完,那麼別人要只要邏輯就要從頭到尾讀一遍。而分別拆分成三個,一眼就能看出這段邏輯先後做了什麼。寫方法切忌一口吃一個胖子。
  • 封裝到父類:
    如果多各類要執行相似的功能和代碼,可以把該方法放到它們的父類中,或者提取出來成業務工具類。
  • Move Method—-方法遷移
    遵守“單一職責”原則,當類中的方法不適合放在當前類中時,就應該為該方法尋找合適下家。移到與方法耦合大的類中。當一個方法被其他類使用比在它所在類中的使用還要頻繁時,我們就需要使用遷移方法重構了——將方法遷移到更頻繁地使用它的類中。
  • Move Field—-搬移欄位
    當在一個類中的某一個欄位,被另一個類的物件頻繁使用時,我們就應該考慮將這個欄位的位置進行更改了
  • Extract Class—-提煉類
    一個類如果過於複雜,做了好多的事情,違背了“單一職責”的原則,所以需要將其可以獨立的模塊進行拆分,當然有可能由一個類拆分出多個類。
    對類的細化也是為了減少代碼的重覆性,以及提高代碼的復用性,便於代碼的維護。
  • 提升方法、欄位(Pull Up Method)
    將方法向繼承鏈上層遷移的過程。用於一個方法被多個實現者使用時。在繼承的體系中,當多個類使用了相同或類似的方法,就可以考慮將該方法抽取到基類,沒有基類就創建一個。欄位提升同方法。
  • 降低方法
    即父類抽象方法讓多個子類實現。多個子類有相同的功能但是有各個具體的實現方法,那麼這種封裝就可以用多型性了,父類創建一個抽象方法,將方法實現降低到子類。
  • 重覆代碼的提煉
    有時候為了趕專案進度,儘快完成功能,會偷懶將實現功能的一片代碼複製一遍,直接套用。這種把多餘的刪掉,保留一個,也許只需傳一兩個引數就可以封成一個方法供多處呼叫。
  • 重命名變數(類、方法、變數)
    這個很重要,可以不誇張地說,命名的水平就體現了編程能力的高低。在重構的過程中,當發現類名,方法名在當前版本不符合它的功能含義,就該考慮對其重新命名。
  • 補加註釋
    對於全域性變數,公用函式,邏輯複雜的地方添加註釋,彌補之前的遺漏。
  • 將較長的判斷或代碼運算用臨時變臉暫存

 

if(stateCode = OK && datas != null && canShow)
function(Math.random((num1-num2)*num3))

 

如上這種長長的判斷條件和引數會使 這種代碼應該先將if判斷條件寫成一個變數,放入變數判斷,將function引數寫一個區域性變數儲存結果,再傳入方法。

 

  • 使用泛型封裝成統一的方法或類
  • 函式要避免過多的引數造成閱讀的複雜性

 

public void requestPhoneThirdRegister(String loginway, String nickname, String openId, String token, String expires, String phone, final CallBackimpl callBackimpl)

 

用這樣的方法直接傳引數就太長了,嚴重降低代碼可讀性。我們可以將引數變數寫到一個物體類中,通過構造方法初始化物件屬性值,只需要傳遞一個物件就搞定,也解決了增減引數帶來的變動問題。

 

  • 嵌套條件分支優化
     if(){
            if(){
                if(){

                }
            }
        }else{

        }

相信大家也見識過不少這樣的箭頭代碼,像怎麼也解不開的死結。遇到這種代碼,一定要盡可能要優化。通常做法:判斷陳述句,if條件成立,執行代碼塊,誒,這樣就生成了一個嵌套層級。

優化的核心思想:直接判斷不滿足的條件,if條件成立,直接return,儘快跳出方法來減少嵌套的層級。

第二種:將條件判讀合併

  • 儘量避免雙重否定的條件
    private boolean isChecked(){
        if(){
            return true;
        }
    }

一個條件方法。

if(!isChecked()){

}

 

然後用否定來判斷這個條件,這樣可能會一時之間轉變不過來導致條件判斷反了。當然頭腦靈活的忽略這條。

 

  • 去除東北亂燉的Util類
    當我們在寫代碼中偶然間需要抽出公用方法時,一時之間找不到合適的類去放置,然後就隨意地放進了XXUtil或XXManager類中。長此以往,該類所含功能越來越雜,dp和px轉化在其中,屏幕尺寸相關方法在其中,日期轉化在其中,加密的索性也放在其中,那有無網絡,網絡型別判斷也加入吧。這不就像垃圾場了嗎,各類雜物都堆在其中,不符合單一職責原則,應該按照如上的功能塊分解成多個職責單一的類。類多不要緊,關鍵要做到職責單一。
  • 將滿篇跑的魔鬼數字和字串用定義的常量表示。
    如果只是某個類或者某個模塊需要用到該常量,就宣告到對應類中。如果是全域性專案都會用到的常量,就提升到專案的常量配置檔案中。


●編號381,輸入編號直達本文

●輸入m獲取到文章目錄

推薦↓↓↓

 

Java編程

更多推薦25個技術類公眾微信

涵蓋:程式人生、演算法與資料結構、黑客技術與網絡安全、大資料技術、前端開發、Java、Python、Web開發、安卓開發、iOS開發、C/C++、.NET、Linux、資料庫、運維等。

    赞(0)

    分享創造快樂