2009-09-15 139 views
2

我有幾個(超過20個)方法(getXXX()),它們在調用時可能會拋出異常(NotCalculatedException)。重構調用其他方法的方法拋出異常

在另一種方法中,我需要訪問這些方法給出的結果。就目前而言,我有一個可怕的代碼,它看起來像:

public void myMethod() { 
    StringBuffer sb = new StringBuffer(); 
    // Get 'foo' result... 
    sb.append("foo = "); 
    try { 
     sb.append(getFoo()); 
    } catch (NotCalculatedException nce) { 
     sb.append("not calculated."); 
    } 
    // Get 'bar' result... 
    sb.append("\nbar = "); 
    try { 
     sb.append(getBar()); 
    } catch (NotCalculatedException nce) { 
     sb.append("not calculated."); 
    } 
    ... 
} 

,而無需修改getXXX方法(因此他們必須保持自己的throws NotCalculatedException),你會如何重構/簡化myMethod()使它看起來更好?

請注意,此項目仍在使用Java 1.4 :(


編輯

不能把所有的getXXX()方法在try { ... }塊,作爲StringBuffer的意志如果一種方法拋出NotCalculatedException,則不完整。

public void myMethod() { 
    StringBuffer sb = new StringBuffer(); 
    try { 
     sb.append("foo = "); 
     sb.append(getFoo()); 
     sb.append("\nbar = "); 
     sb.append(getBar()); 
    } catch (NotCalculatedException nce) { 
     sb.append("not calculated."); 
    } 
    ... 
} 

在其他也就是說,如果getFoo()拋出一個NotCalculatedException,我想有這樣的輸出:

foo = not calculated 
bar = xxx 
... 

如果我把一切都放在一個單一的try { ... },我將有輸出,我不想要得到:

foo = not calculated 

回答

2

我不認爲你應該使用NotCalculatedException來控制邏輯。

但我對此有幾點想法。

  1. 您需要另一個getter方法

    sb.append(this.getFoo( 「未計算」));

  2. 創建hasValue的方法

    sb.append(hasFoo()this.getFoo(): 「未計算」);

  3. 創建通用getter方法

    sb.append(this.getValueByName( 「富」));

0

您可以將「foo」,「bar」等存儲在數組中。在這些循環中,打印每一個,然後使用反射來查找/調用相應的getFoo(),getBar()。不好,我承認。

查看Method對象獲取更多信息。

編輯:或者,使用AspectJ圍繞該對象的每個getXXX()方法調用並捕獲異常。

+0

是的,我想過使用反射,但我真的不喜歡這樣的解決方案(在這種情況下)... – romaintaz 2009-09-15 14:33:01

1

對於每個getXXX您可以添加一個getXXXOrDefault(),其中包含異常並返回getXXX或「未計算」的值。

public void myMethod() {  
     StringBuffer sb = new StringBuffer();  
     // Get 'foo' result...  
     sb.append("foo = "); 
     sb.append(getFooOrDefault()); 
     // Get 'bar' result...  
     sb.append("\nbar = "); 
     sb.append(getBarOrDefault()); 
     // ... 
} 

public Object getFooOrDefault() { 
     try { 
       return getFoo(); 
     } catch() { 
       return "not calculated."; 
     } 
} 

還是...使用反思

public Object getValueOrDefault(String methodName) { 
     try { 
       // 1 . Find methodName 
       // 2 . Invoke methodName 
     } catch() { 
       return "not calculated."; 
     } 
} 

但我覺得我還是比較喜歡第一個選項。

+0

是的,這是一個想法,但它意味着我將創建20種新的方法。 .. – romaintaz 2009-09-15 14:34:18

+0

海事組織,這是一個壞主意。不要使用對象,使用存儲getFoo()的返回值的包裝器和指示檢索是否正常的代碼(enum/int/bool)。 – 2009-09-15 14:51:14

+0

我只使用Object,因爲我不知道getFoo或getBar的返回類型是什麼。即便如此,爲什麼downvote? – 2009-09-15 14:56:45

0

你可以使用Execute Around idiom。不幸的是,Java語法是冗長的,所以在簡單的情況下它不是什麼好事。假設NotCalculatedException是一個無用的例外。

appendThing(sb, "foo = ", new GetValue() { public Object get() { 
    return getFoo(); 
}}); 
appendThing(sb, "bar = ", new GetValue() { public Object get() { 
    return getBar(); 
}}); 

另一個難看方法將結合一個循環,並切換:

int property = 0; 
lp: for (;;) { 
    String name = null; // Ugh. 
    try { 
     final Object value; 
     switch (property) { 
      case 0: name= "foo"; value = getFoo(); break; 
      case 1: name= "bar"; value = getBar(); break; 
      default: break lp; 
     } 
     ++property; 
     sb.append(name).append(" = ").append(value).append('\n'); 
    } catch (NotCalculatedException exc) { 
     sb.append(name).append(" = ").append("not calculated.\n"); 
    } 
} 

可替代地,有一個枚舉和每個參數的開關。只是不要使用反射!

+0

爲什麼有關反射的評論?這是一個風格問題,還是有原因,它不會工作? (我知道我已經提出了反思,並且我承認這並不好,但我相信它*會起作用) – 2009-09-15 14:35:11

+1

反思是一個很好的跡象表明某些非常非常錯誤的事情正在發生。 – 2009-09-15 14:39:02

+0

除非Lambdas到達Java,否則第一個選項看起來非常糟糕。 如果您的團隊中有代碼格式化標準(並且他們可能使用IDE默認設置)。 反射本身並不壞,問題在於Java語言沒有強類型方法,並且語法良好(在C#中委託)。 – 2009-09-15 15:02:40

1

我的建議是更多的代碼,但改善的可讀性爲myMethod的:

public void myMethod() { 
    StringBuilder resultBilder = new StringBuilder(); 

    resultBuilder.append("foo="); 
    appendFooResult(resultBuilder); 
    resultBuilder.append("\nbar="); 
    appendBarResult(resultBuilder); 

    ... 
} 

private void appendFooResult(StringBuilder builder) { 
    String fooResult = null; 
    try { 
     fooResult = getFoo(); 
    } catch (NotCalculatedException nce) { 
     fooResult = "not calculated."; 
    } 
    builder.append(fooResult); 
} 

private void appendBarResult(StringBuilder builder) { 
    String barResult = null; 
    try { 
     barResult = getBar(); 
    } catch (NotCalculatedException nce) { 
     barResult = "not calculated."; 
    } 
    builder.append(barResult); 
} 
0

好像Java沒有代表出像C#的盒子 - 但是谷歌向我表明有ways to roll your own。所以下面可能是一些嘗試..

public static PrintProperty(JavaDelegateWithAName del, StringBuilder collector) 
{ 
    try 
    { 
    collector.append(del.Name+ " = "); 
    collector.append(del.Target.Invoke()); 
    } 
    catch(NotCalculatedException nce) 
    { collector.append("NotCalculated"); } 
} 

...主要

foreach(JavaDelegateWithAName entry in collectionOfNamedJavaDelegates) 
    SomeUtilityClass.PrintProperty(entry, sb); 
1

我想你應該離開你的代碼是。它很詳細,但很容易分辨它做了什麼,它的行爲是否正確。

+0

或者,使用bruno提出的將try/catch移入覆蓋方法的建議,看起來更好一點 – 2009-09-15 14:49:10

+0

+1爲了美觀起見,沒有必要過分地闡述某些東西。 – banjollity 2009-09-15 20:47:11