Refactoring Constants and Variables Lesson Three: Constants and Variables.
-
Upload
verity-hodges -
Category
Documents
-
view
259 -
download
0
description
Transcript of Refactoring Constants and Variables Lesson Three: Constants and Variables.
RefactoringConstants and Variables
Lesson Three: Constants and Variables
RefactoringConstants and Variables
Process1. Review scope of all constants2. Review scope of all variables3. Adjust any gets/sets due to reviews4. Apply refactorings
RefactoringConstants and Variables
1. Review the scope of all constants2. Review the scope of all variables3. Adjust code to limit scope
A. Review all the constants and variables to make sure they are not MORE global in scope than necessary. Downcast any that are too broad in scope. Adjust gets and sets to adapt to new or modified scope.
RefactoringConstants and Variables
3. Adjust code to limit scope
Investigate variables, parameters, and methods to see if they can be local or need to be uplifted to later evaluate their partitioning into classes.
setW
inni
ngS
tate
best
Mov
e
lega
lUse
rMov
e
lega
lCom
pute
rMov
e
gam
eSta
tus
rese
tFirs
t
mou
seR
elea
sed
init
pain
t
const int ENDINGSTATE r r rconst int LOSE r rconst int CONTINUE r rconst int STALEMATE r rconst int WIN r r
var int computerStatus p p p ps p s gs g gvar Image userImage gvar boolean computerFirst p sg gvar arrayint mostStrategicMove[] rvar Image computerImage gvar int userStatus p p ps p p gs g g
var arrayint winningState[] u r r
12
3
RefactoringConstants and Variables
3. Adjust code to limit scope
private static int mostStrategicMove[] = {4,0,2,6,8,1,3,5,7};
// square order of importance
BECOMES
int mostStrategicMove[] = {4,0,2,6,8,1,3,5,7};// square order of importance
// in the method bestMove
RefactoringConstants and Variables
4. Apply Refactorings
Replace Magic Number with Symbolic ConstantIntroduce Explaining VariableSplit Temporary Variable Replace Temp with QuerySeparate Query from Modifier ****Replace Array with Object *****
RefactoringConstants and Variables
Summary:
You have a literal number with a particular meaning
Create a constant, name it after the meaning, and replace the number with it.
Replace Magic Number with Symbolic Constant
RefactoringConstants and Variables
Replace Magic Number with Symbolic Constant: Motivation:
Magic numbers are numbers with special values that usually are not obvious.
Add a constant to store the values of these magic numbers.
RefactoringConstants and Variables
Replace Magic Number with Symbolic Constant: Example:
double potentialEnergy (double mass, double height) { return mass * 9.81 * height; }// end potential Energy
double potentialEnergy (double mass, double height { return mass * GRAVITATIONAL_CONSTANT * height; }// end potentialEnergystatic Final double GRAVITATIONAL_CONSTANT * 9.81;
Should be
RefactoringConstants and Variables
Replace Magic Number with Symbolic Constant: Mechanics:
declare a constant and set to magic number
find occurrences of magic number
if magic matches constant usage – use constant
when all magic numbers changed
compile and test.
RefactoringConstants and Variables
Replace Magic Number with Symbolic Constant: static final int ENDINGSTATE = (1 << 9) - 1; BECOMESstatic final int NINE_SHIFTING_BITS = 9;static final int ENDINGSTATE = (1 << NINE_SHIFTING_BITS) - 1;
for (int i = 0 ; i < 9 ; i++) { // for square = 0 to < 9 BECOMES
static final int firstCell = 0; // first cell at row 1 col 1static final int lastCell = 8; // last cell at row 3, col 3
for (int i = firstCell ; i <= lastCell ; i++) { \
RefactoringConstants and Variables
Replace Magic Number with Symbolic Constant: int bestmove = -1;if (bestmove == -1) { if (bestmove != -1) { return -1; // return no more moves
BECOMESstatic final int bestMoveNotFound = -1; //indicating best move not foundint bestmove = bestmoveNotFound;if (bestmove == bestMoveNotFound) { if (bestmove != bestMoveNotFound) { return bestMoveNotFound; // return no more moves
RefactoringConstants and Variables
Replace Magic Number with Symbolic Constant: for (int row = 0 ; row < 3 ; row++) { for (int col = 0 ; col < 3 ; col++, i++) {int col = (x * 3) / d.width;// determine colint row = (y * 3) / d.height; // determine the row
BECOMESstatic final int NUMBER_OF_COLUMNS = 3;static final int NUMBER_OF_ROWS = 3;for (int row = 0 ; row < NUMBER_OF_ROWS ; row++) { for (int col = 0 ; col < NUMBER_OF_COLUMNS ; col++, i++) {int col = (x * NUMBER_OF_COLUMNS) / d.width;// determine colint row = (y * NUMBER_OF_ROWS) / d.height; // determine the row
RefactoringConstants and Variables
Summary:
You have a complicated expression.
Put the result of the expression in a temp with a name that explains the purpose.
4. Introduce Explaining Variable
RefactoringConstants and Variables
4. Introduce Explaining Variable: Motivation:
Complex code that requires many lines of code but could more easily be explained with some variable name that helps to explain the code semantics.
RefactoringConstants and Variables
4. Introduce Explaining Variable: Example: If ( (platform.toUpperCase().indexOf(“MAC”) > -1) && (browser.toUpperCase().indexOf(“IE”) > -1) && wasInitialized () && resize >0) { ….. other code …..}
goes to
final boolean isMacOs = platform.toUpperCase().indexOf(“MAC”) > -1;final boolean isIEBrowser = platform.toUpperCase().indexOf(“IE”) > -1;final boolean wasResized = resize >0;
If (isMacOs && isIEBrowser && wasInitialized () && was Resized) { ….. other code …..}
RefactoringConstants and Variables
4. Introduce Explaining Variable: Mechanics:
declare a final temp variable
set it to the result portion of the expression
compile and test
RefactoringConstants and Variables
Summary:
You have one temp assigned to more than once and it is not a loop variable.
Make a new temp for each assignment
5. Split Temporary Variables
RefactoringConstants and Variables
5. Split Temporary Variables:Motivation:
Looping variables (control variables of a loop) or accumulator variables (summing variables) may have the need for assignments more than once. Other variables should not be assigned to more than once.
Investigation of greater than one assignments to the same variable may yield variables that are actually used for different semantics.
RefactoringConstants and Variables
5. Split Temporary Variables: Example: double getDistanceTravelled (int time) { double result; double acc = _primaryForce / _mass; // initial value of acceleration of first force int primaryTime = Math.min(time, _delay); result = 0.5 * acc * primaryTime * primaryTime; int secondaryTime = time - _delay; if (secondaryTime > 0) { double primaryVel = acc * _delay; acc = (_primaryForce * _secondaryForce) / _mass; // final value of acceleration result += primaryVel * secondaryTime + 0.5 *acc * secondaryTime * secondaryTime; } // end if return result;} // end getDistanceTravelled
RefactoringConstants and Variables
5. Split Temporary Variables: Example: double getDistanceTravelled (int time) { double result; double primaryacc = _primaryForce / _mass; // initial value of acceleration of first force int primaryTime = Math.min(time, _delay); result = 0.5 * primaryacc * primaryTime * primaryTime; int secondaryTime = time - _delay; if (secondaryTime > 0) { double primaryVel = acc * _delay; double acc = (_primaryForce * _secondaryForce) / _mass; // final value of acceleration result += primaryVel * secondaryTime + 0.5 *acc * secondaryTime * secondaryTime; } // end if return result;} // end getDistanceTravelledCAN YOU THINK OF OTHER REFACTORING?
RefactoringConstants and Variables
5. Split Temporary Variables:Mechanics:
find the variables assigned to more than once
change the name for each different assignments
change references
compile and test
RefactoringConstants and Variables
Summary:
You are using a temporary variable to hold the result of an expression.
Extract the expression into a method Replace all references to the temp with the expression.
3. Replace Temp with Query
RefactoringConstants and Variables
3. Replace Temp with Query: Motivation:
Methods with many temps tend to be long.
Replacing the temp variable with a query method makes the code cleaner for further refactoring.
RefactoringConstants and Variables
3. Replace Temp with Query: Example:
double getPrice(){ int basePrice = _quanity * itemPrice; double discountFactor; if (basePrice > 1000) discountFactor = 0.95 else discountFactor = 0.98; return basePrice *discountFactor;}// end getPrice
RefactoringConstants and Variables
3. Replace Temp with Query: Example:
double getPrice(){ int basePrice = _quanity * itemPrice; double discountFactor; if (basePrice() > 1000) discountFactor = 0.95 else discountFactor = 0.98; return basePrice() *discountFactor;}// end getPrice
private int basePrice () { return quanity * itemPrice; }
RefactoringConstants and Variables
3. Replace Temp with Query: Example:
double getPrice(){ double discountFactor = discountFactor(); if (basePrice() > 1000) discountFactor = 0.95 else discountFactor = 0.98; return basePrice() *discountFactor;}// end getPrice
private double discountFactor () { if (basePrice() > 1000) return 0.95; else return 0.98; } // end discountFactor
Extract Method
RefactoringConstants and Variables
3. Replace Temp with Query: Example:
double getPrice(){ double discountFactor = discountFactor(); return basePrice() *discountFactor;}// end getPrice
private double discountFactor () { if (basePrice() > 1000) return 0.95; else return 0.98; } // end discountFactor
private int basePrice () { return quanity * itemPrice; }
Can I do more?
Replace Temp with Query
RefactoringConstants and Variables
3. Replace Temp with Query: Mechanics:
declare the temp as final to check references
compile to test
extract the right hand side as a method body
if a loop take entire loop
name and construct the method
replace the temp with the call
RefactoringConstants and Variables
3. Replace Temp with Query:
int best = bestMove(computerStatus, userStatus);setComputerStatus (computerStatus | 1 << best);
BECOMESsetComputerStatus
(computerStatus | 1 << bestMove(computerStatus, userStatus));
RefactoringConstants and Variables
Summary:
You have an array in which certain elements mean different things.
Replace the array with an object that has a field for each element.
Replace Array with Object
RefactoringConstants and Variables
Replace Array with Object: Motivation:
You have a collection of objects BUT those objects are not similar. Arrays should not be composed of objects not similar.
Replace the dissimilar array with an object.
RefactoringConstants and Variables
Replace Array with Object: Example:
String[] row = new String[3];
row [0] = “Liverpool”; row [1] = ’13”; String name = row(0); int wins = Integer.parseInt(row(1));
The original array.
Code using the array.
RefactoringConstants and Variables
Replace Array with Object: Example:
class Performance {} row._data[0] = “Liverpool”; row._data [1] = ’13”; String name = row._data(0); int wins = Integer.parseInt(row._data(1));
Create and access the array.
RefactoringConstants and Variables
Replace Array with Object: Example:
class Performance {} public String getName() { return _data[0]; public void setName (String arg) {_data[0] = arg; } String name = row.getName(); int wins = Integer.parseInt(row._data[1]);
private String [].data = new String[3];
Add getters and setters.
Make the array private.
RefactoringConstants and Variables
Replace Array with Object: Example:
class Performance {} public String getName() { return _name; public void setName (String arg) {_name = arg; } private String _name;
Change the interface and replace array internally by adding a field for each array element and changing accessors.
RefactoringConstants and Variables
Replace Array with Object: Mechanics:
create a new class for the array
change all users of the array to use the class
add getters and setters for each element
for each element, create a field
delete the array
compile and test
RefactoringConstants and Variables
Replace Array with Object: