在当前的Java项目中,我们有类似于以下示例的代码:
try {
doSomeThing(anObject);
}
catch (SameException e) {
// Do nothing or log, but don't abort current method.
}
try {
doOtherThing(anObject);
}
catch (SameException e) {
// Do nothing or log, but don't abort current method.
}
// ... some more calls to different method ...
try {
finallyDoYetSomethingCompletelyDifferent(anObject);
}
catch (SameException e) {
// Do nothing or log, but don't abort current method.
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,使用完全相同的对象调用了几个不同的方法,并且对于每个调用,捕获并处理相同的异常(或以非常类似的方式).异常不会被重新抛出,但可能只会被记录然后被丢弃.
try-catch
围绕每个方法存在的唯一原因是始终执行所有方法,无论先前执行的方法是否失败.
我根本不喜欢上面的代码.它占用了大量的空间,非常重复(尤其是在catch
-block中完成的日志记录;此处未提供)并且看起来很糟糕.
我可以想到其他一些编写代码的方法,但是也不太喜欢它们.我想到了以下选项:
循环切换顺序/用于案例范例
for (int i = 0; i <= 9; i++) {
try {
switch (i) {
case 0:
doSomeThing(anObject); break;
case 1:
doOtherSomeThing(anObject); break;
// ...More cases...
case 9:
doYetSomethingCompletelyDifferent(anObject); break;
}
}
catch (SameException e) {
// Do nothing or log, but don't abort current method.
}
}
Run Code Online (Sandbox Code Playgroud)
这显然是错误的代码,非常容易出错并且看起来很业余.
反射
使用反射来获取Method
方法的对象,以便按照它们应该执行的顺序将它们存储在列表中.然后迭代此列表并使用anObject
as only参数调用该方法.异常在循环内部处理.
我不喜欢这种方法,因为错误(例如方法名称中的拼写错误)仅在运行时弹出,而Reflection API有些繁琐.
函子
像这样创建一个Functor类:
private class Functor
{
void doStuff(MyObject object) throws SameException;
}
Run Code Online (Sandbox Code Playgroud)
然后创建一个Functor
调用方法的对象列表.像这样:
List<Functor> functors = new ArrayList<Functor>();
functors.add(new Functor() {
@Override
public void execute(MyObject anObject) {
doSomeThing(anObject);
}
});
functors.add(new Functor() {
@Override
public void execute(MyObject anObject) {
doOtherSomeThing(anObject);
}
});
Run Code Online (Sandbox Code Playgroud)
稍后,迭代此列表并调用execute()
每个Functor
对象.我可以用两个词来总结我对这种方法的感觉:代码膨胀.
由于我不喜欢这四种方法,我想在这里讨论这个问题.你觉得最好的方法是什么?你是怎么解决过去的类似问题的?是否有一个我完全错过的更简单的解决方案?
我会提倡重构方法(或" 我们为什么一开始就到这里来? "):
考虑为什么单个方法可以在使用myObject执行"stuff"之后抛出异常,然后可以安全地忽略该异常.由于异常会转义该方法,因此myObject必须处于未知状态.
如果忽略异常是安全的,那么肯定是错误的方式来传达每个方法中出错的地方.
相反,也许每个方法都需要对失败进行一些记录.如果不使用静态记录器,则可以将记录器传递给每个方法.
仿函数方法是我心目中最好的方法 - 遗憾的是,Java没有更好的方式来表示闭包或代理.这基本上就是你真正想要的,而在C#(和许多其他语言)中,这将是微不足道的.
你可以通过以下方式减少物理膨胀:
Functor[] functors = new Functor[] {
new Functor() { @Override public void execute(MyObject anObject) {
doSomeThing(anObject);
}},
new Functor() { @Override public void execute(MyObject anObject) {
doSomeOtherThing(anObject);
}}
};
Run Code Online (Sandbox Code Playgroud)
在这里崩溃的空白可能会违背你正在使用的风格指南,但我认为它使代码更容易实际阅读,因为你可以更容易地看到肉.
最好开始游说Java 8中的闭包;)
归档时间: |
|
查看次数: |
393 次 |
最近记录: |