refactor

重構和單元測試是程序員的兩大法寶,他們的作用就像空氣和水對於人一樣,平凡,不起眼,但是意義深重。預善事,必先利器,本文就介紹怎樣在Eclipse中進行重構。

本文介紹了Eclipse支持的重構種類,它們的含義,以及怎樣重構。本文同時也可以作爲學習重構知識的快速手冊。

什麼是重構
重構是指在保持程序的全部功能的基礎上改變程序結構的過程。重構的類型有很多,如更改類名,改變方法名,或者提取代碼到方法中。每一次重構,都要執行一系列的步驟,這些步驟要保證代碼和原代碼相一致。

爲什麼重構很重要
手工重構時,很容易在代碼中引入錯誤,例如拼寫錯誤或者漏掉了重構的某一步。爲了防止引入錯誤,在每次重構前後,都要執行充分的測試。你可能會好奇重構是否是值得的。
重構的理由很多。你可能想要更新一段代碼很爛的程序。或者最初的設計隊伍都不在了,現在隊伍中每人瞭解這些程序。爲了更新,你必須要重新設計構建程序來滿足你的需求。另一個原因是原來的設計無法使你將新的特性添加進去。爲了添加進去,你要重構這些代碼。第三個原因是一個自動重構的工具可以爲你自動生成代碼,例如Eclipse中的重構功能。使用重構,你可以在重寫儘量少的代碼和仍保持軟件功能的同時,使代碼的邏輯性更好。


測試
在重構時,測試是十分重要的。應爲重構改變了代碼的結構,你要保證重構後代碼的功能沒有被改變。手工重構時,一個好的測試套是必須的。使用自動重構工具是,測試也是必要的,但不需要很頻繁,應爲自動重構工具不會產生手工重構時的那些錯誤,如拼寫錯誤。
在Eclipse中可以使用JUnit方便的爲程序創建測試代碼,具體方法不在本文描述。


Eclipse中的重構
JDT,Eclipse中的Java插件,能夠對Java項目,類,或成員進行多種類型的自動重構。可以採取多種方法快速的爲Java項目中的某個元素進行重構。
爲某些元素進行重構的前提是你必須選中他們。你可以在多個視圖中選擇這些元素,像大綱視圖或包瀏覽視圖。可以按住Ctrl或Shift鍵,在視圖中選擇多個元素。另外一種選擇的方法是使該元素的編輯區高亮顯示,或者把鼠標定位到源程序文件。在選中希望重構的元素後,可以從重構菜單的下拉項選擇重構,也可以從右鍵單擊後彈出菜單中選擇重構子菜單。同時,Eclipse還提供了重構的快捷鍵操作。
某些重構可以應用在任意元素上,有些則只能用在特定類型的元素上,如類或方法。在本文的最後的表格中,列出了重構能夠應用的元素類型,以及重構的快捷鍵。
在Eclipse中,所有的重構都能夠在正式執行之前預覽一下。在重構對話框中點擊“預覽”按鈕,可以查看所有將要被改變的地方。唯一沒有預覽按鈕的的重構是Pull Up,在它的重構嚮導中,到最後,預覽面板總會出現。可以將其中的個別變化反選掉,這樣這些改變就不會生效。


撤銷和重做
在重構菜單中有撤銷和重做項。他們和編輯菜單中的撤銷重做不同。即使重構改變了很多文件,編輯菜單中的撤銷重做只會更改當前文件。重構菜單中的撤銷和重做則會對一次重構的所有文件進行撤銷和重做操作。但是在使用時,它們有一定的限制。
重構後,無論重構改變了文件與否,如果任一個文件被另外改變而且保存了,你就無法撤銷或重做這個重構。假如一個文件在重構中被修改了,然後又被編輯了,但是還沒有保存,這時就會有錯誤信息提示,如果你想要撤銷或重做該重構,必須撤銷未保存的文件。
只要注意到以上的限制條件,你就可以隨心所欲的對重構進行撤銷或重做。你甚至能夠編譯,運行你的程序測試一下,然後再撤銷該重構,只要你沒有改變並保存任何文件。

