2011-04-26 90 views
4

我继承了一个处理请求的java应用程序,如果它确定某个请求应该被取消,就会抛出一个异常。对于以前的开发人员来说,例外情况很方便,因为他们是退出不再适用的逻辑树的一种简单方法(是转向),并且它将堆栈跟踪打印到日志中,这是一个很好的信息。这似乎是论坛和博客上的关于异常不应该用于流量控制的问题,超过一半的请求被取消,所以它们绝对不是特殊情况。一个论点是性能,这不适用,因为我们的例外代码运行速度足够多年。另一个论点是,它的转变并不明确,我同意这一点。我的问题是:什么是替代方案。我唯一能想到的是如果处理应该继续,每个方法返回true,否则返回false。这似乎是它会膨胀巨大我的代码更改此:什么是流量控制例外的替代方案?

checkSomething(); 
checkSomethingElse(); 

到这一点:

boolean continueProcessing = false; 
continueProcessing = checkSomething(); 
if (!continueProcessing) { 
    return false; 
} 
continueProcessing = checkSomethingElse(); 
if (!continueProcessing) { 
    return false; 
} 

然后呢,如果该方法应该返回的东西?任何指导都会很棒。我真的很想观察任何“最佳实践”。

更新:

我也许应该在第一时间提到另一个位是一个请求被取消的时间超过50%,并不意味着事情没有去正确的,这意味着要求WASN终究不需要。

+0

我认为*检查*异常描述意图完美(而不是GOTO)。我没有看到这个问题。确保定义你自己的异常,并提供足够的具体信息来处理你的特例(多个catch块对此很好)。 – laher 2011-04-26 23:57:20

+1

正确使用goto没有任何问题。唯一的事情是,大多数时候,他们没有得到恰当的使用。 – Anonymoose 2011-04-27 00:43:41

+2

不要为了改变而改变任何东西。它的工作原理,并行之有效 - 让它成为现实。抽象的想法很好,但工作代码更好。 – 2011-04-27 01:16:06

回答

4

在您的方案中,替代方法会抛出异常并返回结果。

哪一个最好(哪一个是“最佳实践”)取决于“检查...”方法的失败应该归类为正常还是异常。在某种程度上,这是一个判断电话,必须作出。在作出这一呼吁也有几件事情要牢记:

  • 创建+投掷+捕获异常大致幅度不是测试一个布尔值的慢3个数量级。

  • 返回状态码的最大问题是很容易忘记测试它们。

综上所述,最好的做法是不要使用异常实现正常流量控制,但它是由你来决定在哪里正常之间的界线特殊是。


没有看到真正的代码/上下文,我的直觉是,这可能是一个适当的地方使用异常。

+0

以前的开发人员很了解他的生意。代替spagetti代码 - 一次干净的投掷。如果他设法提供清洗变化的状态,他是一个神的闪耀。 – 2011-04-27 01:03:26

+0

我更新了上面的问题,以反映一个请求被取消超过50%的时间,取消只是意味着一个请求毕竟不需要,而不是说有问题。性能再次不是问题。这个应用程序在晚上运行在服务器上,足够快。 – Stinky 2011-04-27 16:38:35

-2

如何

if (!checkSomething()) return false; 
if (!checkSomethingElse()) return false; 

无需为标志,如果你提前退出。

+0

@ThomasS:守卫子句比任何我能想到的替代品都要干净。我个人觉得处理一堆嵌套条件有点困难,这将是“可接受的”选择。如果'checkSomething'等被命名为更好的东西,比如'somethingIsBroken',并且如果它被打破,则返回true,这会更有意义。但我仍然认为这个想法是正确的。肯定比使用正常流量的例外少毛毛。那会比“goto”差得多。它更像是来自INTERCAL的'COMEFROM',这是一种设计难以使用的语言*。 – cHao 2013-01-14 16:35:17

0
int error = 0; 

do 
{//try-alt 
    error = operation_1(); if(error > 0){break;} 
    error = operation_2(); if(error > 0){break;} 
    error = operation_3(); if(error > 0){break;} 
}while(false); 

switch(error) //catch-alt 
{ 
case 1: handle(1); break; 
case 2: handle(2); break; 
case 3: handle(3); break; 
} 
0

TL;博士担忧的

分离,IMO你应该这样做:

continue = checkSomething() && checkSomethingElse(); 

或许有代码中与其它设计问题。



有什么功能的关注 - 因为你要定义它(这可能是一个主观的问题)? 如果错误符合函数的关注点,则不要抛出异常。如果你对这个错误是否适合这个问题感到困惑,那么这个函数可能会试图完成太多的问题(糟糕的设计)。

错误控制选项:

  1. 不报告错误。它要么是直接通过功能或处理不太多的事情
  2. 返回值是
    1. 空,而不是一个对象
    2. 错误信息(不是对象成功返回甚至不同的数据类型)的。
  3. 传入的参数将用于存储错误数据。
  4. 触发事件
  5. 如果发生错误,调用闭包传递函数。
  6. 抛出异常。 (我主张这应该通常如果不是的任意定义功能的目的的一部分才能这样做)

如果代码的目的是检查一些状态,然后知道了状态为假是直接点的函数。不要抛出异常,但返回false。

这就是它看起来像你想要的。您有正在运行检查程序Y和Z的进程X.进程X(或任何调用进程)的控制流程为而不是与检查系统状态相同。