1.Replace Temp with Query
2.Introduce Explaining Variable
3.Split Temporary Variable
4.Remove Assignments to Parameters
5.Replace Method with Method Object
6.Substitute Algorithm
1.Replace Temp with Query
將運算式提煉成一個獨立函式(query Method)。
將暫時變數的所有引用點替換為對新函式的呼叫。新函式可被其他函式所使用。
Example:
1: double basePrice = _quantity *_itemPrice;
2: if(basePrice > 10000)
3: return basePrice * 0.95;
4: else
5: return basePrice * 0.98;
提煉
1: if(basePrice() > 10000)
2: return basePrice() * 0.95;
3: else
4: return basePrice() * 0.98;
5: //...
6: double basedPrice()
7: {
8: return _quantity *_itemPrice;
9: }
Motivation
1.將暫時變數替換成query method同一個Class都可以獲得這資訊且能夠為這class編寫更清晰的程式碼。
2.Replace Temp with Query往往運用Extract Method之前不可少的一個步驟,區域變數會使程式碼難以提煉,所以應該盡可能將區域變數替換為query method。
3.暫時變數只被賦值一次,或者賦值給暫時變數的運算式不受其他條件影響。
4.可先將query method需告成private,較容易保護。
5.確保提煉出來的函式無任何副作用。如果有影響可使用Separate Query from Modifier。
2.Introduce Explaining Variable
將複雜運算式(或其中一部分)的結果放進一個暫時變數,以此變數名稱來解釋運算適用途。
Example:
1: if(platform.toUpperCase().indexOf("MAC") > -1 )&&
2: browser.toUpperCase().indexOf("IE") > -1)&&
3: wasInitialized() && resize > 0)
4: {}
提煉
1: final boolean isMacOs = platform.toUpperCase().indexOf("MAC") > -1;
2: final boolean isIEBrowser = browser.toUpperCase().indexOf("IE") > -1;
3: final boolean wasResized = resize >0;
4: if(isMacOs && isIEBrowser && wasInitialized() && wasResized){}
Motivation:
1.用良好命名的暫時變數來解釋對應條件子句的意義。
2.但也可以盡量使用Extract Method來解釋一段程式碼意義,這方法就可以不需要做了。
3.Split Temporary Variable
某個暫時變數被賦值超過一次,它既不是迴圈變數,也不是一個急用暫時變數(collecting temporary variable)。
Example:
1: double temp = 2 * (_height + _width);
2: System.out.println(temp);
3: temp = _height * _width;
4: System.out.println(temp);
提煉
1: final double perimeter = 2 * (_height + _width);
2: System.out.println(perimeter);
3: final double area = _height * _width;
4: System.out.println(area);
Motivation:
1.暫時變數可能會被多次賦值,為每個不同功能的暫時變數給予不同的命名。
4.Remove Assignments to Parameters
對一個參數進行賦值的動作。
Example
1: int discount (int inputVal,int quantity,int yearToDate)
2: if(inputVal > 50) inputVal -= 2;
提煉
1: int discount (int inputVal,int quantity,int yearToDate)
2: {
3: int result - inputVal;
4: if(inputVal > 50) result -= 2;
5: }
Motivation:
1.會使用這個方式是因為降低了pass by value 和 pass by reference的清晰度。
5.Replace Method with Method Object
將這個函式放進一個單獨物件中,如此一來區域變數就成了物件內的欄位。然後在同一個物件將這個大型函式分解數個小函式。
Example
1: class Order..
2: double price(){
3: double primaryBasePrice;
4: double secondaryBasePrice;
5: double tertiaryBasePrice;
6: }
Motivation
1.區域變數的存在增加函式分解難度,雖然Replace Temp with Query可以減輕一點負擔,但還是可能完全無法拆解,就可使用這個方法。
2.這將會把所有區域變數變成函式物件,然後使用Extract Method。
1: class Account
2: {
3: int gamma(int inputVal,int quilityVal,int date)
4: {
5: int importantVal1 = (intputVal * quility) * delta();
6: int importantVal2 = (inputVal * date);
7: //And so on...
8: return importantVal3 *2;
9: }
10: }
建立新的Class
1: class gamma
2: {
3: private Account _acount;
4: private int inputVal;
5: private int data;
6: private int qualityVal;
7: private int importValue1;
8: private int importValue2;
9: //Constructor
10: Gamma(Acount source,int inputValArg,int quilityArg,int dataArg)
11: {
12: _acount = source;
13: inputVal = inputValAtg;
14: quilityVal = quilityArg;
15: data = dataArg;
16: }
17: int compute()
18: {
19: importantValue1 = (inputVal * quility) + _account.delta();
20: return ....
21: }
22: }
因此在改動Account Class:
1: int gamma(int inputVal,int quility,data)
2: {
3: return new Gamma(this,inputVal,quility,data).compute();
4: }
可以輕易的在Gamma class 使用Extract Method。
5.Substitute Algorithm
1: string foundPerson(string[] people)
2: {
3: for(int i =0; i< people.length;i++)
4: {
5: if(people[i].equals("Don"))
6: return "Don";
7: if(people[i].equals("J"))
8: return "J";
9: if(people[i].equals("D"))
10: return "D";
11: }
12: return "";
13: }
提煉
1: string foundPerson(string[] people)
2: {
3: List candidates - Arrays.asList(new string[] {"Don","J","D"} );
4: for (int i =0; i < people.length;i++)
5: return people[i];
6: return "";
7: }
No comments:
Post a Comment