Refactoring Java Code in Studio
Overview
Refactoring is the process of improving the design of code without changing the external behavior. It improves the design of a software or code, prevents decay of the program, improves readability, reduces bugs, makes it easier to spot bugs, speeds up code development and increases productivity.
Refactoring can be used to add a new feature or function to a code, to fix bugs or during code review. For more information on refactoring, visit www.refactoring.com.
This document describes the following Java refactoring available in Studio:
- Rename: Renames the selected package, class, method, field and variable
- Change method signature: Change method name, return type, parameter type, parameter name; Add or remove parameter; Reorders parameters
- Extract superclass: Create a superclass based on an existing class
- Extract super interface: Create an interface based on the methods of a class
- Move anonymous to inner: Convert an anonymous class into a named inner class
- Declare methods, variables, fields, and constructors: Declare any undeclared variable for a method, field, or constructor at the specified position
Refactoring framework in Studio
In Studio, files in the source tree are parsed prior to refactoring. This takes time based on the size of source. The selection is analyzed and it is ensured that refactoring is valid. Refactoring is performed for a valid selection. A backup copy of all affected files is made and an error message is displayed for an invalid selection. Studio provides error recovery options.
Refactoring in Studio has been designed to make the process easy. Refactoring is done by placing the cursor at the desired position. This is followed by analysis of the impact of refactoring, and manipulation of Abstract Syntax Tree(AST). An AST is a data structure representing parsed data. It can be used as an internal representation of a program being optimized and from which code is generated. The code is changed via manipulation of AST. Studying AST often helps in debugging and writing new refactoring. When refactoring is implemented, the manipulation functions contained in Studio should be used. Studio is aware of files that have been changed in AST.
Studio provides a preview option. When this option is enabled, all usages of the selected package, class, method, field, variable, interface or superclass to be refactored are in the output panel. The usages are grouped based on method invocation or declaration. User can include or exclude any usage. User must be careful while renaming an interface or overridden methods.
Renaming elements in the code
Rename refactoring in Studio enable you to rename a package, class, method, field, and local variable in the Java code. All references are updated, automatically. The following usages are renamed:
- Rename package: Package statements, import statements, and qualified names of classes
- Rename class: Import statements and the qualified names of the classes
- Rename method: All calls of the method, all overridden and implemented methods in the subclasses
- Rename field: All read and write usages of the field
- Rename variable: All read and write usages of the variable
To Rename a package, class, method, field or a variable:
- In Editor, place the cursor at the element to be renamed. For our example, let us rename a package TopicSess.
- Select Refactor > Rename from the menu bar or right click on the concerned Java file and select Refactor > Rename or click Shift + F8.
- Type a more comprehensible name for example, TopicSession.
- Select Preview usages to view all usages of TopicSession in the Preview tab in output panel; Select Search in comments and literals option in the Rename dialog to correct the usages of the refactored member in all comments and strings.
- To continue, click Run in the preview panel toolbar. To cancel, click Stop.
Changing method signatures
Change Method Signature (CMS) enables you to change a method name, add a parameter, remove a parameter, reorder parameters, change a return type, change a parameter type, and change a parameter name.
CMS is applicable to constructors as well but their name or return type can not be changed. It searches for all usages of the method. All calls, implementations and overriding of the method are modified accordingly to reflect the change. If a parameter is added, it should be supplied with a default value to be used for method calls. To change a method signature:
- In Editor, place the cursor at a method to be refactored. For our example let us change method signature for credit().
- Select Rafactor > Change Method Signature from menu bar or as a right click option, or press Ctrl + F8.
Table 1:
|
Attribute
|
Description
|
|
Method Name
|
Present name of the selected method is displayed
|
|
Visibility
|
Enables the user to select the method type such as Package, Private, Protected or Public
|
|
Return Type
|
Enables the user to select the return type for the method
|
|
Throws Exception
|
Enables the user to specify a particular exception to be detected
|
|
Method Parameters
|
Enables the user to add or remove parameters or change their order
|
Note: Parameters that are specified in the panel but do not exist in the selected file appear in red. Press enter to view details of the error.
- Select Preview option to view all occurrences of credit() in the output panel.
- To continue, select Run from the output panel tool bar. To cancel, select Stop.
When method signature can not be changed
A message appears if the method signature cannot be changed. A solution for the problem is also mentioned.
Extracting a superclass from an existing class
E xtract Superclass refactoring enables you to create a superclass based on an existing class. Fields and methods in the original class can be moved to the superclass. For a method, only the method declaration can be transferred. The implementation declaring the method as abstract in the superclass is non-transferable. The superclass and the original class are inherited from the superclass itself. Extract Superclass option in the main menu is disabled if cursor is placed at an invalid location.
- In Editor, place the cursor at the class to be extracted. For our example, let us extract the class CheckingBean.
- Select Refactor > Extract Superclass from menu bar. Enter the details in the panel.
Table 2:
|
Attribute
|
Description
|
|
Extract From
|
Displays the concerned package.filename
|
|
Superclass Name
|
Name of the superclass
|
|
Select Members
|
Select class members to be included in the superclass. Abstract option enables transfer of the method declaration and the its implementation in the class.
|
|
View Dependencies only
|
Enabling this option displays the selected members and their dependents only. This option is enabled only if one of the listed members is selected
|
|
Create JavaDoc
|
Creates a copy, or moves existing Javadoc; Generates stubs with all necessary tags and attributes. Selecting None does not create any Javadocs for the extracted class
|
Note: Selecting a member highlights other dependent members that are mandatory in the extracted class.
- Enter superclass name as TestBean; select members. Click OK to proceed. The option `View dependencies only' is enabled after a member is selected from the list. You can choose to view only those members that depend on the selection.
- Select Copy, None, or Move options to create Javadocs in the extracted class.
TestBean.java is created in Studio with all necessary details.
Extracting an interface based on methods of a class
Extract Super Interface refactoring enables the user to create an interface based on the methods of a class. Static final fields declared in the initial class can be moved to the interface. This creates an interface containing the selected methods and fields. The specified class methods implement the corresponding interface methods.
- In the editor, place the cursor at the class name or within the class.
- Select Refactor > Extract Interface from the menu bar.
- Enter details in the following panel:
Table 3:
|
Attribute
|
Description
|
|
Extract From
|
Displays the package and filename as package.filename
|
|
Interface Name
|
Name of the extracted interface
|
|
Select Members
|
Select class members to be included in the superclass.
|
|
Create JavaDoc
|
Generates a Javadoc stub with all necessary tags and attributes
|
Note: All the members are selected by default. the user can uncheck some members as per requirement.
Moving properties of an anonymous class to an inner class
In Studio, an anonymous class can be converted to a named inner class. If this class accesses any local variable, a constructor is created for the inner class and the values of the local variable are passed on. If the anonymous class is within a non-static method, a reference can be passed to the outer class of the constructor. Large anonymous classes can be simplified using this refactoring to make the code more readable and share selected inner class functionalities.
For example, to convert an anonymous class Runnable to an inner class Job:
- Place the cursor within the inner class.
Note: A warning appears if the cursor is placed at a wrong position.
- Select Refactor > Convert Anonymous To Inner from the right click menu or from the menu bar.
- In the panel, type the inner class name.
For this example, type Job. Click OK.
Note: Unselect Make class static option to obtain a non-static inner class. Select the type of inner class as Default, Private, Protected, or Public. If constructors for the inner class are required, provide package details in the Constructor Parameters field.
Declaring method, variable, field, and constructors
Any undeclared variable for a method, field, or constructor is declared at the specified position. Studio provides:
- Method declaration
- Variable declaration
- Field declaration
- Constructor declaration
Place the cursor at the undeclared variable and press Alt + Enter.
- Variable Declaration: The variable gets declared assuming that the block of code in which it is declared is the scope of use of that variable. The dropdown suggests all the variable types that can be used to declare the variable
- Field Declaration: The variable is declared as a class level variable or a field. The dialog provides:
- List of CreateIn which are the classes where that field declaration can be done
- The modifier combo box lists all the modifiers that are allowed based on the context in which it is called and the class in which it is going to be declared. The modifier list changes by changing the CreateIn. Field type is the same as the variable declaration.
- Constructor Declaration: When the modifier or super is called inside a constructor for an undefined constructor declaration, the modifier is declared as public. In the parameter table, all parameter types are in a available in the dropdown that provides a list of the variable wide types allowed in that context
- For class instance creation with a set of parameters for which there is no constructor, the constructor is declared in the class to which the constructor belongs. The name of the parameter is taken from the context of use.
- Method Declaration: CreateIn provides options to define the method in the inner, superclasses, or interface. The modifiers are the same as the case of field and depend on the context of use. Parameter Table contain the same info as constructor declaration.
Limitations of refactoring
Refactoring has the following limitations:
- Databases: Some refactoring may involve changing the database schema. Business applications are generally coupled with the database schema that supports them. This makes database difficult to change. Even for layered databases where there are minimum dependencies, migrating the data is a long task.
- Changing Interfaces: Refactoring such as rename method, change interfaces. The implementation of a software module is changed separately from changing the interfaces. If refactoring changes a published interface, both the old and new interfaces should be retained with the old interface still working to avoid loss of data.
- Code: When the current code does not work and rewriting the whole code is necessary, refactoring should be avoided. This area is still being worked upon.
Note: Design changes and mistakes are difficult to refactor. This area is still being worked upon.