2010-06-02 55 views
3

我重構是達到500線的方法的長期方法(不要問我爲什麼)重構,簡單地填充

的方法基本上可以查詢地圖列表從數據庫中,每個地圖列表做一些計算並將該計算的值添加到地圖中。然而,有太多的計算和完成,代碼已經達到了超過500行!

下面是一個示例預覽:

public List<Hashmap> getProductData(...) { 
    List<Hashmap> products = productsDao.getProductData(...); 
    for (Product product: products) { 
     product.put("Volume",new BigDecimanl(product.get("Height")* 
       product.get("Width")*product.get("Length")); 
    //over 10 more lines like the one above 
     if (some condition here) { 
     //20 lines worth of product.put(..,..) 
     } else { 
     //20 lines worth of product.put(..,..) 
     } 
     //3 more if-else statements like the one above 
     try { 
     product.put(..,..) 
     } catch (Exception e) { 
     product.put("",..) 
     } 
     //over 8 more try-catches of the form above 
    } 

上如何去重構這個任何想法?

+1

你讀過Martin Fowlers重構書嗎?我真的不能推薦它。它以任何級別的程序員都能理解的方式來解釋重構技術,因此它不僅是重構的實際書籍(清潔代碼和使用遺留代碼是值得的合作伙伴),它可能是最好的書面技術書籍之一 – 2010-06-02 10:45:07

回答

4

這依賴於業務邏輯,但最簡單的方法去是長方法分裂成更小的:

for (Product product: products) { 
    handleProduct(product); 
} 


private void handleProduct(Product product) throws Exception { 
    if (condition1) { 
    handleProduct1(product); 
    } 
} 

如果每個條件,特定的業務情況相符這將使更多的意義並且有一個有意義的名字。

+0

+ 1感謝您的回答。這絕對是我正在考慮的事情之一。 – Jeune 2010-06-02 12:52:52

2

這是很難提供一個詳細的回答沒有更多的信息,但你可以考慮的做法是:

  • 改制使用Product類層次結構,而不是代表每個產品的Map產品(名稱,值)對。當前的Map表示意味着許多錯誤不會在運行時間之前被檢測到;更好地選擇更強的輸入,以便在編譯時執行更多檢查。
  • 在頂級Product類或接口上定義一個模板方法,該方法執行當前在500行方法中定義的大部分處理。例如,您可以按照下面的代碼提取將訪問者傳遞給模板方法。

/** 
* Our visitor definition, responsible for processing each product. 
*/ 
public interface ProductVisitor { 
    void processProductA(ConcreteProductA a); 

    void processProductB(ConcreteProductB b); 
} 

/** 
* Top-level product definition. 
*/ 
public interface Product { 
    void process(ProductVisitor v); 
} 

/** 
* A conrete product implementation. Makes a callback to the visitor 
* allowing itself to be processed. 
*/ 
public class ConcreteProductA implements Product { 
    public void process(ProductVisitor v) { 
    v.processProductA(this); 
    } 
} 

/** 
* As per the previous product implementation but makes a *different* 
* callback to the visitor. 
*/ 
public class ConcreteProductB implements Product { 
    public void process(ProductVisitor v) { 
    v.processProductB(this); 
    } 
} 

這種方法的主要優點是,你避免很多明確的if-then在你的代碼使設計更塊鬆耦合。缺點是它可能使代碼不易讀。

是在我腦海中的劃分方法
+0

我以前聽過這種模式。在分解更大的方法後,我會慷慨地做到這一點+1 – Jeune 2010-06-02 12:54:46

+0

糟糕,我剛剛意識到使用地圖的問題一直到頂端,例如我將地圖返回的方法。他們堅持使用地圖。所以我別無選擇,只能堅持地圖。現在,我仍然可以以某種方式應用模式,而是使用地圖。 @ - ) – Jeune 2010-06-02 14:14:55

+0

儘管如此,您可以將內部映射轉換爲產品實現。此時您可以檢查地圖參數的組合是否構成有效的產品。這很整潔,因爲它意味着你在開始時失敗並且可以拋出相關的異常;例如InvalidProductException。 – Adamski 2010-06-02 16:52:48

7

一個簡單的想法是「找到感覺更小的任務」,所以這裏有一些提示:

製作方法爲單品級

processCollection(collection) { 
// startup code 
for (Item i: collection) 
    processCollectionItem(i, ...other args...); 
// final code 
} 

試圖削減每個評論塊在其自己的方法

// does a 
instr 1 
instr 2 
instr 3 
instr 4 
// does b 
instr 5 
instr 6 
instr 7 
instr 8 

CONVER TS至

a(...); 
b(...); 

嘗試看看是否一些一堆線是一些一般圖案

map.put(a[0], b[0]); 
map.put(a[1], b[1]); 
... 

轉換的一個具體體現

putKeysAndValues(a, b); 

putKeysAndValues(a, b) { 
    for (int i=0; i<a.length; i++) 
    map.put(a[i], b[i]); 
} 
0

您可以通過將條件放置移動到單獨的方法並從當前方法調用它來縮短方法。

例如。

... 
if (some condition here) 
{ method1(map);} 
    else 
{method2(map);} 

此外,如果有共同的任務,也可以在不同的方法中拉它們。

1

假如你不能改變的道...這是我會怎麼處理它,不一定是正確的:

public List<Hashmap> getProductData(...) { 
    List<Hashmap> products = productsDao.getProductData(...); 
    try{ 
    addVolume(products); 
    ... 
    doCondition1(products); 
    ... 
    } catch (E1 e){ 
    ... 
    } ... { 
    } 
} 

public addVolume(List<HashMap> products) throws E1, E2, ... { 
    for(HashMap product : products){ 
    product.put("Volume",new BigDecimanl(product.get("Height")* 
       product.get("Width")*product.get("Length")); 
    } 
} 

... do other things ... 

public doCondition1(List<HashMap> products) throws E1, E2, ...{ 
    for(HashMap product : products){ 
    if(condition1){ 
     ... 
    }else{ 
     ... 
    } 
    } 
} 

...condition 2, condition 3, ... 

當然,你可以把內環路您

getProductData(...)

+0

+1以小步驟開始的關鍵 - 每步之後進行測試 – 2010-06-02 10:47:19