什么是流量控制例外的替代方案?
我inheritance了一个java应用程序,它处理请求并在确定应该取消请求时抛出exception。 对于以前的开发人员来说,例外是很方便的,因为它们是退出不再适用的逻辑树的简单方法(是一个goto),并且它会向日志打印一个堆栈跟踪,这是一个很好的信息。 似乎是论坛和博客上的共识,不应将exception用于流量控制,并且超过一半的处理请求被取消,因此它们绝对不是例外情况。 一个论点是性能,它不适用,因为我们的exception代码运行速度足够多年。 另一个论点是,它的结论并不清楚,我同意这一点。 我的问题是:替代方案是什么。 我唯一能想到的是,如果处理应该继续,则每个方法都返回true,否则返回false。 这似乎会使我的代码变得非常膨胀:
checkSomething(); checkSomethingElse();
进入这个:
boolean continueProcessing = false; continueProcessing = checkSomething(); if (!continueProcessing) { return false; } continueProcessing = checkSomethingElse(); if (!continueProcessing) { return false; }
那么如果该方法应该返回什么呢? 任何指导都会很棒。 我真的很想观察可用的“最佳实践”。
更新:
我可能应该首先提到的另一个问题是,请求在超过50%的时间内被取消,并不意味着某些事情没有正确,这意味着毕竟不需要请求。
在您的方案中,替代方法是抛出exception并返回结果。
哪个最好(哪个是“最佳实践”)取决于“检查……”方法的失败是否应归类为正常或exception。 在某种程度上,这是你必须做出的判断。 在打电话时,有几点需要注意:
-
创建+抛出+捕获exception大约比测试布尔结果低3个数量级。
-
返回状态代码的一个大问题是很容易忘记测试它们。
总之,最佳实践是不使用exception来实现正常的流量控制,但是由您来决定正常和exception之间的边界线。
在没有看到真实的代码/上下文的情况下,我的直觉是这可能是使用exception的合适位置。
请参阅Javaexception有多慢? 对这个主题进行了很好的讨论。
TL;博士
分离关注点和IMO你应该这样做:
continue = checkSomething() && checkSomethingElse();
或者代码中可能还有其他设计问题。
函数的关注点 – 你想要定义它(这可能是一个主观问题)? 如果错误符合函数的关注点,则不要抛出exception 。 如果你对错误是否符合问题感到困惑,那么函数可能试图自己完成太多的关注(糟糕的设计)。
错误控制选项:
- 不报告错误。 它要么直接由function处理,要么不重要
- 返回值是
- null而不是对象
- 错误信息(甚至可能是与成功返回的对象不同的数据类型)。
- 传入的参数将用于存储错误数据。
- 触发事件
- 如果发生错误,则调用传递给函数的闭包。
- 抛出exception。 (我认为通常只有在它不是函数的任意定义目的的一部分时才应该这样做)
如果代码的目的是检查某个状态,那么知道状态为false就是函数的关键点 。 不要抛出exception,但返回false。
这就是你想要的样子。 您有正在运行检查程序Y和Z的进程X.进程X(或任何调用进程)的控制流与检查系统状态不同。
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; }
怎么样
if (!checkSomething()) return false; if (!checkSomethingElse()) return false;
如果你提前退出,则不需要旗帜。