簡體   English   中英

重構調用其他引發異常的方法的方法

[英]Refactoring a method which is calling others methods that throws Exception

我有幾個(超過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 { ... }塊中,因為如果一個方法拋出NotCalculatedException ,則StringBuffer將不完整。

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

我認為您不應該使用NotCalculatedException來控制邏輯。

但是我對此有一些想法。

  1. 您需要另一種吸氣方法

    sb.append(this.getFoo(“未計算”)));

  2. 創建hasValue方法

    sb.append(hasFoo()?this.getFoo():“未計算”);

  3. 創建一個通用的getter方法

    sb.append(this.getValueByName( “富”));

對於每個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.";
        }
}

但我認為我仍然更喜歡第一選擇。

我的建議是增加代碼,但提高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);
}

我認為您應該將代碼保持原樣。 它很冗長,但是很容易分辨它的作用,並且行為正確。

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

有關更多信息,請參見Method對象。

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

您可以使用Execute Around成語。 不幸的是,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");
    }
}

另外,每個參數都有一個枚舉和一個開關。 只是不要使用反射!

似乎Java沒有像C#-這樣的開箱即用的代理,但是Google向我展示了可以使用自己的代理的方法 因此,以下可能是可以嘗試的方法。

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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM