Download Evolving Software, Refactoring Philosophy - Lecture Slides | CMSC 433 and more Study notes Programming Languages in PDF only on Docsity!
1
CMSC 433 – Programming Language
Technologies and Paradigms
Spring 2007
Refactoring April 24, 2007 Lots of material taken from Fowler, (^) Refactoring: Improving the Design of Existing Code
Evolving Software
- The requirements of real software often change in waysProblem that cannot be handled by the current design
- Moreover, trying to anticipate changes in the initial implementation can be difficult and costly
- – Redesign as requirements changeSolution (^) Refactor (^) code to accommodate new design 3
Example
double potentialEnergy(double m, double h) Constant(p204) Replace Magic Number with Symbolic (^) { return m * 9.81 * h; }
double potentialEnergy(double m, double h) static final double G = 9.81; becomes... (^) { return m * G * h; }
Some Motivations for This Refactoring
- So we like to give them a name– But why they have those values is not obviousMagic numbers have special values
- Easy to make errorsMagic numbers may be used multiple times
May make a typo when putting in a number
May need to change a number later (more digits of G)
5
• Conventional Wisdom: The Design is Fixed
- Step 2: Build your system– Step 1: Design, design, designSoftware process looks like this:
- You need to communicate your new design with– You need to update your design documents– You might break something in the codeOnce you’re on step 2, don’t change the design! everyone else
What if the Design is Broken?
- When you’re “cleaning up the code,” you’re not adding– Design changes are very expensiveYou’re kind of stuck features
- Very expensive in the long run– Makes code harder to understand and maintain– Makes code harder to changeResult: An inappropriate design 7
Refactoring Philosophy
- Step 1: Make a– So let’s not even pretendIt’s hard to get the design right the first time (^) reasonable (^) design that should work, but...
- Plan for changes
As implementers discover better designs
As your clients change the requirements (!)
But how can we ensure changes are safe?
Refactoring Philosophy (cont’d)
- Follow mechanical patterns (which could be automatedMake all changes small and methodical in some cases) called (^) refactorings , (^) which are semantics-preserving
- Notice: we need fully automated tests for this case– If something breaks, you know what caused it– By rerunning all of your unit testsRetest the system after each change
13
When to Refactor: An Analogy
Unfinished refactoring is like going into debt
payments (extra maintenance costs)Debt is fine as long as you can meet the interest
- [Ward Cunningham]overwhelmedIf there is too much debt, you will be
Barriers to Refactoring
- Clean first,– Mitigated by testingMay introduce errors (^) then (^) add new functionality
- “We pay you to add new features, not to improve the– Producing negative lines of codeCultural issues code!”
If it ain’t broke, don’t fix it 15
Barriers to Refactoring (cont’d)
- E.g., databases that rely on schema detailsTight coupling with implementations
- I.e., you can’t refactor if you don’t control code callers– If others rely on your API, you can’t easily change itPublic interfaces
- It might be hard to see a path from the current design toDesigns that are hard to refactor the new design
- You may be better off starting from scratch
What Code Needs to be Refactored?
- These are called “smells”be addressed with refactoringBad code exhibits certain characteristics that can
Different smells suggest different refactorings
17
Feature Envy
- E.g., invoking lots of get methodsthan the one it is actually inA method seems more interested in a class other
- Move method from one class to anotherMove Method
- Pull out code in one method into a separate methodExtract Method
Move Method
Should other methods also be moved?
What about sub- and superclasses?
What about access control (public, protected)? 19
Extract Method
Are you ever going to reuse this new method?
Local variable scopes?
Extra cost of method invocation? } System.out.println(“amount” + amt);System.out.println(“name” + name);printBanner();void printOwning(double amt) { } printDetails(amt);printBanner();void printOwning(double amt) {} System.out.println(“amount” + amt);System.out.println(“name” + name);void printDetails(double amt) {
Long Method
understand than lots of short ones.A method is too long. Long methods are harder to
Can decompose with Extract Method
- Remove code that assigns a method call to a temporary,Replace Temp with Query and replace references to that temporary with the call
- Use the command pattern to build a “closure”Replace Method with Method Object
25
Duplicated Code
- Use Extract Method to pull it out into a methodthe same classThe same expression used in different places in
- PullUp method into parent– Extract Method in each, thensame superclassThe same expression in two subclasses sharing the
- Extract Class - Break a class that does too many thingsDuplicated code in two unrelated classes into smaller classes
Pull Up Method
matchMight do other refactorings if methods don’t quite
What if doesn’t appear in all subclasses? 27
Extract Class
How do we decide what goes in new class?
Do fields still need to be accessed in orig class?
Long Parameter List
Lots of parameters occlude understanding
- Remove method parameters and instead use some otherReplace Parameter with Method way to get the parameter value (e.g., method call)
- Group parameters that go together into a containerIntroduce Parameter Object object
29
Replace Parameter with Method
discountedPrice can call getDiscount() itself discountedPrice(basePrice, discount);double finalPrice =double discount = getDiscount();double basePrice = num * price; discountedPrice(basePrice);double finalPrice =double basePrice = num * price;
Introduce Parameter Object
31
Divergent Change
- To add a new financial currency, change these four– To add a new database, change these three methodsfor different reasonsOne class is commonly changed in different ways
Suggests maybe this shouldn’t be one object
Apply Extract Class to group together variations
Shotgun Surgery
- Opposite of Divergent Changeof little changes to different classesEvery time I make change X, I have to make lots
Move Method
- Switch field from one class to anotherMove Field
- A class isn’t doing very much, so inline its features intoInline Class its users (reverse of Extract Class)
37
Other Bad Smells (cont’d)
- If code is heavily commented, eitherComments!
It’s very tricky code (e.g., a hard algorithm), or
The design is bad, and you’re trying to explain it
- “When you feel the need to write a comment, first try to superfluous.”refactor the code so that any comment becomes
Refactoring with Tools
Many refactorings can be performed automatically
mistakeThis reduces the possibility of making a silly
- http://www.eclipse.orgEclipse provides support for refactoring in Java 39
More information
Textbook: Refactoring by M. Fowler
- http://www.refactoring.com/catalog/index.htmlCatalog of refactorings:
- http://industriallogic.com/xp/refactoring/Refactoring to patterns