CSC/ECE 517 Fall 2011/ch5 5d he
Automatic Refactoring
Introduction
Refactoring is a technique for restructuring an existing code, altering its internal structure without changing its external behavior. Its done as a series of small transformations. Each transformation does little, but a sequence of transformations can produce a significant restructuring. Since each refactoring is small, it's less likely to go wrong. The system is also kept fully working after each small refactoring, reducing the chances that a system can get seriously broken during the restructuring.<ref name="refone"> Refactoring Home Page http://refactoring.com/ </ref> As people make changes to the code to realize their short term goals without fully understanding the design of code, the code loses its structure. The refactoring work is done to remove bits that aren’t really in the right place. Loss of the structure of code has a cumulative effect. The harder it is to see the design in the code, the harder it is to preserve it, and the more rapidly it decays. Regular refactoring helps code retain its shape. <ref name="reftwo"> Why should you Refactor http://sourcemaking.com/refactoring/why-should-you-refactor </ref>
Fully autonomous factoring doesn't appear to exist at this time in the IDE(s) described below. However there are papers Inducing Evolution-Robust Pointcuts <Ref name="refseven">Inducing Evolution-Robust Pointcuts, Braem, M.</ref> and Automatic Refactoring of Erlang Programs<ref name="refeight">Automatic Refactoring of Erlang Programs http://www.ece.cmu.edu/~aavgerin/papers/PPDP09.pdf</ref> that point the way to the future of refactoring that can be fully automated. In the context of this wiki article, automatic refactoring means automated refactoring under programmer control and guidance.
Common Refactoring Techniques
Extraction Refactoring
There are several refactoring techniques related to extraction: Extract method, Extract local variables, extract constants. The first method "Extract method will create a new method from code you've selected. Extract Local Variable refactoring takes an expression that is being used repeatedly and assigns it to a local variable. Extract constant refactoring is to select a static, constant expression, which the refactoring will convert to a static final constant. This is useful for removing hard-coded numbers and strings from your code
Inline Refactoring
This type refactoring is the reverse of local variable extraction, in which we remove a local variable and use the value of the variable(typically an expression) in the place where the variable is used. This can be marginally more efficient than using a temporary variable and, by making the code terser, makes it either easier to read or more cryptic, depending on your point of view<ref name="refthree"> refactoring for everyone http://www.ibm.com/developerworks/library/os-ecref/ </ref>
Encapsulating Fields
Generally its not a good practice to expose the class attributes through public interface. Thus, Encapsulating such fields will make such fields as private or protected as appropriate and generate getters and setters for the associated field.
Changing Method Signature
Here we change the change the parameters, visibility, and return type of a method.
Other Refactorings
There are a multitude of refactorings. Those that are included with RubyMine<ref name="reffour">RubyMine :: Ruby and Ruby on Rails IDE with smart code completion, syntax highlighting and refactoring http://www.jetbrains.com/ruby/features/ruby_ide.html#Refactorings</ref> include:
- Rename refactoring
- Extract Method
- Extract Module
- Extract Superclass
- Introduce Variable
- Introduce Constant
- Introduce Field
- Introduce Parameter
- Inline Variable
- Pull Up Members
- Push Down Members
- Override Method
Martin Fowler has online resources for additional refactoring definitions which can be found here http://martinfowler.com/bliki/refactoring.html<ref name="reffive">MF Blicki: refactoring http://martinfowler.com/bliki/refactoring.html</ref> and here http://refactoring.com/catalog/<ref name="refsix">Alpha list of refactorings http://refactoring.com/catalog/</ref>.
Refactoring support in popular IDE(s)
IDE | Language(s) | Refactoring Support | Automated Refactoring? | Number of Refactoring support | Support for Pattern | Example |
---|---|---|---|---|---|---|
Borland Delphi | Object Oriented Pascal | Rename refactoring, Refactor driven “Find References”, Introduce Variable refactoring, Introduce Field refactoring, Inline Variable refactoring, Change Parameters refactoring, Safe Delete refactoring, Push Members Up / Down refactoring, Pull Members Up refactoring, Extract Superclass refactoring, Extract Interface refactoring, Move Members refactoring, Declare variable refactoring, Declare field refactoring, Extract method refactoring, Find unit/import namespace refactoring, Refactor driven “Find in Files”, Extract to resource string refactoring<ref name="borlandrefactorings>Leveraging What You Have: 10 Top Things Added to Delphi Since Delphi 7 http://edn.embarcadero.com/article/37416</ref> | Yes | 17 | Declare Variable<ref name="borlanddecvar">Increased Productivity with Refactoring, Unit Testing, Help Insight, Error Insight, and Sync Edit in Borland Delphi 2005 http://edn.embarcadero.com/article/33278</ref> |
Before Refactoring procedure TWinForm1.btnOpen_Click(sender: System.Object; e: System.EventArgs); begin if (OpenFileDialog1.ShowDialog = System.Windows.Forms.DialogResult.OK) then begin Assign(f,OpenFileDialog1.FileName); Reset(f); try finally CloseFile(f); end; end; end; After Refactoring procedure TWinForm1.btnOpen_Click(sender: System.Object; e: System.EventArgs); var f: TextFile; begin if (OpenFileDialog1.ShowDialog = System.Windows.Forms.DialogResult.OK) then begin Assign(f,OpenFileDialog1.FileName); Reset(f); try finally CloseFile(f); end; end; end; |
Eclipse <ref name='refeclipse'>Eclipse Refactoring Actions http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Freference%2Fref-menu-refactor.htm </ref> | C, C++, Java | Rename selected Elements, Move selected elements, Change Method Signature, Extraction, Convert Anonymous Class to Nested, Convert Local Variable to Field, Extract Super class and Interface, push down, pull up, Introduce Indirection, Encapsulate Field, Migrate JAR File, Create & Apply Refatoring Scripts | Yes | 27 | Introduce Factory |
Before Refactoring int x= p * 5; p.x; After Refactoring int x= getFoo(p); (Method Extraction) p.getX() (Encapsulate Field) |
Kdevelop | C, C++ | Several<ref name="kdeveloprefactorings">Kdevelop4: Now with refactoring! http://zwabel.wordpress.com/2008/11/05/kdevelop4-now-with-refactoring/</ref> | Yes but very limited. Project wide search/replace and local search/replace. | 2 | Rename Class | Right click on class name and select Rename |
NetBeans <ref name="refnetbeans">Refactoring in NetBeans 4.1 http://java.sun.com/developer/technicalArticles/tools/refactoring/</ref> | Java | Renaming fields, methods, classes, or packages, Encapsulating fields, Changing method parameters, Moving classes, | Yes but very limited | 4 | No |
Before Refactoring public class Foo{ public int n; public int Compute(int val); } After Refactoring (Encapsulating field) pubic class Foo{ private int n; public int getN(); public void setN(int val); public int Compute(int arg); } |
Padre | Perl | Lexically Rename Variable, Introduce Temporary Variable<ref name="padrerefactorings" >How to do it in Padre http://padre.perlide.org/howto.html</ref> | Yes | Unknown | Right click on item to refactor and select refactoring choice from the context menu | |
RubyMine | Ruby | No | Yes | 11 | Introduce Temporary |
Before Refactoring c = a * b + 5 d = 2 * a * b After Refactoring t = a * b c = t + 5 d = 2 * t |
Visual Studio <ref name="refvstudio">7 Refactoring Methods in Visual Studio 2010 http://p2p.wrox.com/content/articles/7-refactoring-methods-visual-studio-2010 </ref> | C, C++, Java, C# | Extract Method, Encapsulate Field, Extract Interface, Rename, Promote Variable to Parameter(Changing method signature), Generate Method Stub(Used for testing purposes) | Yes | 7 | No | Promoting Variable to Parameter
Before Refactoring public void MethodA() { MethodB(); } public void MethodB() { string output = "Test String"; MessageBox.Show( output); } After Refactoring public void MethodA() { MethodB("Test String"); } public void MethodB(string output) { MessageBox.Show( output); } |
Refactoring in NetBeans
References
<references/>