Transcript of Refactoring tutorial
- 1. Tutorial SEEG
- 2.
- 3. 3 Confidential 12/13/2011
- 4. : ? Bad Code Good Code
- 5. :: Bad Code Broken Window Theory
- 6. , . Tool Refactoring public int getCharge(int quantity) {
public int getCharge(int quantity) { int charge = 0; int charge =
0; Date now = new Date(); Date now = new Date(); // Summer if
(isSummerTime(now)) { if (now.before(SUMMER_START)||
now.after(SUMMER_END)) { charge = quantity * WINTER_RATE + charge =
quantity * WINTER_RATE + WINTER_SERVICEC_CHARGE;
WINTER_SERVICEC_CHARGE; } else { } else { charge = quantity *
SUMMER_RATE; charge = quantity * SUMMER_RATE; } } return charge;
return charge } } private boolean isSummerTime(Date now) { return
now.before(SUMMER_START) || now.after(SUMMER_END); }
- 7. : ? ? ?
- 8. : ? , , . ,
- 9. : (10~30), .
- 10. : Publish Ex) Android Service.onStart() I/F Delegation :
API Publish Throw Delegation : Super Exception , ?
- 11. : , . With design I can think very fast, but my thinking is
full of little holes Alistair Cockburn Role , . . . Complexity
- 12. : . . , .
- 13. () Switch
- 14. : Obvious Copy & Paste Unobvious (ex, , ) ExtractMethod
ExtractMethod -> Pull Up Field or Pull Up Method -> Form
Template Method
- 15. : . People often make assumptions based on the object names
alone Word Cunningham Rename Method Rename Field Rename Constants
Tip ! add, register, put, create -> add
- 16. : PriceCalculator Product .. calculate() .. getQuantity()
bmethod() getDiscountRate() Move Method
- 17. : Class A Class B (private .. .. ) amethod() xmethod()
bmethod() ymethod() Move Method Change Bidirectional Reference to
Unidirectional Extract Hierarchy-> Hide Delegate
- 18. : Extract Method Rename Method Introduce Assertion
- 19. : . Extract Method .
- 20. : . Replace Parameter with Method Object Preserve Whole
Object Introduce Parameter Object Caller Callee
- 21. : Switch Switch , Switch OOP Switch Switch Step 1: Extract
Method Step 2: Move Method Step 3: Replace Type Code with Subclass
or Replace Type Code with State/Strategy Switch 21 Confidential
12/13/2011
- 22. . , . . 22 Confidential 12/13/2011
- 23. 23 Confidential 12/13/2011
- 24. 24 Confidential 12/13/2011
- 25. : .
- 26. : -> - -> Extract Method -> Rename Method ->
Introduce Assertion
- 27. : - package ch3;public class Matcher { public Matcher() { }
[Rename Method] // . public boolean compare(int[] expected, int[]
actual, int clipLimit, int delta) { // clipLimit . [Extract Method]
for (int i = 0; i < actual.length; i++) if (actual[i] >
clipLimit) actual[i] = clipLimit; // . [Extract Method] if
(actual.length != expected.length) return false; // delta . for
(int i = 0; i < actual.length; i++) if (Math.abs(expected[i] -
actual[i]) > delta) return false; return true; }} 27
Confidential 12/13/2011
- 28. Refactoring : Extract Method .{ { // clipLimit . //
clipLimit . for (int i = 0; i < actual.length; i++) for (int i =
0; i < actual.length; i++) if (actual[i] > clipLimit) if
(actual[i] > clipLimit) actual[i] = clipLimit; actual[i] =
clipLimit; }} private void cutLargeValues(int[] values, int limit)
{ for (int i = 0; i < values.length; i++) if (valuesl[i] >
limit) values [i] = limit; } 28 Confidential 12/13/2011
- 29. Refactoring : Rename Method . !! 29 Confidential
12/13/2011
- 30. Refactoring : Introduce Assertion assertion double
getExpenseLimit() { double getExpenseLimit() { // should have
either expense limit or a primary project return Assert.isTrue
(_expenseLimit != NULL_EXPENSE || _primaryProject != null);
(_expenseLimit != NULL_EXPENSE) ? return (_expenseLimit !=
NULL_EXPENSE) ? _expenseLimit: _expenseLimit:
_primaryProject.getMemberExpenseLimit();
_primaryProject.getMemberExpenseLimit();} } Assertion . Assertion
Assertion . Assertion Assertion Extract Method 30 Confidential
12/13/2011
- 31. : - . , -> , , ? -> ExtractMethod
- 32. : -> Extract Class -> Extract Subclass -> Extract
Interface
- 33. Refactoring : Extract Class , , ! 33 Confidential
12/13/2011
- 34. Refactoring : Extract Class 34 Confidential 12/13/2011
- 35. Refactoring : Extract Subclass JobItem +getTotalPrice()
JobItem +getUnitPrice() +getTotalPrice() +getUnitPrice()
+getEmployee() LaborItem +getUnitPrice() +getEmployee() Extract
Class Extract Subclass Extract Subclass (variation) . . Extract
Class (variation) . , . 35 Confidential 12/13/2011
- 36. Refactoring : Extract Interface , Billable +getRate()
Employee +hasSpecialSkill() +getRate() +hasSpecialSkill()
+getName() Employee +getDepartment() +getRate() +hasSpecialSkill()
+getName() +getDepartment() Extract Superclass Extract Interface .
36 Confidential 12/13/2011
- 37. : - Coupling . -> Replace Parameter with Method ->
Preserve Whole Object -> Introduce Parameter Object
Coupling
- 38. Refactoring : Replace Parameter with Method , . , Int
basePrice = quantity * itemPrice; int basePrice = quantity *
itemPrice;discountLevel = getDiscountLevel(); double finalPrice =
getDiscountedPrice(basePrice);double finalPrice =
getDiscountedPrice(basePrice, discountLevel);
- 39. Refactoring : Preserve Whole Object Int low =
daysTempRange().getLow();Int high = daysTempRange().getHigh();
withinPlan = plan.withinRange(daysTempRange());withinPlan =
plain.withinRange(low, high) , ,
- 40. Refactoring : Introduce Parameter Object -> -> ,
- 41. 41 Confidential 12/13/2011
- 42. : . : , : , , (Type Embedded in Name) (Uncommunicative
Name) (Inconsistent Name)
- 43. : ex) addCourse(Course c) ex) iCount -> , -> ->
Rename Method, Rename Field, Rename Constant , .
- 44. : Rename Method, Rename Field, Rename Constant * , .
- 45. : . Ex) add(), store(), put(), place(), register() . ->
Rename Method, Rename Field, Rename Constant , .
- 46. 46 Confidential 12/13/2011
- 47. 47 Confidential 12/13/2011
- 48. : & , , , , , , . . . . -> Collapse Hierarchy ->
Inline Class -> Inline Method -> -> Remove Parameter , , ,
.48 Confidential 12/13/2011
- 49. Refactoring : Inline Class & Collapse Hierarchy* Inline
Class .* Collapse Hierarchy LoginContext LoginModule
+authenticate() Collapse Hierarchy IDPasswordLoginModule
KerberosLoginModule x x FingerPrintLoginModule +authenticate()
+authenticate() +authenticate() 49 Confidential 12/13/2011
- 50. Refactoring : Inline Method .int getRating() { int
getRating() { return (moreThanFiveLateDeliveries()) ? 2 : 1; return
(_numberOfLateDeliveries > 5) ? 2 : 1;} }boolean
moreThanFiveLateDeliveries() { return _numberOfLateDeliveries >
5;} Indirection Refactoring Refactoring 50 Confidential
12/13/2011
- 51. 51 Confidential 12/13/2011
- 52. : . . . . (Magic Number) (Duplicated Code) (Alternative
Classes with Different Interfaces)
- 53. : . Replace Magic Number with Symbolic Constant ,
- 54. : public void analyze(File file) throws
FileNotFoundException { private static final int INDEX_TYPE = 0;
BufferedReader reader = new BufferedReader(new FileReader(file));
private static final int INDEX_TIME = 1; private static final int
INDEX_URL = 2; try { private static final int INDEX_IPADRESS = 3;
String aLine = reader.readLine(); public void analyze(File file)
throws FileNotFoundException { while (aLine != null) {
BufferedReader reader = new BufferedReader(new FileReader(file));
// type, time, id, ip address String[] record =
aLine.split(SEPERATOR); try { String aLine = reader.readLine();
AccessLog aLog = new AccessLog(); aLog.setType(record[0]); while
(aLine != null) { aLog.setTime(record[1]); // type, time, id, ip
address aLog.setUrl(record[2]); String[] record =
aLine.split(SEPERATOR); aLog.setIpAddress(record[3]); Replace Magic
Number with Symbolic Constant AccessLog aLog = new AccessLog();
aLine = reader.readLine(); aLog.setType(record[INDEX_TYPE]); }
aLog.setTime(record[INDEX_TIME]); } catch (IOException e) {
aLog.setUrl(record[INDEX_URL]); e.printStackTrace();
aLog.setIpAddress(record[INDEX_IPADRESS]); } finally { // .. aLine
= reader.readLine(); } }} } catch (IOException e) {
e.printStackTrace(); } finally { // .. } } , 54 Confidential
12/13/2011
- 55. : . . Copy & Paste -> Extract Method -> Extract
Method -> Pull Up Field or Pull Up Method -> Form Template
Method -> Extract Class , -> Substitute Algorithm .
- 56. : 56 Confidential 12/13/2011
- 57. : , -> Rename Method -> Move Method, Add Parameter,
Parameterize Method -> Extract Superclass -> .
- 58. 58 Confidential 12/13/2011
- 59. : ? Boolean (Complicated Boolean Expression) (Simulated
Inheritance) 59 Confidential 12/13/2011
- 60. : Boolean , , ) public boolean isAcceptable1(int score, int
income, boolean authorized) { if (!((score > 700) || ((income
>= 40000) && (income 500)) || (income > 100000)) )
return false; else return true; } DeMorgans Law)public boolean
isAcceptable2(int score, int income, boolean authorized) { if
(((score 100000) || !authorized || (score = 40000) &&
(income 500)) || (income > 100000)) ) return false; else return
true; } Introduce Explaining Variable) public boolean
isAcceptable3(int score, int income, boolean authorized) { boolean
hasMidRangeIncome = (income >= 40000) && (income
100000;; boolean hasHighScore = score > 700; if (!( hasHighScore
|| (hasMidRangeIncome && authorized && (score >
500)) || hasHighIncome) ) return false; else return true; } 61
Confidential 12/13/2011
- 62. Refactoring : Introduce Explaining Variable & DeMorgans
LawIntroduce Explaining Variable) public boolean isAcceptable3(int
score, int income, boolean authorized) { boolean hasMidRangeIncome
= (income >= 40000) && (income 100000;; boolean
hasHighScore = score > 700; if (!( hasHighScore ||
(hasMidRangeIncome && authorized && (score >
500)) || hasHighIncome) ) return false; else return true; }
Introduce Explaining Variable) & DeMorgans Law public boolean
isAcceptable4(int score, int income, boolean authorized) { boolean
hasMidRangeIncome = (income >= 40000) && (income
100000;; boolean hasHighScore = score > 700; if (!hasHighScore
&& (!hasMidRangeIncome || !authorized || !(score > 500))
&& !hasHighIncome) return false; else return true; } 62
Confidential 12/13/2011
- 63. Refactoring : Decompose Conditional) public boolean
isAcceptable1(int score, int income, boolean authorized) { if
(!((score > 700) || ((income >= 40000) && (income
500)) || (income > 100000)) ) return false; else return true; }
Decompose Conditional) public boolean isAcceptable5(int score, int
income, boolean authorized) { if (!(isHighScore(score) || (
isMidRangeIncome(income) && authorized &&
isMidScore(score)) || isHighIncome(income)) ) return false; else
return true; } 63 Confidential 12/13/2011
- 64. Refactoring : Decompose Conditional) public boolean
isAcceptable5(int score, int income, boolean authorized) { if
(!(isHighScore(score) || ( isMidRangeIncome(income) &&
authorized && isMidScore(score)) || isHighIncome(income)) )
return false; else return true; } ) public boolean
isAcceptable6(int score, int income, boolean authorized) { if
(isHighScore(score) || ( isMidRangeIncome(income) &&
authorized && isMidScore(score)) || isHighIncome(income) )
return true; else return false; } 64 Confidential 12/13/2011
- 65. Refactoring : Consolidate Conditional Expression ) public
boolean isAcceptable1(int score, int income, boolean authorized) {
if (!((score > 700) public|| ((income >= 40000) &&
(income 500)) { || (income > 100000)) ) ifreturn false;
(isHighScore(score) else|| ( isMidRangeIncome(income) &&
authorized && isMidScore(score)) || isHighIncome(income)
return true; } ) return true; else return false; } Consolidate
Conditional ExpressionConsolidate Conditional Expression) public
boolean isAcceptable8(int score, int income, boolean authorized) {
if (isHighScore(score) || isHighIncome(income)) // return true; if
(isMidRangeIncome(income) && authorized &&
isMidScore(score)) return true; else Refactoring return false; } -
- - 65 Confidential 12/13/2011
- 66. Boolean 66 Confidential 12/13/2011
- 67. : public class Employee { private int type; private static
final int ENGINEER = 0; 1 private static final int SALESMAN = 1;
private static final int MANAGER = 2; public Employee(int type) {
this.type = type; Type } Replace Type Code with public int
calculatePayment() { switch (type) { case ENGINEER: return
monthlySalary; State/Strategy case SALESMAN: return monthlySalary +
commission; case MANAGER: return monthlySalary + bonus; Replace
Type Code with default: throw new RuntimeException("Incorrect
Employee"); Subclass }} public String getJobTitle() { 2 switch
(type) { case ENGINEER: Replace Conditional with return "Engineer";
case SALESMAN: Class return "Salesman"; case MANAGER: return
"Manager"; default: throw new RuntimeException("Incorrect
Employee"); } }} 67 Confidential 12/13/2011
- 68. Boolean 68 Confidential 12/13/2011
- 69. 69 Confidential 12/13/2011
- 70. 70 Confidential 12/13/2011
- 71. : Book Book height title genre category width author weight
price getDiscount() getRequiredDeliveryRoom() content Book , , 71
Confidential 12/13/2011
- 72. : ->Replace Data Value with Object -> : Replace Type
Code with Class : Replace Array with Object 72 Confidential
12/13/2011
- 73. Refactoring : Replace Data with Object User +firstName:
String +lastName: String Order Customer Replace Data
with+orderNumber: String Object Order +firstName:
String+customeFirstNamer: String 1 1 +lastName:
String+customerLastName: String +orderNumber+price:
float+addressState: String Address+addressCity: String
+state+addressStreet: String +city+addressZipCode1: String
+zipCode1+addressZipCode 2: String 1 1 +zipCode2+telAreaCode:
String+telNumber: String +getDeliveryCost() home Contact office
+areaCode +number 73 Confidential 12/13/2011
- 74. Refactoring : Replace Array with Object String[] row = new
String[3]; Performance row = new Performance(); row [0] =
"Liverpool"; row.setName("Liverpool"); row [1] = "15";
row.setWins("15"); 74 Confidential 12/13/2011
- 75. : public field getter/setter 1- : Encapsulate Field 2- :
Remove Setting Method 3-Collection : Encapsulate Collection 4- :
Extract Method and Move Method 5- , , public , getter/setter 75
Confidential 12/13/2011
- 76. Refactoring : Encapsulate Collection Collection get/set
(read-only view) , add/remove Collection (get) Collection .
Collection (set) Collection Collection . 76 Confidential
12/13/2011
- 77. Encapsulate Collection 77 Confidential 12/13/2011
- 78. 78 Confidential 12/13/2011
- 79. : .( ) .( ) . , Is-A , Replace Inheritance with Delegation
Extract Subclass, Push Down Field, Push Down Method , . -> Java
Collection79 Confidential 12/13/2011
- 80. : Drawable Drawable +draw() Line +draw() Exception
+getArea() +getArea() , 0 Rectangle Circle Rectangle Circle Line
+getArea() Drawable +draw() Shape Line +getArea() +getLength()
Rectangle Circle80 Confidential 12/13/2011
- 81. Liskov Substitution Principle(LSP)Functions that use
pointers or references to base classes must be able to use objects
of derived classes without knowing it. , Square Rectangle . -> ,
LSP . Shape Rectangle.setWidth() Square.setWidth() . +getArea()
Shape Rectangle Circle +getArea()
+width+height+setWidth()+setHeight()+getWidth() Square Rectangle
Circle+getHeight() +width +width +height +height +setLength()
+setWidth() +setHeight() Square +getWidth() +getHeight()OOD IS-A
.81 Confidential 12/13/2011
- 82. Refactoring : Replace Inheritance with Delegation 82
Confidential 12/13/2011
- 83. : ( ) (private ) . . -> Self Encapsulate Field ->
Form Template Method -> Replace Inheritance with Delegation 83
Confidential 12/13/2011
- 84. Refactoring : Form Template Method , , , , , .84
Confidential 12/13/2011
- 85. : , Delegation. . -> Collapse Hierarchy -> Inline
Class .85 Confidential 12/13/2011
- 86. 86 Confidential 12/13/2011
- 87. : 87 Confidential 12/13/2011
- 88. : & Class A Class B Class A Class B .. .. .. attributeA
amethod() getX() amethod() bmethod() getY() bmethod() amethod()
private . - Move Method Move Method - Extract Hierarchy-> Hide
Delegate - Change Bidirectional Reference to Unidirectional88
Confidential 12/13/2011
- 89. Refactoring : Hide Delegate , (Delegate) . Client
Department . Law of Demeter . : . 89 Confidential 12/13/2011
- 90. Refactoring : Change Bidirectional Association to
Unidirectional . Bidirectional Association . -> Zombie Cluster
-> Coupling 90 Confidential 12/13/2011
- 91. : & Remove Middleman Hide Delegate .
person.getDepartment().getManager() Delegate Feature . Server . . .
Delegate Feature Server . . Hide Delegate Remove Middleman ! , . 91
Confidential 12/13/2011
- 92. 92 Confidential 12/13/2011
- 93. : (Divergent Change) (Parallel Inheritance Hierarchies)
(Combinational Explosion) (Shotgun Surgery) 93 Confidential
12/13/2011
- 94. : (Divergent Change) Shape Shape ShapWriter +draw() +draw()
+persist() +persist() 5px .. Binary , XML .. Rectangle Circle
Triangle RectangleWriter CircleWriter TriangleWriter Rectangle
Circle Triangle +draw() +draw() +draw() +persistence()
+persistence() +persistence() +draw() V +draw() V +draw()V
+persist() V +persist() V +persist() V . . Extract Class Class . 94
Confidential 12/13/2011
- 95. : SRP Test Method Uses , Used History ? 95 Confidential
12/13/2011
- 96. : Shape ShapWriter +draw() +persist() Rectangle Circle
Triangle RectangleWriter CircleWriter TriangleWriter +draw()
+draw() +draw() +persistence() +persistence() +persistence() ->
. Move Method, Move Field 96 Confidential 12/13/2011
- 97. : ShapeWriter Triangle +persist() ? DB ? Rectangle Circle
+draw() +draw() RectangleExcelWriter RectangleXmlWriter
RectangleExcelWriter RectangleXmlWriter (or Concern) . Replace
Inheritance with Delegation Tease Apart Inheritance 97 Confidential
12/13/2011
- 98. Refactoring : Tease Apart Inheritance , . , . 98
Confidential 12/13/2011
- 99. : (Shotgun Surgery) . . . Move Method, Move Field &
Persistence 99 Confidential 12/13/2011
- 100. 100 Confidential 12/13/2011
- 101. : . Introduce Foreign Method Introduce Local Extension
[Introduce Local Extension] 101 Confidential 12/13/2011