Eclipse中的重構類型
如果你看一下Eclipse的重構菜單,可以看到四部分。第一部分是撤銷和重做。其他的三部分包含Eclipse提供的三種類型的重構。

第一種類型的重構改變代碼的物理結構,像Rename和Move。第二種是在類層次上改變代碼結構,例如Pull Up和Push Down。第三種是改變類內部的代碼,像Extract Method和Encapsulate Field。這三部分的重構列表如下。

類型1 物理結構
l Rename
l Move
l Change Method signature
l Convert Anonymous Class to Nested
l Convert Member Type to New File

類型2 類層次結構
l Push Down
l Push Up
l Extract Interface
l Generalize Type (Eclipse 3)
l User Supertype Where Possible
類型3 類內部結構
l Inline
l Extract Method
l Extract Local Variable
l Extract Constant
l Introduce Parameter
l Introduce Factory
l Encapsulate Field



Rename:
Rename用來改變一個Java元素的名字。雖然你可以手工改變Java文件Java元素的名字,但是這樣不能自動更新所有引用它們的文件或Java元素。你必須在項目中搜索文件然後手工替換這些引用。很可能你就會漏掉一個或者改錯一個。Rename重構會智能的更新所有有此引用的地方。
有時候,Java元素的名字不是很明瞭,或者它的功能已經改變了。爲了保持代碼的可讀性,該元素的名字也要更新。使用Rename重構,能夠十分快捷的更新元素的名字和所有引用它的地方。
要爲一個Java元素改名,在包瀏覽視圖或大綱視圖選中該元素,從重構菜單中選擇Rename項,或者使用快捷鍵Alt+Shift+R。Rename對話框會出現。在這裏添入新的名字,選擇是否更新該元素的引用。點擊預覽按鈕,會打開預覽窗口,在這裏,你可以看到那些內容會被改變。點擊OK按鈕,重構結束。

Move
Move和Rename很相似。它用來把元素從一個位置移動到另一個位置。它主要用來將類從一個包移動到另一個包。選中要移動的元素,從重構菜單中選擇Move,或者使用快捷鍵,Alt+Shift+V,在彈出窗口中選擇要移動的目的地。你仍然可以用預覽功能檢查一下有什麼改變,也可以按OK按鈕直接讓其生效。


Change Method Signature
更改方法簽名能夠改變參數名,參數類型,參數順序,返回類型,以及方法的可見性。也可以添加,刪除參數。
要執行此重構,選擇要重構的方法,選中重構菜單的更改方法簽名項,會出現更改方法簽名對話框。

在此對話框中選擇方法的修飾詞,返回類型,參數。參數的添加,修改,移動,刪除可以通過右邊的按鈕控制。當添加新的參數時,會自動賦予默認值。凡是調用此方法的地方都會用此默認值作爲參數輸入。
改變方法簽名可能在方法中導致問題,如果有問題,當你點擊預覽或OK時,會被標記出來。


Move Members Type to New File
此重構將嵌套類轉爲一個單獨類。將會創建一個新的Java文件包含此嵌套類。選中要重構的類,在重構菜單上選擇Move Member Type to New File項,在彈出的對話框中添入要創建的實例的名字。



Push Down
此重構將算中的方法和成員從父類中移動到它的直接子類中,所有下推的方法都可選作爲一個抽象方法留在父類中。下推重構對於重新構建項目設計十分有用。
選擇若干方法或成員,從重構菜單中選擇下推項,彈出下推對話框。

在此對話框中,可以分別選擇方法或成員,所有選中元素都會移動到當前類的子類中。當點擊Add Required按鈕時,所有已選擇元素所必需的元素也會自動選上,此行爲並不能保證所有必須的元素都能自動選中,還是需要人工確認。當有方法被選中時,編輯按鈕就會可用,點擊編輯按鈕,彈出編輯對話框。在其中可以選擇爲選中方法在當前類中遺留抽象方法,還是在當前類中刪除這些方法。雙擊一天選中的方法,也可以打開編輯對話框。在方法的Action列點擊,會出現一個下拉列表,可以在其中選擇遺留抽象方法還是在當前類中刪除方法。按回車鍵確認編輯結果。


