390 likes | 640 Views
Lesson Three: Constants and Variables. Process 1. Review scope of all constants 2. Review scope of all variables 3. Adjust any gets/sets due to reviews 4. Apply refactorings. 1. Review the scope of all constants 2. Review the scope of all variables 3. Adjust code to limit scope.
E N D
Process1. Review scope of all constants2. Review scope of all variables3. Adjust any gets/sets due to reviews4. Apply refactorings
1. Review the scope of all constants2. Review the scope of all variables3. Adjust code to limit scope • 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.
3. Adjust code to limit scope 2 1 3 Investigate variables, parameters, and methods to see if they can be local or need to be uplifted to later evaluate their partitioning into classes.
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
Apply Refactorings Replace Magic Number with Symbolic ConstantIntroduce Explaining VariableSplit Temporary Variable Replace Temp with QuerySeparate Query from Modifier ****Replace Array with Object *****
Replace Magic Number with Symbolic Constant 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: Motivation: Magic numbers are numbers with special values that usually are not obvious. Add a constant to store the values of these magic numbers.
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 potentialEnergy static Final double GRAVITATIONAL_CONSTANT * 9.81; Should be
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.
Replace Magic Number with Symbolic Constant: static final int ENDINGSTATE = (1 << 9) - 1; BECOMES static 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 1 static final int lastCell = 8; // last cell at row 3, col 3 for (int i = firstCell ; i <= lastCell ; i++) { \
Replace Magic Number with Symbolic Constant: int bestmove = -1; if (bestmove == -1) { if (bestmove != -1) { return -1; // return no more moves BECOMES static final int bestMoveNotFound = -1; //indicating best move not found int bestmove = bestmoveNotFound; if (bestmove == bestMoveNotFound) { if (bestmove != bestMoveNotFound) { return bestMoveNotFound; // return no more moves
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 col int row = (y * 3) / d.height; // determine the row BECOMES static 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 col int row = (y * NUMBER_OF_ROWS) / d.height; // determine the row
4. Introduce Explaining Variable 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: 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.
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 …..}
4. Introduce Explaining Variable: Mechanics: declare a final temp variable set it to the result portion of the expression compile and test
5. Split Temporary 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: 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.
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
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 getDistanceTravelled CAN YOU THINK OF OTHER REFACTORING?
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
3. Replace Temp with Query 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: Motivation: Methods with many temps tend to be long. Replacing the temp variable with a query method makes the code cleaner for further refactoring.
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
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; }
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
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
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
3. Replace Temp with Query: int best = bestMove(computerStatus, userStatus); setComputerStatus (computerStatus | 1 << best); BECOMES setComputerStatus (computerStatus | 1 << bestMove(computerStatus, userStatus));
Replace Array with Object 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: 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.
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.
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.
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.
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.
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