使用 IDEA 幾分鐘就重構了同事800 行"又臭又長" 的類!真香!
這里是碼農充電第一站,回復“666”,獲取一份專屬大禮包 真愛,請設置“星標”或點個“在看”

最近在對已有項目進行擴展的時候,發(fā)現要改動的一個類它長 766 行,開放了近 40 個 public 接口,我流著淚把它給改完了。為了防止這樣的慘劇再次發(fā)生在我的身上,我覺得有必要寫一篇博客來讓廣大程序猿同胞知道代碼重構的重要性
“如果你身邊有一個類寫上千行的猿,一定要把此文轉給 ta
實際項目中,真的不建議類過長以及職責過多,非常不友好!!!
另外,Guide 在經歷了幾個項目之后,發(fā)現大部分情況下一個類一般是不會太長的,除非是這個類職責太多,再或者說自己沒有抽取相應的邏輯/工具類方法。
我覺得我們寫代碼不光是要把功能實現,還一定要對代碼的質量比如可讀性有較高要求。檢驗你的代碼可讀性與否很簡單,就是隨便拉一個稍微懂點業(yè)務的開發(fā)過來看你的代碼,看看別人能不能很快就看懂。
我當時自己寫簡單的 RPC 框架的時候,大部分時間實際都花在了方法的命名、類的拆分和包的拆分這三件事情上。
還有一點我印象比較深的是:好的代碼盡量是不需要注釋,通過名字就能看清意思。 但是,我在經歷了幾個項目之后發(fā)現,這點真的對開發(fā)有太高要求,很難保證,特別是在沒有 Code Review 的時候。
團隊成員之前達成一個共識很重要!!!
一下子扯了這么多題外話,都是有感而發(fā),我們開始正菜吧!
為什么類不能過長?

類過長——讀不通,擴展不通
讀不通——直接用滾輪滾都得好幾秒,就算是原作者,時間長了恐怕也難以理清整個類,更不用說是其他的讀者 擴展不通——一個類有過多的接口,會讓擴展這個類變得異常困難,一動千行
類過長——可能有冗余代碼
“此時 CV 工程師打了個冷戰(zhàn)
冗余代碼,就是重復代碼,通常出自使用 Ctrl+C,Ctrl+V 來生產代碼的 CV 工程師之手,冗余代碼的危害非常大:
冗余代碼使方法、類過長,不簡潔 冗余代碼會造成發(fā)散式修改(冗余代碼需要變動時,每一處 Ctrl+V 都需要修改)
類過長——多半是職責過多

一個類開放幾十個接口,絕對存在職責過多的問題,就像圖中的 Tom 貓一樣手忙腳亂,一個類的職責過多也有巨大問題:
違反設計原則——單一職責原則(單一職責原則要求一個類只實現一個職責,比如一只 Tom 只做掃地、擦桌、拖地中的一件事,而其他事的實現可以轉移給史派克狗或肥胖女傭),違反了這個原則會導致發(fā)散式變化、發(fā)散式修改、類過長等代碼問題,還會讓你的類難以擴展,甚至會讓其他程序猿認為你不專業(yè) 發(fā)散式變化(指引發(fā)此類修改的地方很多),如果一個類的職責很多,那它的扇入(調用者)一定很多,每個調用者的修改都有可能讓你這個類不得不隨之修改,也就是發(fā)散式變化 就是說不管哪兒出了問題,你這個類都得遭殃 發(fā)散式修改(指此類修改引發(fā)修改的地方很多),相同的,如果一個類職責很多,那支撐它實現的下級,即扇出(被調用方)一定很多,如果此類邏輯發(fā)生變動,所有下級被調用者可能都得隨之修改,也就是發(fā)散式修改 就是說你這個類出了問題,不管哪兒都會遭殃 難以擴展:如果你的一個類接口非常多,那它的子類怎么辦?它的包裝類怎么辦?難道全部都要實現這么多接口,全部都要承擔同樣多的職責嗎?擴展起來真的非常麻煩 觸發(fā)機關:【測試之怒】【運維之怒】
我已經寫了幾千行了,怎么辦?

重構——抽取冗余代碼
抽取冗余代碼就是將重復代碼抽取成一個獨立的方法,之后再使用這段代碼時就不再需要 Ctrl + C,Ctrl + V,而是直接調用對應的方法即可
這樣做也可以縮短原方法,使原方法更加簡潔易懂
更值得一提的是如果這段代碼需要修改,也只需修改一處,而不是發(fā)散式地到處修改
真是一箭三雕
使用 IDEA 進行冗余代碼的抽取
1.找到重復代碼