Pull Up
上移與下推類似,也是在類之間移動方法和成員。上移將方法或成員從一個類移動到它的一個父類中。選中若干個方法或成員,在重構菜單中選擇上移項,上移向導馬上會出現。
在選擇目標類多選框中,列出了當前類繼承的所有父類。你只能將方法或成員移動到它們其中的一個裏面。
如果在選中方法的Action列,被設置成在目標類中聲明抽象方法,那麼在目標類的非抽象子類中創建必須的方法選項變爲可選。當它選中時,目標類的所有子類,如果它們中沒有選中的方法,則會爲它們創建選中的方法。
和在下推中一樣,選擇多個方法,點擊編輯按鈕,或者雙擊一個方法,都會打開編輯成員對話框。其中有兩個選項,上移和在目標類中聲明抽象方法。上移只是簡單的複製方法到到父類中,並提供選擇是否在當前類中刪除該方法。在目標類中聲明抽象方法會在父類中創建一個選中方法的抽象方法,如果父類不是抽象類則置爲抽象類,最後選中方法留在當前類中。和在下推中一樣,也可以點擊Action列,可以在出現的下拉列表中選擇。
如果方法的Action列選爲上移,在下一步的嚮導中,將會要求你選擇是否在當前類中刪除這些方法,選中的方法會在當前類中被刪除。
在嚮導的任意一步都可以按完成按鈕,結束重構操作,此時按照默認規則進行重構。


Extract Interface
提煉接口可以從一個存在的類中創建一個接口。你可以選擇在接口中包含着個類的那些方法。選中一個類,從重構菜單選擇提煉接口項,就可以打開提煉接口對話框。
這此對話框中添入接口的名字,選擇希望包含的方法,在這個列表裏面只列出了公共方法。選中改變對類[當前類名]的應用爲對接口的引用選擇框,將把所有對當前類的引用更新爲對此接口的引用。


Generalize Type
泛化類型重構可以將一個聲明對象的類型改變爲它的超類,選擇變量,參數,對象成員,方法返回類型,然後選擇重構菜單的泛化類型項。在打開的泛化類型對話框,選擇希望的新類型,然後點擊完成按鈕,結束重構。


Use Supertype Where Possible
使用超類會將對一個特定類型的引用改變爲對它的超類的引用。選擇一個類,選中重構菜單的使用超類項,會打開使用超類對話框。選中希望的超類類型,點擊完成按鈕完成重構。重構後,instanceof 表達式也會做相應的替換。



Inline
內聯是用代碼或值來取代調用方法的地方,靜態final對象成員,或局部變量。比如說,如果你內聯一個方法調用,這個調用的地方就會被替換爲該方法體。要內聯一個方法,靜態final對象成員,局部變量,選中這些元素,在重構菜單中選擇內聯項,或者使用快捷鍵Alt + Ctrl + I。在隨後打開的內聯對話框,你可以選擇是否要內聯所有的調用,或者是選擇的調用。如果選擇所有調用,你還可以選擇是否刪除聲明本身。

Extract Method
如果方法中含有過多特定的操作,方法太長,或者其中的某段代碼被多次使用,這時,可以用提煉方法重構將這部分代碼提取到單獨的方法中。在Eclipse中應用此重構方便快捷。
選中要提煉的代碼段,從重構菜單中選擇提煉方法項,或者使用快捷鍵Alt + Shift + M。
在提煉方法對話框中,輸入新方法的名字,選擇修飾詞,選擇是否讓新方法拋出運行時異常。在底部提供了新方法的預覽。


Extract Local Variable
使用一個變量來代替一個表達式有很多好處。如果表達式在多處被使用,這樣能夠提高性能,而且也提高了代碼的可讀性。要把一個表達式提煉爲局部變量,選擇要提煉的表達式,從重構菜單中選擇提煉局部變量項,或者使用快捷鍵Alt + Shift + L。
在提煉局部變量對話框中輸入新變量的名字,選擇是否要替換所有的表達式,是否使此變量爲final。在對話框的底部提供變量的預覽。

