CSC/ECE 517 Fall 2009/wiki1a 9 mk: Difference between revisions
(One intermediate revision by the same user not shown) | |
(No difference)
|
Latest revision as of 15:17, 12 September 2009
Research in Refactoring Tools
Refactoring
Refactoring is the process of modifying existing source codebase in a structured and incremental way, while preserving its external behavior. This process preserves the functionality of the program without introducing new bugs. Refactoring also promotes reuse of the existing codebase for other purposes thus increasing code reusability.
Overview
One of the most important aspect of any software meant for real world applications is its ability to evolve.Many surveys conducted by major software organizations have reavealed that, maintenance is the major part of the total Software Development life cycle. Maintenance of the code would be much less difficult, if the code has the capacity to evolve, where in refactoring comes into picture. Refactoring improves the internal structure of the codebase keeping the behaviour/functionality of the program same as before and therefore any program which meets its specifications before refactoring will continue to meet those specifications even afterwards. Refactoring can be done on any codebase and it is a general set of operations. Hence, it comes with preconditions which specifies under what circumstances refactoring can be performed, also with the conformation that the dependency graphs are unchanged even after the refactoring is performed.
Code smell: Code smell is the surface indication that usually corresponds to problem in the code [system].
So of the common code smell examples are:
- A class that has grown too large.
- A class that uses methods of another class excessively.
- Classes that depend on the implementation details of other classes.
- Identical or very similar code exists in more than one location.
- A class that does too little or which can be implemented as a method in some other class.
- A method, function, or procedure that has grown too large.
- A method, function, or procedure that is very similar to another.
- A situation where in a complicated design pattern is chosen over a simple design which would be sufficient.
These are some of the indications that code refactoring needs to be done. Code Refactoring is done to remove the above specified code smells.
Code Smell(Duplicate Code) example
if (this.o.ChkSum()) { Operation1(); }
and in another method you have: if (this.o.ChkSum()) { Operation2(); }
Current Automated Refactoring Tools
Most of Refactoring tool features can be grouped into three broad categories.
1. Changing the name and physical organization of code, including renaming fields, variables, classes, and interfaces, and moving packages and classes.
2. Changing the logical organization of code at the class level, including turning anonymous classes into nested classes, turning nested classes into top-level classes, creating interfaces from concrete classes, and moving methods or fields from a class to a subclass or superclass.
3. Changing the code within a class, including turning local variables into class fields, turning selected code in a method into a separate method, and generating getter and setter methods for fields.
Given below is an example of Refactoring, demonstrating how it enhances reusability
void displayValues() { double averageSalary = 0; double totalCars = 0; for (int i = 0; i < people.length; i++) { averageSalary += people[i].salary; totalCars += people[i].carCount; } averageSalary = averageSalary / people.length; System.out.println(averageSalary); System.out.println(totalCars); }
The refactored code:
void printValues() { System.out.println(averageSalary()); System.out.println(totalCars()); } private double averageSalary() { double result = 0; for (int i = 0; i < people.length; i++) { result += people[i].salary; } return result / people.length; } private double totalCars() { double result = 0; for (int i = 0; i < people.length; i++) { result += people[i].carCount; } return result; }
Given below is the list of most used automated refactoring tools
- Aptana for Ruby(Can be used as a Plug-in for Eclipse)
- IntelliJ IDEA
- Eclipse's JDT
- NetBeans (for Java)
- Visual Studio 2008 (for .NET)
- ReSharper (An addon for Visual Studio)
- Refactor Pro (An addon for Visual Studio)
Academic underpinnings behind the refactoring work
William F. Opdyke, who is one of the important person behind the success of refactoring, was the first to think in the lines of "why people could be reluctant to refactor their software, given that refactoring improves the software.They found mainly four reasons
1. "I don't understand how to refactor."
2. "If the benefits are long-term, why exert the effort now? In the long term, I may no longer be with the project.”
3. "Refactoring code is an overhead activity; I’m paid to write new features."
4. "Refactoring might break the code."
The first two issues were addressed by defining a taxonomy of refactoring, which helped both in short term as well as in long term. For example, when defining a new feature that is a variant on an existing feature, one can define classes (usually abstract classes) that capture the common behavior, and use subclassing to capture the feature differences. The approach for addressing the latter two of these issues was by providing automated assistance, which help to increase the speed of program restructuring.
William F. Opdyke, in one his other research found that, object-oriented programming makes program components more reusable, but in the long run reusing the design of an application is more important than reusing the implementation of any
one of its components. An important object-oriented technique to facilitate design-level reuse is an application frame-
work, which is an abstract design of an application, consisting of an abstract class for each
major component. The important aspects of the framework are given below, most of which are self explainatory
- Preserving Behavior During Refactoring: Refactoring is likely to violate seven properties: a class is allowed to have no more than one superclass, which cannot be one of its subclasses; class names and memeber names must be distinct; inherited member variables should not be overridden; signatures compatibility between overriding methods and the overridden method; assignments must always be typesafe; semantic equivalence between references and operations i.e., the mapping of inputs to outputs must be the same.
- Twenty-six low-level refactorings whose correctness is argued, fall in one of the categories:Creating a Program Entity, Deleting a Program Entity, Changing Program Entity, Moving a member variables.
- Refactoring To Generalize: Creating An Abstract Super-class involves, identifying and moving common features between classes to an abstract superclass.
- Refactoring To Specialize: Subclassing and Simplifying Conditionals.
- Capturing Aggregations and Components: Refactorings involving aggregations include moving members between an aggregate and component classes and converting inheritance to aggregation. These require that components be distinguishable from non-component members and that all components be exclusive, i.e., exist in only one aggregate object at any time.
We take a Matrix and 2D array example to demonstrate, why refactoring preferably converts inheritance to aggregation. Matrix class inheriting from 2D array, which in turn has an array to store elements and get/set operations to access elements, seems resonable at one glance. Lets take a function of matrix multiply as shown below
Matrix matrixMultiply(Matrix m){ j=get(x,y); put(k,x,y); ... ... }
There is a problem with this representation because, if a matrix is a special matrix like sparse, it can be more efficiently stored than storing in a 2D array. In inheritance, the matrix class is tighlty coupled to the 2D class, so it cannot be changed. A matrix has a representation and is not a representation. So, the operations on abstraction and representation class need to be separated.So, we introduce a new class Matrix representation and we can create an instance of 2D array class inside the aggregate of Matrix class given as below.
Matrix matrixMultiply(Matrix m){ j=matrixRep->get(x,y); matrixRep->put(k,x,y); ... ... }
Now, the get and set are referenced through new component and inheritance link can be modified.
Improvements Current Refactoring Tools need
Tools that help the programmers with refactoring should:
- Be lightweight. Users can normally select code quickly and efficiently, and any tool to assist selection should not add overhead to slow down the common case.
- Help the programmer overcome unfamiliar or unusual code formatting.
- Allow the programmer to select code in a manner specific to the task they are performing. For example, while bracket matching can be helpful, bracketed statements are not the only meaningful program construct that a programmer needs to select.
- Language Independent, all of the current refactoring tools depend on language-dependent refactoring engines, which prevents a smooth integration with mainstream development environments.They should minimize the language-dependent part of refactoring tools, providing a standard way for programmers and tools to perform refactorings no matter what language they work in.
- Meta-model Approach
- Program Auditing facilities like UML diagrams, documentation etc help in understanding the programs better and a tight integration between these auditing facilities and refactory tools will be real good. Most commonly, integration in software development environments is achieved by means of a repository: a shared database accumulating all knowledge about the software system underdevelopment. Thus, for refactoring tools to become part of mainstream software development environments, the most natural way would be to adhere to a repository architecture. Such a repository architecture requires a central data model (the so-called meta-model) which should be highly language independent and contain sufficient information to represent refactorings.
- Capable of performing Security Oriented transformation, which mean automated transformations that change programs to eliminate security threats;they can be source to source or binary to binary transformations. They improve the security of systems, which means that they do not preserve all types of behavior (although this is against the very definition of refactoring). They preserve expected behavior, but should change a system’s response to security attacks.
Conclusion
Refactoring is an integral part of all software development projects and it is very important for refactoring tools to make refactoring fast and functionality preserving. There are many improvements that have been suggested for code refactoring and it is required that it gets implemented to reduce code smell, provide easier understanding of code, as well as re usability of code. These qualities will be adopted by new refactoring tools, making them usable and thus more used, and eventually contribute to the production of more reliable, on-time refactored software. It is also important that the refactoring tools improve the experience of refactoring, help programmers correctly identify problems with a proposed refactoring, and increase speed of the refactoring process.
See Also
- Refactoring: Improving the Design of Existing Code by Martin Fowler, Kent Beck, John Brant
- Design pattern (computer science)
- Code Factoring
- Redesign (software)
References
[1] http://www.refactoring.com
[2] https://netfiles.uiuc.edu/dig/RefactoringInfo/
[3] William F. Opdyke. Refactoring Object-Oriented Frameworks. Ph.D.thesis, University of Illinois at Urbana-Champaign, 1992.
[4] A Meta-model for Language-Independent Refactoring (2000) Sander Tichelaar , Stéphane Ducasse , Serge Demeyer , Oscar Nierstrasz
[5] Refactoring Object-Oriented Software to Support Evolution and Reuse, William F. Opdyke
[6] Security Oriented ProgramTransformations (Or How to Add Security on Demand), Munawar Hafiz