The authors are reconstructed by Eclipse automatic reconstruction capabilities to explore the Eclipse auto-reconstruction can assist in reacting this process. The program example uses the example in the book "Refactoring: Improving The Design of Existing Code".
Eclipse's auto-reconstruction feature is well supported by various program elements, and automatically updates related references. Eclipse can support methods and fields move between classes and automatically update references. Eclipse helps the inner field, the update replacement of the function. Eclipse gives the extraction method, variables and other program elements.
The process of reconstructing is a process that is constantly trying to and explores. Eclipse's reconstruction supports revocation and redo, and can preview the result of reconstruction, which is a practical function.
Eclipse's renaming, extraction method, mobile, inline function, change method of code structure levels, etc., is a function of comparing maturing and also worthwhile. As for the design structure, Eclipse does not support well. However, the author believes that the concept of automatic reconstruction should be "Refactoring in Tools", and people still undertake most of the reconstruction work.
First, preparatory work
This article uses "Refactoring: Improving The Design of Existing Code" example. The code before reconstructing and the code after each step of reconstruction see annex. Readers are best to cooperate with "Refactoring: Improving The Design of Existing Code".
Eclipse uses the following version:
The Chinese language package is installed at the same time.
Second, refactoring the first step: decomposition and recombinant Statement ()
purpose:
1. Refieve the SWICH statement in the statement () function into a stand-alone function amounectFor ().
2. Modify the AmountFor () parameter name
Reconstruction method:
EXTRACT METHOD
Rename Method
method:
1. Select the code block of the SWICH statement, select "Reconstruction / Extraction Method" in the Right-click menu, and the parameter dialog box appears. Eclipse automatically analyzes local variables in the code block and finds two local variables: Each and THISAMOUNT. Where EACH is only read in the code block, but Thisamount will be modified in the code block. According to the rules summarized by Reconstruction of Extract Method, you should use the EACH as a parameter of the extracted function, thisamount is used as the return value of the extracted function. However, Eclipse does not distinguish between the two variables directly as the parameters of the new method, as shown.
Our goal is to use the EACH that is not modified in the extraction function as a parameter; the THISAMOUNT that will be modified as the return value. The solution is to
Double THISAMOUNT = 0; this line code is moved to the top of the Switch statement, turning this:
Double THISAMOUNT = 0;
Switch (Each.getMovie (). getpricecode ()) {
Case Movie.Regular:
THISAMOUNT = 2;
IF (Each.getDaysrented ()> 2)
THISAMOUNT = (Each.getDaysrented () - 2) * 1.5;
Break;
Case movie.new_release:
THISAMOUNT = Each.getDaysrented () * 3;
Break;
Case movie.childrens:
THISAMOUNT = 1.5;
IF (Each.getDaysrented ()> 3)
THISAMOUNT = (Each.getDaysrented () - 3) * 1.5; Break;
}
Select this code, select "Reconstruction / Extraction Method" in the Right-click menu, Eclipse becomes smart this time, as shown.
Select the "Preview" button to pre-see the results after the rectification, which is in line with our original purpose.
Select the "OK" button, the pieces after the reconstruction are as follows:
Public string stat () {
Double totalamount = 0;
INT frequentrenterpoints = 0;
ENUMERATION RENTALS = _Rentals.ements ();
String result = "Rental Record for" getName () "/ n";
While (rentals.hasmorelements ()) {
Rental Each = (RENTAL) RENTALS.NEXTELEMENT ();
Double THISAMOUNT = AmountFor (EACH);
FREQUENTRENTERPOINTS ;
IF ((Each.getMovie (). getPriceCode ()) == Movie.new_Release &&
Each.getDaysrented ()> 1)
FREQUENTRENTERPOINTS ;
Result = "/ t" each.getmovie (). gettitle () "/ t"
String.Valueof (THISAMOUNT) "/ N";
Totalamount = THISAMOUNT;
}
Result = "Amount Owed IS" String.Valueof (Totalamount) "/ N";
Result = "You eighted" String.Valueof (frequentrenterpoints)
"frequent renter points";
Return Result;
}
/ **
* @Param EACH
* @Return
* /
Private Double AmountFor (Rental Each) {
Double THISAMOUNT = 0;
Switch (Each.getMovie (). getpricecode ()) {
Case Movie.Regular:
THISAMOUNT = 2;
IF (Each.getDaysrented ()> 2)
THISAMOUNT = (Each.getDaysrented () - 2) * 1.5;
Break;
Case movie.new_release:
THISAMOUNT = Each.getDaysrented () * 3;
Break;
Case movie.childrens:
THISAMOUNT = 1.5;
IF (Each.getDaysrented ()> 3)
THISAMOUNT = (Each.getDaysrented () - 3) * 1.5;
Break;
}
Return THISAMOUNT;
}
2, select the parameter Each of AmountFor (), select "Reconstruction / Rename" in the Right-click menu, enter a new name in the dialog: Arental, select OK, all EACH references in AmountFor () are replaced with new The name. Modify local variables in AmountFor () for Result with the same approach. The AMOUNTFOR () code after reconstruction is as follows: / **
* @Param Arental
* @Return
* /
Private Double Amountfor (Rental
Arental) {
Double
Result = 0;
Switch
Arental.getmovie (). getpricecode ()) {
Case Movie.Regular:
RESULT = 2;
IF
Arental.getDaysrented ()> 2)
Result = (Arental.getDaysrented () - 2) * 1.5;
Break;
Case movie.new_release:
Result =
Arental.getDaysrented () * 3;
Break;
Case movie.childrens:
RESULT = 1.5;
IF
Arental.getDaysrented ()> 3)
Result = (Arental.getDaysrented () - 3) * 1.5;
Break;
}
Return
RESULT;
}
Third, reconstruct the second step: move the "amount calculation" code
purpose:
1. Transfer the function amountfor () into the Rental class and renamed GetCharge ().
2, update and replace all references to AmountFor ().
Reconstruction method:
Move Method
Change method Signatrue
INLINE METHOD
Inline Temp
method:
1. Select the definition of the function amountfor (), select Refactor / Move in the Right-click menu, display the parameter settings dialog. Change the new method name to getcharge. Press the "OK" button, the AmountFor () function in the Customer Class is moved to the Rental Class and is renamed: getcharge ().
At the same time, Eclipse automatically adds a line of "delegate" code to the new function in the customer amountfor () function:
Private Double AmountFor (Rental "{
Return area org.getcharge ();
}
This line of code produces compilation errors because the AmountFor () private type is passed to a new method:
/ **
* @Param this
* @Return
* /
Private Double getcharge () {
......
}
2, continue to refactor! Select the getcharge () method, select "Reconstruction / Change Method" in the Right-click menu, pop up the parameter selection dialog box, change the access modifier from private to public. Eclipse's compilation error prompts disappear automatically.
3, return to the Customer class, replace all the places referenced to AmountFor () with direct reference to getcharge (). Select the function Amountfor (Rental Arental) of the Customer class, select Reconstruction / Inline in the Right-click menu, and the parameter selection dialog box appears.
Select the "Confirm" button to reference the AmountFor () place to be replaced with a reference to getcharge ().
Public string stat () {...
Double THISAMOUNT = Each.getcharge ();
......
}
4. Remove the temporary variable THISAMOUNT.
Select the variable THISAMOUNT, select "Reconstruction / Inline" in the Right-click menu, and the preview window is reconstructed as follows, and it can be seen that the purpose of the reconstruction is met. Press the "Confirm" button to reconstruct the code.
Statement () code:
Public string stat () {
Double Totalamount = 0; // Total consumption amount
INT frequentrenterpoints = 0; // Changke points
ENUMERATION RENTALS = _Rentals.ements ();
String result = "Rental Record for" getName () "/ n";
While (rentals.hasmorelements ()) {
Rental Each = (Rental) Rentals.nexTelement (); // Get a rental record
// Add frequent renter Points (accumulated generic point)
FREQUENTRENTERPOINTS ;
// Add bouns for a two two new release restal
IF ((Each.getMovie (). getPriceCode ()) == Movie.new_Release &&
Each.getDaysrented ()> 1)
FREQUENTRENTERPOINTS ;
// show figures for this rental (Show this bank)
Result = "/ t" each.getmovie (). gettitle () "/ t"
String.Valueof (Each.getcharge ()) "/ n";
TOTALAMOUNT = Each.getCharge ();
}
// Add Footer Lines (finish print)
Result = "Amount Owed IS" String.Valueof (Totalamount) "/ N";
Result = "You eighted" String.Valueof (frequentrenterpoints)
"frequent renter points";
Return Result;
}
Fourth, reconstruct the third step: refine the "constant customer point calculation" code
OBJECTIVE: To extract the "Regular Calculation Calculation" code and placed in the Rental class, the "Regular Calculation Calculation" code is as follows.
Public string stat () {
......
// Add frequent renter Points
FREQUENTRENTERPOINTS ;
// Add bouns for a two two new release restal
IF ((Each.getMovie (). getPriceCode ()) == Movie.new_Release &&
Each.getDaysrented ()> 1)
FREQUENTRENTERPOINTS ;
......
}
The code after the reconstruction is as follows:
Frequentrenterpoints = each.getfrequentrenterpoints (); Reconstruction Method:
EXTRACT METHOD
Move Method
Change method Signatrue
INLINE METHOD
method:
1. First, extract the code to a separate function.
Reconstruct the code with "Extraction Method": GetFrequentrenterpoints. Unfortunately, Eclipse cannot generate code such as: frequentrenterpoints = getfrequentrenterpoints (Rental Arental); The reason is that the partial variables of the self-incremental operation FREQUENTRENTERPOINTS should appear on the right of the equation, so the extraction function getFrequentrenterPoints () must use frequentrenterpoints as a parameter. Handmade modification function and reference to the function, the code after the reconstruction is as follows:
Public string stat () {
......
While (rentals.hasmorelements ()) {
......
Frequentrenterpoints = getFrequentrenterPoints (EACH);
......
}
......
}
/ **
* @Param EACH
* @Return
* /
Private Int getFrequentrenterpoints (Rental Each) {
IF ((Each.getMovie (). getPriceCode ()) == Movie.new_Release &&
Each.getDaysrented ()> 1)
Return 2;
Else
Return 1;
}
2, move getFrequentrenterPoints () into the Rental class.
3. For GetFrequentRenterPoints () Change Method Characteristic "for public.
4. Execute the inline operation with the Customer's function getfrequentrenterpoints () to complete the target.
V. Reconstruct the fourth step: remove temporary variables (Totalamount and FrequentrenterPoints)
Purpose: Removal of temporary variables (TOTALAMOUNT and FREQUENTRENTERPOINTS)
method:
1. Analyze the definitions and reference structures of Totalamount and FREQUENTRENTERPOINTS are as follows:
//
Declaration and definition
Double totalamount = 0;
INT frequentrenterpoints = 0;
......
//
Modify in the cycle
While (rentals.hasmorelements ()) {
......
FREQUENTRENTERPOINTS = Each.getFrequentrenterPoints ();
......
TOTALAMOUNT = Each.getCharge ();
......
}
......
//
Use outside the cycle
Result = "Amount Owed IS" String.Valueof (Totalamount) "/ N";
Result = "You eighted" String.Valueof (frequentrenterpoints)
"frequent renter points"; ......
The above two variables are defined and used outside the cyclic body, modified in the cycle, using the Replace Temp with Query method to remove these two temporary variables is a slightly complex reconstruction. Unfortunately, Eclipse does not currently support such reconstruction.
2, manually modify the code.
6. Reconstruct the fifth step: use polymorphic substitution and price-related conditions logic
purpose:
1. Move the function getcharge in the RentAl class to the MOVIE class.
2. Move the functions in the RentAl class into the MOVIE class.
Reconstruction method:
Move Method
INLINE METHOD
method:
1. Select the function getcharge () in the Rental class, the right-key menu is selected, and the Eclipse prompts that the recipient cannot be not moved. The reason is this row statement:
Switch (GetMovie (). getpricecode ()) {// get a movie rental price
Select GetMovie (), right-key menu selection "Reconstruction / Inline", and determine the postcode to become:
Switch (_MoVie.getPricecode ()) {// get a movie rental price
After selecting getcharge (), after "Reconstruction / Move" is executed, the function is moved to the MOVIE class. However, this is only partially reached a restructuring, we found that the mobile code passed the Rental as a parameter to getcharge (), manually modified, code becomes:
Class movie ...
/ **
* @Param this
* @Return
* /
Public Double getcharge
INT _DAYSRENTED {
Double result = 0;
Switch (getpricecode ()) {// get a movie rental price
Case movie.regular: // ordinary film
RESULT = 2;
IF (_
DaysRented> 2)
Result = (_
DaySRENTED-2) * 1.5;
Break;
Case movie.new_release: // new film
Result = _
DaysRented * 3;
Break;
Case movie.childrens: // Children's film
RESULT = 1.5;
IF (_
DaysRented> 3)
Result = (_
DaysRenTED-3) * 1.5;
Break;
}
Return Result;
}
Class Rental ...
/ **
* @Param this
* @Return
* /
Public double getcharge () {
Return_Movie.getcharge (_
Daysrented);
}
2. Treat GetFreQuentrenterPoints (), reconstructed code:
Class movie ...
/ **
* @Param Frequentrenterpoints
* @Param this
* @Return
* /
Public int getFrequentrenterPoints (int daysrented) {
IF ((GetPriceCode ()) == Movie.new_release &&
Daysrented> 1)
Return 2;
Else
Return 1;
}
Class Rental ...
/ **
* @Param Frequentrenterpoints * @Param THIS
* @Return
* /
Public int getFrequentrenterPoints (int daysrented) {
IF ((GetPriceCode ()) == Movie.new_release &&
Daysrented> 1)
Return 2;
Else
Return 1;
}
Seven, reconstruct the sixth step: finally ... we come to inherit
Purpose: To introduce the STATE mode for the Switch statement.
method:
Unfortunately, I have to end Eclipse automatic reconstruction journey in advance. Eclipse can hardly do structural reconstruction. Perhaps Martin Fowler's automatic reconstruction tool calls in the book from "Refactoring Work under Tools". Art is a patented in humans, and the dream of programming art will continue.
Interested readers can view the last step of handmade. Take the reconstruction!
Appendix: Eclipse support reconstruction method (from eclipse Chinese help)
name
Features
Revoke
Perform the "revocation" of the previous reconstruction. As long as any other source changes have not been executed other than the reconstruction, the reconstruction of the revocation buffer is valid.
Redo
Execute "redo" in the last revocation. As long as any other source changes have not been executed other than the reconstruction, reconstruct the revocation / redo buffer is effective.
Rename
Start the "Rename" Reconstruction dialog box: Rename the selected element and correct all references to the element (if it is enabled) (still in other files). Can be used for: methods, fields, local variables, method parameters, types, compilers, packages, source folders, and items parsing to one of these element types.
mobile
Start the "Move" Reconstruction dialog: Move the selected element and correct all references to the element (if it is enabled) (still in other files). Suitable for: an instance method (which can be moved to a component), one or more static methods, static fields, types, compilers, packages, source folders, and projects, and one of these elements The text selection section of the species.
Change method characteristic
Start the "Change Method" Reconstruction dialog. Change the parameter name, parameter type, and parameter order, and update all references to the appropriate method. In addition, parameters can be removed or added, and the method returns the type and its visibility. This reconstruction can be applied to methods or parsing text selection.
Convert anonymous class to nested classes
Start "Convert anonymous class to Nested Class" Reconstruction dialog. Help you convert an anonymous internal class to a member class. This reconstruction can be applied to anonymous internal classes.
Convert nested types to top
Start "Convert Nested Type to Top Type" Reconstruction dialog. Create a new Java compiler for the selected member type and update all references as needed. For non-static member types, the fields will be added to allow access to the previous peripheral instance. This reconstruction can be applied to a member type or parsing for text.
Push
Start "down" reconstruction dialog box. Move a group of methods and fields from a class to its subclass. This reconstruction can be applied to a text selection in one or more methods and fields or fields or methods declared in the same type.
pull up
Start "pull" reconstruction wizard. Move the field or method to the superclass or (for method) to declare the method as an abstract class in the superclass. This reconstruction can be applied to one or more methods, fields, and member types declared in the same type, or can be applied to text selection within the field, method, or member type.
Extraction
Start the "Extract Interface" Reconstruction dialog. Use a set of methods to create a new interface and make the selected class implement the interface and change the reference to the class to a reference to the new interface as much as possible. This reconstruction can be applied to the type.
Use super-type as much as possible
Start "Use the Super Type" dialog box as much as possible. Replace a type of appearance as one of its hypercarpse, before performing this replacement, you need to identify all possible locations that are possible for this replacement. This reconstruction can be used for types. Inline
Start the "Inline" reconstruction dialog. Inline local variables, methods or constants. This reconstruction can be used in a text selection of methods, static final fields, and parsing to methods, static final fields, or local variables.
Extraction method
Start the "extraction method" reconstruction dialog. Create a new way to include the currently selected statement or expression and replace the replacement with reference to the new method. You can use the editing menu
Expand the choice to get a valid selection range.
This feature is useful for cleaning lengthy, messy or too complex methods.
Extract local variables
Start the "Extracted Variable" Reconstruction dialog. Create a new variable specified by the currently selected expression and replace the selection to reference to the new variable. This reconstruction can be used to resolve text selection for local variables. You can use the editing menu
Expand the choice to get a valid selection range.
Extract constant
Start the "Extracted Constant" Reconstruction dialog. Creating a static final field from the selected expression and replacing the field reference, and you can select some other location where you rewrite the same expression. This reconstruction can be used for a static final field and a text selection parsing to a static final field.
Convert local variables to fields
Start the "Transition to the Local Variable to Field" Reconstruction dialog. Convert local variables into a field. If the variable is initialized at the time of creation, this operation will move the initialization to the declaration or class of the new field or class constructor. This reconstruction can be used to resolve text selection for local variables.
Encapsulation field
Start the "Self-Packing Field" Reconstruction dialog. Replace all references to fields with getting and setting methods. It applies to the selected field or parsing text selection.
Code download
Author: Zhang Yu
Lenovo Lindi Software (Original Lenovo Software Design Center)