<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何重構(gòu)千行“又臭又長(zhǎng)”的類(lèi)?IntelliJ IDEA 幾分鐘就搞定!

          共 2587字,需瀏覽 6分鐘

           ·

          2022-07-25 14:42

          點(diǎn)擊關(guān)注公眾號(hào),Java干貨及時(shí)送達(dá)

          作者 | 圍軍兒

          來(lái)源 |  juejin.cn/post/6844904038383747086

          最近在對(duì)已有項(xiàng)目進(jìn)行擴(kuò)展的時(shí)候,發(fā)現(xiàn)要改動(dòng)的一個(gè)類(lèi)長(zhǎng)766行,開(kāi)放了近40個(gè)public接口,我流著淚把它給改完了。為了防止這樣的慘劇再次發(fā)生在我的身上,我覺(jué)得有必要寫(xiě)一篇博客來(lái)讓廣大程序猿同胞知道代碼重構(gòu)的重要性

          如果你身邊有一個(gè)類(lèi)寫(xiě)上千行的猿,一定要把此文轉(zhuǎn)給ta

          為什么類(lèi)不能過(guò)長(zhǎng)?

          類(lèi)過(guò)長(zhǎng)——讀不通,擴(kuò)展不通

          • 讀不通——直接用滾輪滾都得好幾秒,就算是原作者,時(shí)間長(zhǎng)了恐怕也難以理清整個(gè)類(lèi),更不用說(shuō)是其他的讀者

          • 擴(kuò)展不通——一個(gè)類(lèi)有過(guò)多的接口,會(huì)讓擴(kuò)展這個(gè)類(lèi)變得異常困難,一動(dòng)千行

          類(lèi)過(guò)長(zhǎng)——可能有冗余代碼

          此時(shí)CV工程師打了個(gè)冷戰(zhàn)

          冗余代碼,就是重復(fù)代碼,通常出自使用Ctrl+C,Ctrl+V來(lái)生產(chǎn)代碼的CV工程師之手,冗余代碼的危害非常大:

          1. 冗余代碼使方法、類(lèi)過(guò)長(zhǎng),不簡(jiǎn)潔

          2. 冗余代碼會(huì)造成發(fā)散式修改(冗余代碼需要變動(dòng)時(shí),每一處Ctrl+V都需要修改)

          類(lèi)過(guò)長(zhǎng)——多半是職責(zé)過(guò)多


          一個(gè)類(lèi)開(kāi)放幾十個(gè)接口,絕對(duì)存在職責(zé)過(guò)多的問(wèn)題,就像圖中的Tom貓一樣手忙腳亂,一個(gè)類(lèi)的職責(zé)過(guò)多也有巨大問(wèn)題:

          1. 違反設(shè)計(jì)原則——單一職責(zé)原則(單一職責(zé)原則要求一個(gè)類(lèi)只實(shí)現(xiàn)一個(gè)職責(zé),比如一只Tom只做掃地、擦桌、拖地中的一件事,而其他事的實(shí)現(xiàn)可以轉(zhuǎn)移給史派克狗或肥胖女傭),違反了這個(gè)原則會(huì)導(dǎo)致發(fā)散式變化、發(fā)散式修改、類(lèi)過(guò)長(zhǎng)等代碼問(wèn)題,還會(huì)讓你的類(lèi)難以擴(kuò)展,甚至?xí)屍渌绦蛟痴J(rèn)為你不專(zhuān)業(yè)

          2. 發(fā)散式變化(指引發(fā)此類(lèi)修改的地方很多),如果一個(gè)類(lèi)的職責(zé)很多,那它的扇入(調(diào)用者)一定很多,每個(gè)調(diào)用者的修改都有可能讓你這個(gè)類(lèi)不得不隨之修改,也就是發(fā)散式變化

            就是說(shuō)不管哪兒出了問(wèn)題,你這個(gè)類(lèi)都得遭殃

          3. 發(fā)散式修改(指此類(lèi)修改引發(fā)修改的地方很多),相同的,如果一個(gè)類(lèi)職責(zé)很多,那支撐它實(shí)現(xiàn)的下級(jí),即扇出(被調(diào)用方)一定很多,如果此類(lèi)邏輯發(fā)生變動(dòng),所有下級(jí)被調(diào)用者可能都得隨之修改,也就是發(fā)散式修改

            就是說(shuō)你這個(gè)類(lèi)出了問(wèn)題,不管哪兒都會(huì)遭殃

          4. 難以擴(kuò)展:如果你的一個(gè)類(lèi)接口非常多,那它的子類(lèi)怎么辦?它的包裝類(lèi)怎么辦?難道全部都要實(shí)現(xiàn)這么多接口,全部都要承擔(dān)同樣多的職責(zé)嗎?擴(kuò)展起來(lái)真的非常麻煩

          5. 觸發(fā)機(jī)關(guān):【測(cè)試之怒】【運(yùn)維之怒】

          我已經(jīng)寫(xiě)了幾千行了,怎么辦?

          重構(gòu)——抽取冗余代碼

          抽取冗余代碼就是將重復(fù)代碼抽取成一個(gè)獨(dú)立的方法,之后再使用這段代碼時(shí)就不再需要Ctrl + C,Ctrl + V,而是直接調(diào)用對(duì)應(yīng)的方法即可

          這樣做也可以縮短原方法,使原方法更加簡(jiǎn)潔易懂

          更值得一提的是如果這段代碼需要修改,也只需修改一處,而不是發(fā)散式地到處修改

          真是一箭三雕。

          使用IDEA進(jìn)行冗余代碼的抽取

          1.找到重復(fù)代碼

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

          自動(dòng)檢測(cè)出個(gè)別重復(fù)代碼的細(xì)微差別,有些代碼可能只改動(dòng)一兩個(gè)變量,IDEA會(huì)自動(dòng)檢測(cè)出來(lái),并在抽取方法時(shí)提醒我們,選擇左側(cè)Accept Signature Change(接受簽名變動(dòng))可以使抽取的方法自動(dòng)替換更多的重復(fù)點(diǎn)

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

          3.重構(gòu)——更改方法簽名

          如果你對(duì)抽取出的方法的名字、參數(shù)、返回值或是修飾符不滿(mǎn)意,不要使用Ctrl + R 修改,IDEA提供了重構(gòu)方法——更改簽名(快捷鍵Ctrl + F6)

          注意:方法的名字指的是方法做了什么,而非怎么去做,最好是動(dòng)詞+名詞格式

          比如:Tom.掃地() √

          Tom.掃地With掃把() ×

          Tom.用掃把掃地() ×

          重構(gòu)——轉(zhuǎn)移成員變量+函數(shù)(轉(zhuǎn)移職責(zé))

          將不應(yīng)該由自己管理的成員變量和函數(shù)轉(zhuǎn)移出去

          那就要考慮兩個(gè)問(wèn)題:該轉(zhuǎn)移誰(shuí)?轉(zhuǎn)移給誰(shuí)?

          來(lái)看一個(gè)圖

          1. 圖中成員【偏A】被類(lèi)【A】調(diào)用兩次,而只被它所在的類(lèi)【過(guò)長(zhǎng)類(lèi)】調(diào)用1次,因而應(yīng)該轉(zhuǎn)移給【A】去管理

          2. 由于函數(shù)【偏A】與成員【偏A】的親密度較高(只調(diào)用了【偏A】),因而應(yīng)與【偏A】共進(jìn)退,同去留,轉(zhuǎn)移給【A】

          3. 成員【偏B】和函數(shù)【偏B】也是相同道理

          4. 職責(zé)1(函數(shù)【1】和成員【偏職責(zé)1】)和職責(zé)2(函數(shù)【2】和成員【偏職責(zé)2】)由于找不到可轉(zhuǎn)移的合適的類(lèi),所以應(yīng)抽取出一個(gè)新的類(lèi)

          注意,先決定移動(dòng)哪個(gè)成員變量,然后再?zèng)Q定移動(dòng)哪個(gè)函數(shù)

          使用IDEA轉(zhuǎn)移成員變量和函數(shù)

          1.移動(dòng)成員變量,鼠標(biāo)選擇成員變量->右鍵->Refactor->Move,然后選擇轉(zhuǎn)移至哪個(gè)類(lèi)

          2.移動(dòng)函數(shù)(與移動(dòng)成員變量步驟相同)

          重構(gòu)——抽取類(lèi)

          當(dāng)你發(fā)現(xiàn)要轉(zhuǎn)移的成員變量和函數(shù)找不到合適的類(lèi)時(shí)(轉(zhuǎn)移職責(zé)卻找不到下家),要想起來(lái),這里是程序世界,而我們程序猿就是類(lèi)和對(duì)象的造物主,是時(shí)候創(chuàng)建一個(gè)新的類(lèi),讓它來(lái)替我們分擔(dān)職責(zé)(成員變量和函數(shù))了

          使用IDEA抽取類(lèi)

          1.重構(gòu)

          選中要搬的成員變量和函數(shù),右鍵->Refactor->Extract->Delegate(抽取一個(gè)委托者,委托他來(lái)管理這部分變量和函數(shù),如果只有變量或只有函數(shù),可以抽出參數(shù)對(duì)象Paramater Object或方法對(duì)象Method Object)

          不推薦抽取參數(shù)對(duì)象,因?yàn)橐话銋?shù)對(duì)象是給參數(shù)多的方法用的(用參數(shù)對(duì)象取代一長(zhǎng)溜的參數(shù)),而且如果成員變量抽取了也不會(huì)影響任何函數(shù)的話(huà),那就是無(wú)用對(duì)象了,不如直接把他們刪除掉

          2.為新類(lèi)起個(gè)名,選個(gè)包吧

          3.注意

          抽取的函數(shù)和成員一定要符合一個(gè)原則,那就是被抽取函數(shù)使用被抽取成員的次數(shù)一定高于剩余函數(shù)的次數(shù),不然違反親密性原則(成員應(yīng)歸于調(diào)用它最多的類(lèi),沒(méi)有理由你用的比我多還讓我來(lái)管理)

          4.一些小問(wèn)題

          由于抽取的函數(shù)直接使用了未抽取的對(duì)象而導(dǎo)致重構(gòu)失敗,涉及到另一個(gè)重構(gòu)(使用get方法而非直接使用私有成員變量),使用此重構(gòu)即可解決



          1、相比高人氣的Rust、Go,為何 Java、C 在工具層面進(jìn)展緩慢?

          2、讓程序員早點(diǎn)下班的《技術(shù)寫(xiě)作指南》

          3、互聯(lián)網(wǎng)人為什么學(xué)不會(huì)擺爛

          4、為什么國(guó)外JetBrains做 IDE 就可以養(yǎng)活自己,國(guó)內(nèi)不行?區(qū)別在哪?

          5、微軟欲閉源VS Code的C#擴(kuò)展惹眾怒

          6、上能寫(xiě)代碼,下要“揍”黑客,還有什么不是程序員的“鍋”?

          點(diǎn)分享

          點(diǎn)收藏

          點(diǎn)點(diǎn)贊

          點(diǎn)在看

          瀏覽 12
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  www.xxxx.日本 | 欧美乱妇高清无乱码免费-久久99国产高清 | 99热在线只有精品 | 人人摸在线观看 | 成人AV天堂 |