Extract Constant
提煉常量與提煉局部變量很相似,唯一的區別是提煉常量重構可以選擇提煉出的常量的修飾詞,而且此常量將作爲類的成員變量。

Introduce Parameter
介紹參數重構在方法中創建新的參數,然後用此新參數取代局部變量或者成員變量的實例。要是用此重構,選中方法中一個成員變量或局部變量的引用,然後從重構菜單中選擇介紹參數項。


Introduce Factory
工廠是用來創建新對象,返回新創建對象的方法。你可以選擇一個類的構造方法,從重構菜單中選擇介紹工廠項,應用此重構,爲此類創建工廠方法。

在介紹工廠對話框,輸入工廠方法的名字和需要工廠方法創建的對象的名字。選擇構造方法的修飾詞是否爲私有。
點擊OK按鈕後,在指定的類中會出現此指定工廠方法。此方法創建一個當前類的實例,然後返回此實例。

Convert Local Variable to Field
轉換局部變量爲成員變量重構,將方法內的變量聲明移動到方法所在類中,使該變量對整個類可見。選擇一個局部變量,從重構菜單中選擇轉換局部變量爲成員變量項,隨後打開配置的對話框。

在此對話框中,添入成員變量的名字,選擇修飾詞,選擇在哪裏實例化此成員變量。隨後的聲明爲靜態,聲明爲final 選擇項是否可以使用,取決於實例化位置的選擇情況。

Encapsulate Field
要正確的實踐面向對象編程,應該將成員變量的修飾詞置爲私有,提供相應的訪問器來訪問這些成員變量。但是這些操作很煩瑣。如果使用了封裝成員變量重構,則十分方便。選擇一個成員變量,從重構菜單中選擇封裝成員變量項。

在封裝局部變量對話框中,添入Getter, Setter方法的名字,選擇新方法在哪個方法後出現。選擇合適的修飾詞。應用了此重構會創建兩個新方法,將此成員變量的修飾詞置爲私有,將對此成員變量的引用改變爲對新方法的引用。

重構項列表:
下表從Eclipse幫助中提取,列出了各種重構支持的Java資源類型,對應的快捷鍵。

名字 可應用的Java元素 快捷鍵
Undo 在一次重構後可執行 Alt + Shift + Z
Redo 在一次撤銷重構後可執行 Alt + Shift + Y
Rename 對方法,成員變量,局部變量,方法參數,對象,類,包,源代碼目錄,工程可用。 Alt + Shift + R
Move 對方法,成員變量,局部變量,方法參數,對象,類,包,源代碼目錄,工程可用。 Alt + Shift + V
Change Method Signature 對方法可用。 Alt + Shift + C
Convert Anonymous Class to Nested 對匿名內部類可用。
Move Member Type to New File 對嵌套類可用。
Push Down 對同一個類中成員變量和方法可用。
Pull Up 對同一個類中成員變量和方法,嵌套類可用。
Extract Interface 對類可用。
Generalize Type 對對象的聲明可用。
Use Supertype Where Possible 對類可用。
Inline 對方法,靜態final類,局部變量可用。 Alt + Shift + I

Extract Method 對方法中的一段代碼可用。 Alt + Shift + M

Extract Local Variable 對選中的與局部變量相關的代碼可用。 Alt + Shift + L

Extract Constant 對靜態final類變量,選中的與靜態final類變量相關的代碼可用。
Introduce Parameter 對方法中對成員變量和局部變量的引用可用。
Introduce Factory 對構造方法可用。
Convert Local Variable to Field 對局部變量可用。 Alt + Shift + F
Encapsulate Field 對成員變量可用。


本文介紹了Eclipse提供的各種重構。這些重構易於使用,可以確保代碼重構更加方便安全。而且可以自動生成代碼以提高生產率。
某些重構改變了某些類的結構,但沒有改變項目中其他類的結構,如下推,上移重構。這時,就要確保項目中所有對改變元素的引用都要被更新。這也是爲什麼要有一個好的測試套。同時,你也要更新測試套中的對改變元素的引用。所以說,重構和單元測試的有機結合對於軟件開發是多麼的重要。

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