范例(Examples):對(duì)局部變量再賦值(Reassigning)
如果被提煉碼對(duì)局部變量賦值,問(wèn)題就變得復(fù)雜了.這里我們只討論臨時(shí)變量的問(wèn)題.如果你發(fā)現(xiàn)源函數(shù)的參數(shù)被賦值,應(yīng)該馬上使用Remove Assignments to Parameters(131).
被賦值的臨時(shí)變量也分兩種情況.較簡(jiǎn)單的情況是:這個(gè)變量只在被提煉碼區(qū)段中使用.果真如此,你可以將這個(gè)臨時(shí)變量的聲明式移到被提煉碼中,然后一起提煉出去.另一種情況是:被提煉碼之外的代碼也使用了這個(gè)變量.這又分為兩種情況:如果這個(gè)變量在被提煉碼之后未再被使用,你只需直接在目標(biāo)函數(shù)中修改它就可以了;如果被提煉碼之后的代碼還使用了這個(gè)變量,你就需要讓目標(biāo)函數(shù)返回該變量改變后的指.我以下列代碼說(shuō)明這幾種不同情況:
void printOwing() {
Enumeration e = _orders.elements();
double outstanding = 0.0;
printBanner();
// calculate outstanding
while(e.hasMoreElements()) {
Order each = (Order) e.nextElement();
outstanding += each.getAmount();
}
printDetails(outstanding);
}
現(xiàn)在我把[計(jì)算]代碼提煉出來(lái):
void printOwing() {
printBanner();
double outstanding = getOutstanding();
printDetails(outstanding);
}
double getOutstanding() {
Enumeration e = _orders.elements();
double outstanding = 0.0;
while(e.hasMoreElements()) {
Order each = (Order) e.nextElement();
outstanding += each.getAmount();
}
return outstanding;
}
Enumeration變量e只在被提煉碼中用到,所以我可以將它整個(gè)搬到新函數(shù)中.double變量outstanding在被提煉碼內(nèi)外都被用到,所以我必須讓提煉出來(lái)的新函數(shù)返回它.編譯測(cè)試完成后,我就把傳值改名,遵循我的一貫命名原則:
double getOutstanding() {
Enumeration e = _orders.elements();
double result = 0.0;
while(e.hasMoreElements()) {
Order each = (Order) e.nextElement();
result += each.getAmount();
}
return result;
}
本例中的outstanding變量只是很單純地被初始化為一個(gè)明確初值,所以我可以只在新函數(shù)中對(duì)它初始化.如果代碼還對(duì)這個(gè)變量做了其他處理,我就必須將它的值作為參數(shù)傳給目標(biāo)函數(shù).對(duì)于這種變化,最初代碼可能是這樣:
void printOwing(double previousAmount) {
Enumeration e = _orders.elements();
double outstanding = previousAmount * 1.2;
printBanner();
// calculate outstanding
while(e.hasMoreElements()) {
Order each = (Order) e.nextElement();
outstanding += each.getAmount();
}
printDetails(outstanding);
}
提煉后的代碼可能是這樣:
void printOwing(double previousAmount) {
double outstanding = previousAmount * 1.2;
printBanner();
double outstanding = getOutstanding(outstanding);
printDetails(outstanding);
}
double getOutstanding(double initialValue) {
double result = initialValue;
Enumeration e = _orders.elements();
while(e.hasMoreElements()) {
Order each = (Order) e.nextElement();
result += each.getAmount();
}
return result;
}
編譯并測(cè)試后,我再將變量outstanding的初始化過(guò)程整理一下:
void printOwing(double previousAmount) {
printBanner();
double outstanding = getOutstanding(previousAmount * 1.2);
printDetails(outstanding);
}
這時(shí)候,你可能會(huì)問(wèn):[如果需要返回的變量不止一個(gè),又該怎么辦?]
你有數(shù)種選擇.最好的選擇通常是:挑選另一塊代碼來(lái)提煉.我比較喜歡讓每個(gè)函數(shù)都只返回一個(gè)值,所以我會(huì)安排多個(gè)函數(shù),用以返回多個(gè)值.如果你使用的語(yǔ)言支持[輸出式參數(shù)](output parameters),你可以使用它們帶回多個(gè)回傳值.但我還是盡可能選擇單一返回值.
臨時(shí)變量往往為數(shù)眾多,甚至?xí)固釤捁ぷ髋e步維艱.這種情況下,我會(huì)嘗試先運(yùn)用Replace Temp with Query(120)減少臨時(shí)變量.如果即使這么做了提煉依舊困難重重,我就會(huì)動(dòng)用Replace Method with Method Object(135),這個(gè)重構(gòu)手法不在乎代碼中有多少臨時(shí)變量,也不在乎你如何使用它們.
如果被提煉碼對(duì)局部變量賦值,問(wèn)題就變得復(fù)雜了.這里我們只討論臨時(shí)變量的問(wèn)題.如果你發(fā)現(xiàn)源函數(shù)的參數(shù)被賦值,應(yīng)該馬上使用Remove Assignments to Parameters(131).
被賦值的臨時(shí)變量也分兩種情況.較簡(jiǎn)單的情況是:這個(gè)變量只在被提煉碼區(qū)段中使用.果真如此,你可以將這個(gè)臨時(shí)變量的聲明式移到被提煉碼中,然后一起提煉出去.另一種情況是:被提煉碼之外的代碼也使用了這個(gè)變量.這又分為兩種情況:如果這個(gè)變量在被提煉碼之后未再被使用,你只需直接在目標(biāo)函數(shù)中修改它就可以了;如果被提煉碼之后的代碼還使用了這個(gè)變量,你就需要讓目標(biāo)函數(shù)返回該變量改變后的指.我以下列代碼說(shuō)明這幾種不同情況:
void printOwing() {
Enumeration e = _orders.elements();
double outstanding = 0.0;
printBanner();
// calculate outstanding
while(e.hasMoreElements()) {
Order each = (Order) e.nextElement();
outstanding += each.getAmount();
}
printDetails(outstanding);
}
現(xiàn)在我把[計(jì)算]代碼提煉出來(lái):
void printOwing() {
printBanner();
double outstanding = getOutstanding();
printDetails(outstanding);
}
double getOutstanding() {
Enumeration e = _orders.elements();
double outstanding = 0.0;
while(e.hasMoreElements()) {
Order each = (Order) e.nextElement();
outstanding += each.getAmount();
}
return outstanding;
}
Enumeration變量e只在被提煉碼中用到,所以我可以將它整個(gè)搬到新函數(shù)中.double變量outstanding在被提煉碼內(nèi)外都被用到,所以我必須讓提煉出來(lái)的新函數(shù)返回它.編譯測(cè)試完成后,我就把傳值改名,遵循我的一貫命名原則:
double getOutstanding() {
Enumeration e = _orders.elements();
double result = 0.0;
while(e.hasMoreElements()) {
Order each = (Order) e.nextElement();
result += each.getAmount();
}
return result;
}
本例中的outstanding變量只是很單純地被初始化為一個(gè)明確初值,所以我可以只在新函數(shù)中對(duì)它初始化.如果代碼還對(duì)這個(gè)變量做了其他處理,我就必須將它的值作為參數(shù)傳給目標(biāo)函數(shù).對(duì)于這種變化,最初代碼可能是這樣:
void printOwing(double previousAmount) {
Enumeration e = _orders.elements();
double outstanding = previousAmount * 1.2;
printBanner();
// calculate outstanding
while(e.hasMoreElements()) {
Order each = (Order) e.nextElement();
outstanding += each.getAmount();
}
printDetails(outstanding);
}
提煉后的代碼可能是這樣:
void printOwing(double previousAmount) {
double outstanding = previousAmount * 1.2;
printBanner();
double outstanding = getOutstanding(outstanding);
printDetails(outstanding);
}
double getOutstanding(double initialValue) {
double result = initialValue;
Enumeration e = _orders.elements();
while(e.hasMoreElements()) {
Order each = (Order) e.nextElement();
result += each.getAmount();
}
return result;
}
編譯并測(cè)試后,我再將變量outstanding的初始化過(guò)程整理一下:
void printOwing(double previousAmount) {
printBanner();
double outstanding = getOutstanding(previousAmount * 1.2);
printDetails(outstanding);
}
這時(shí)候,你可能會(huì)問(wèn):[如果需要返回的變量不止一個(gè),又該怎么辦?]
你有數(shù)種選擇.最好的選擇通常是:挑選另一塊代碼來(lái)提煉.我比較喜歡讓每個(gè)函數(shù)都只返回一個(gè)值,所以我會(huì)安排多個(gè)函數(shù),用以返回多個(gè)值.如果你使用的語(yǔ)言支持[輸出式參數(shù)](output parameters),你可以使用它們帶回多個(gè)回傳值.但我還是盡可能選擇單一返回值.
臨時(shí)變量往往為數(shù)眾多,甚至?xí)固釤捁ぷ髋e步維艱.這種情況下,我會(huì)嘗試先運(yùn)用Replace Temp with Query(120)減少臨時(shí)變量.如果即使這么做了提煉依舊困難重重,我就會(huì)動(dòng)用Replace Method with Method Object(135),這個(gè)重構(gòu)手法不在乎代碼中有多少臨時(shí)變量,也不在乎你如何使用它們.