370 likes | 793 Views
Software Restructuring(Refactoring). Giriprasad Sridhara CISC 879 Spring 2007 May 10 2007. Road Map. In this class Basics of refactoring Relation with Performance optimization Compiler optimization Unit Tests Identifying refactoring opportunities Refactoring catalog. Road Map.
E N D
Software Restructuring(Refactoring) Giriprasad Sridhara CISC 879 Spring 2007 May 10 2007
Road Map In this class Basics of refactoring Relation with Performance optimization Compiler optimization Unit Tests Identifying refactoring opportunities Refactoring catalog
Road Map Learning cannot be vicarious So a small refactoring game! Challenges in refactoring When to refactor? Benefits of refactoring Drawbacks of refactoring Next class Demo with Eclipse Demo with Visual Studio
Road Map Eclipse plug-in to Do your own refactoring Examples of refactorings In real world code JHotDraw Struts Eclipse UI component
Refactoring • Modification of code so as to: • Improve internal structure • Preserve external functionality • Not necessarily to • Fix bugs OR • Add new functionality • But to improve code understandability
Phases of software development • Waterfall model (?) • Analysis • Design • Coding • Testing (unit and integration) • Maintenance • Which is the most expensive phase (?) • Maintenance • Consumes 60-90% of the overall resources!
Software Maintenance • Maintenance(?) • making corrections to fix bugs • making changes to incorporate new features • Consumes maximum resources in software development life cycle • Time and People Money (Millions of dollars!) • Maintenance leitmotif • Understanding existing code AND • Making changes.
Refactoring • If it ain’t broke, don’t fix it! • So Why Refactor? (?) • Helps in software maintenance • As it makes the code • easier to understand • hence easier to make changes.
Behavior preservation • We keep saying refactoring preserves external behavior • But, what exactly is meant by it? (?) • Opdyke defined it as: • For the same set of input values, • The set of output values should be the same • before and after the refactoring. • Is this definition sufficient? (?) • For real time systems etc • We can add the following: • Performance of the program • i.e. execution time. • Memory requirements
Refactoring (What constitutes it and what does not?) • Consider an example: • We are searching for an item in a huge ordered list of items. • Suppose the program uses the recursive version of binary search for this task. • Replacing the binary search with the simpler linear search • IS it refactoring? (?) • NO! • This is because the performance of the program in the worst case has degenerated.
Refactoring (What constitutes it and what does not?) • Replacing the recursive version of binary search with an iterative version • Is it refactoring? (?) • YES • If the developers are more comfortable with non recursive implementations. • Replacing our own implementation of binary search with a proven available implementation from a library (like C++ STL) • Is it refactoring? (?) • YES • Because the maintenance effort is reduced.
Refactoring (What constitutes it and what does not?) • Conclusion: • Simply replacing a more complicated piece of code with supposedly simpler code • Say, replacing a more complex algorithm with a simple algorithm • is NOT refactoring.
Example (Before refactoring) void CnvrtTemp() { // Get the user input cout << "Please enter the temperature " << endl; double d1 =0; cin >> d1; // Convert Fahrenheit to Celsius double d2 = (d1 - 32) * 5.0/9.0; cout << "Converted temperature is " << d2 << endl; }
Example (After refactoring) void ConvertTemperature() { double Fahrenheit = GetUserInput(); cout << "Converted temperature is " << ConvertFahrenheitToCelsius(Fahrenheit) << endl; } double GetUserInput() { cout << "Please enter the temperature " << endl; double Fahrenheit =0; cin >> Fahrenheit; return Fahrenheit; } double ConvertFahrenheitToCelsius(double Fahrenheit) { const int OFFSET = 32; const double CONVERSION_FACTOR = 5.0/9; double Celsius = (Fahrenheit - OFFSET) * CONVERSION_FACTOR; return Celsius; }
Refactoring vs Performance Optimization • Performance optimization (?) • Changes done to code to improve the performance • i.e. execution time (and memory consumption) • May make the code harder to comprehend, while improving the performance. • For example, • Simple versus more complicated but performant algorithm. • Insertion sort with Quick Sort • Due to this, • the code may have become harder to understand and modify, • but it is not the primary concern of performance optimization. • Refactoring on the other hand • does not change the observable behavior at all, • tries to improve the internal structure so that • The code is easier to understand and modify later on.
Refactoring vs Compiler Optimization • Compiler optimization (?) • Changes done by the compiler • To optimize the code • to improve the performance • i.e. execution time (and memory consumption) • Changes done at the back-end i.e. Intermediate Representation or Machine Level • Go to example in Eclipse … • Refactoring • Changes done at the front end i.e. source code level.
Refactoring and Unit Tests • Relationship between refactoring and Unit tests (?) • Refactoring is strongly dependent on having a good suite of unit tests • With the unit tests, we can refactor • Then run the automated tests • To verify that the behaviour is indeed preserved. • Without good unit tests, • developers may shy away from refactoring • Due to the fear that they may break something.
Identifying refactoring opportunities (Code smell) • By bad smells in code • Duplicated code • Poorly named entities • Long Method • Large (God) class • Long parameter list • Comments • Switch statements
Identifying refactoring opportunities (Code smell) • Data clumps • Middle man • Inappropriate intimacy • Primitive obsession • Lazy class • Message chains • Show example in Eclipse …
Classification of Refactorings • Extract Method • Rename Method • Replace magic number with symbolic constant • Pull Up Method • Form Template Method • Remove Parameter
Classification of Refactorings • Eliminate unused return value • Replace conditional with polymorphism • Introduce explaining variable • Move Method • Replace error code with exception • Encapsulate field (no public variables) • Consolidate duplicate conditional fragments • Show example in Eclipse …
Refactoring Game • A small example to illustrate refactoring • Detect smells • Identify the applied refactorings • Please see the hand-out sheets one by one • Subsequent sheets have the answer! • Should take about 5 minutes. • Does NOT count towards your final grade!
Some other Refactorings • Discuss only if time permits • Encapsulate collection • Don’t return vector or list, return iterator • Replace inheritance with delegation • Stack derived from vector in Java 1.1 • Liskov Substitution Principle
Challenges in Refactoring • What do you think are the major challenges in refactoring research? (?) • Which code to refactor? • i.e. identify the bad smell. • Depends on human intuition • Very subjective • CCFinder, DAIKON • OK, we found that we could apply some refactorings to code. • Does the order of applying these matter? (?) • Are there dependencies between a set of refactorings? • Tom Mens et al AGG
Challenges in Refactoring • Say, we are looking at a version control system and difference between 2 versions. • Which of the code changes are due to refactorings? • Why all would code have changed? (?) • Due to bug fix • Due to new feature addition • Due to genuine refactoring • Weissberger et al (signature and clone based) • Correctness of refactored code • JUNGL
Challenges in Refactoring • Reconciling test cases • Code changes due to refactoring • How to identify new test cases • Say, for, Extract Method • How to identify redundant test cases • Say, we removed, duplicated code. • Reconciling with other artifacts • Design documents…
A time to refactor • When should we refactor? (?) • Commonly accepted wisdom (heuristics): • When we add new functionality • When we fix a bug • When we do a code review.
Benefits of refactoring • Software design improvement: (How does it help?) • A primary casualty of bug fixes and feature enhancements in software, is • design of the software • By refactoring, we can ensure that the design does not decay. • Making software easier to understand: (?) • As has been stated previously, this is the primary aim and benefit of refactoring. • Finding bugs: (?) • As we refactor code, we would be looking at it deeply to find refactoring opportunities. • During this process we could also uncover dormant bugs in the code and fix them.
Refactoring problems and limitations • What do you think are problems and limitations of refactoring? (?) • Databases: • Many applications have code that is tightly coupled with an underlying database schema. • The code and the database are usually managed by different people. • Due to these factors, it is difficult to refactor enterprise database applications, • But, they constitute a substantial chunk of the software market • So we need effective refactoring techniques here.
Refactoring problems and limitations • Interfaces: • Refactoring techniques like RenameMethod • change a published interface. • This problem can occur when we want to refactor library code • but we are hampered by the fact that some portions of it are published interfaces • And thus cannot be refactored so easily,(Why?) • Because that would break the client code.
Source of this presentation • Refactoring Book – Martin Fowler • Bill Opdyke – Ph.D Thesis • Don Roberts – Ph.D Thesis • Tom Mens – Refactoring survey • Wikipedia
Want to do research in refactoring? • Check out the following: • University of Illinois, Urbana-Champaign • Ralph Johnson • Tom Mens et al
Questions? Thank you.