2.進行方法抽取 右鍵->選擇重構->抽取->方法 (或者直接使用快捷鍵 Ctrl + Alt + m)


自動檢測出個別重復代碼的細微差別,有些代碼可能只改動一兩個變量,IDEA 會自動檢測出來,并在抽取方法時提醒我們,選擇左側 Accept Signature Change(接受簽名變動)可以使抽取的方法自動替換更多的重復點

可以選擇替換掉所有的重復代碼(竟然有 18 處)

3.重構——更改方法簽名
如果你對抽取出的方法的名字、參數、返回值或是修飾符不滿意,不要使用 Ctrl + R 修改,IDEA 提供了重構方法——更改簽名(快捷鍵 Ctrl + F6)
注意:方法的名字指的是方法做了什么,而非怎么去做,最好是 動詞+名詞 格式
比如:
Tom.掃地() √ Tom.掃地 With 掃把() × Tom.用掃把掃地() ×
重構——轉移成員變量+函數(轉移職責)
將不應該由自己管理的成員變量和函數轉移出去
那就要考慮兩個問題:該轉移誰?轉移給誰?
來看一個圖

圖中成員【偏 A】被類【A】調用兩次,而只被它所在的類【過長類】調用 1 次,因而應該轉移給【A】去管理 由于函數【偏 A】與成員【偏 A】的親密度較高(只調用了【偏 A】),因而應與【偏 A】共進退,同去留,轉移給【A】 成員【偏 B】和函數【偏 B】也是相同道理 職責 1(函數【1】和成員【偏職責 1】)和職責 2(函數【2】和成員【偏職責 2】)由于找不到可轉移的合適的類,所以應抽取出一個新的類
“注意,先決定移動哪個成員變量,然后再決定移動哪個函數
使用 IDEA 轉移成員變量和函數
1.移動成員變量,鼠標選擇成員變量->右鍵->Refactor->Move,然后選擇轉移至哪個類

2.移動函數(與移動成員變量步驟相同)
重構——抽取類
當你發(fā)現要轉移的成員變量和函數找不到合適的類時(轉移職責卻找不到下家),要想起來,這里是程序世界,而我們程序猿就是類和對象的造物主,是時候創(chuàng)建一個新的類,讓它來替我們分擔職責(成員變量和函數)了
使用 IDEA 抽取類
1.選中要搬的成員變量和函數。 然后,右鍵->Refactor->Extract->Delegate(抽取一個委托者,委托他來管理這部分變量和函數,如果只有變量或只有函數,可以抽出參數對象 Paramater Object 或方法對象 Method Object)
“不推薦抽取參數對象,因為一般參數對象是給參數多的方法用的(用參數對象取代一長溜的參數),而且如果成員變量抽取了也不會影響任何函數的話,那就是無用對象了,不如直接把他們刪除掉

2.為新類起個名,選個包吧

3.注意,抽取的函數和成員一定要符合一個原則,那就是被抽取函數使用被抽取成員的次數一定高于剩余函數的次數,不然違反親密性原則(成員應歸于調用它最多的類,沒有理由你用的比我多還讓我來管理)
4.一些小問題 由于抽取的函數直接使用了未抽取的對象而導致重構失敗,涉及到另一個重構(使用 get 方法而非直接使用私有成員變量),使用此重構即可解決。

---END--- 重磅!碼農突圍-技術交流群已成立 掃碼可添加碼農突圍助手,可申請加入碼農突圍大群和細分方向群,細分方向已涵蓋:Java、Python、機器學習、大數據、人工智能等群。 一定要備注:開發(fā)方向+地點+學校/公司+昵稱(如Java開發(fā)+上海+拼夕夕+猴子),根據格式備注,可更快被通過且邀請進群 ▲長按加群 推薦閱讀
? 雷軍1994年寫的老代碼曝光,被稱像詩一樣優(yōu)雅 ?? 同事:你居然還在用 try catch 處理異常?有點Low啊 ???面試官問:MySQL 的自增 ID 用完了,怎么辦? ???互聯網公司忽悠員工的黑話,套路太深了。。。 ?? 記住沒:永遠不要在 MySQL 中使用 UTF-8 ?? 計算機網絡基礎知識總結 最近面試BAT,整理一份面試資料《Java面試BAT通關手冊》,覆蓋了Java核心技術、JVM、Java并發(fā)、SSM、微服務、數據庫、數據結構等等。 獲取方式:點“在看”,關注公眾號并回復?BAT?領取,更多內容陸續(xù)奉上。 如有收獲,點個在看,誠摯感謝 明天見(??ω??)??

