2009-09-15 84 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