java 什么时候可以对业务逻辑使用异常处理?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5378005/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 10:50:26  来源:igfitidea点击:

When is it OK to use exception handling for business logic?

javaexception-handlingcoding-style

提问by Michael McGowan

I think it is accepted that as a general rule in Java (and perhaps any language with exception handling) one should try to avoid using exception handling to actually handle business logic. In general, if it is expected that a certain situation is supposed to happen, one should check for it and handle it more directly than relying on exception handling to do the checking for you. For example, the following is not considered good practice:

我认为可以接受的是,作为 Java(可能还有任何具有异常处理的语言)的一般规则,应该尽量避免使用异常处理来实际处理业务逻辑。一般来说,如果预期某种情况应该发生,那么应该检查它并更直接地处理它,而不是依靠异常处理来为您检查。例如,以下行为不被视为良好实践:

try{
  _map.put(myKey, myValue);
} catch(NullPointerException e){
  _map = new HashMap<String, String>();
}

Instead lazy initialization should be accomplished more like this:

相反,延迟初始化应该更像这样完成:

if(_map == null){
  _map = new HashMap<String, String>();
}
_map.put(myKey, myValue);

Of course there could be far more complex logic than simply handling lazy initialization. So given that this type of thing is usually frowned upon...when, if ever, is it a good idea to rely on an exception happening for certain business logic to occur? Would it be accurate to say that any instance where one feels compelled to use this approach is really highlighting a weakness of the API being used?

当然,可能有比简单地处理延迟初始化更复杂的逻辑。因此,鉴于这种类型的事情通常是不受欢迎的......如果有的话,依靠发生某些业务逻辑的异常发生是个好主意吗?是否可以准确地说,任何一个人感到不得不使用这种方法的实例都真正突出了所使用的 API 的弱点?

回答by a CVn

Whenever the exception can be anticipated but not avoided.

每当异常可以预期但不能避免时。

Say, if you are relying on an external API of some sort to parse data, and that API offers parse methods but nothing to tell whether a given input can be parsed or not (or if whether the parse can succeed or not depends on factors out of your control, but the API doesn't provide appropriate function calls), and the parsing method throws an exception when the input cannot be parsed.

比方说,如果您依赖某种外部 API 来解析数据,并且该 API 提供了解析方法,但无法判断给定的输入是否可以解析(或者解析是否成功取决于外部因素)您的控件,但 API 没有提供适当的函数调用),并且解析方法在无法解析输入时抛出异常。

With a properly designed API, this should boil down to a quantity somewhere in the range "virtually never" to "never".

使用正确设计的 API,这应该归结为“几乎从不”到“从不”范围内的某个数量。

I can see absolutely no reason to use exception handling as a means of normal flow control in code. It's expensive, it's hard to read (just look at your own first example; I realize it was probably written very quickly, but when _maphasn't been initialized, what you end up with is an empty map, throwing away the entry you were trying to add), and it litters the code with largely useless try-catch blocks, which can very well hide realproblems. Again taking your own example, what if the call to _map.add()were to throw a NullPointerExceptionfor some reason otherthan _mapbeing null? Suddenly, you are silently recreating an empty map rather than adding an entry to it. Which I'm sure I don't really have to say can lead to any number of bugs in completely unrelated places in the code because of unexpected state...

我完全没有理由在代码中使用异常处理作为正常流程控制的手段。它很昂贵,很难阅读(看看你自己的第一个例子;我意识到它可能写得很快,但是当_map没有初始化时,你最终得到的是一张空地图,扔掉你正在尝试的条目添加),并且它用大量无用的 try-catch 块乱扔代码,这可以很好地隐藏真正的问题。再次以自己的例子,如果有什么调用_map.add()是抛出一个NullPointerException由于某种原因,其他的不是_map幸福null? 突然间,您正在默默地重新创建一张空地图,而不是向其中添加条目。我敢肯定我真的不必说会由于意外状态而导致代码中完全不相关的地方出现任何数量的错误......

Edit:Just to be clear, the above answer is written in the context of Java. Other languages may (and apparently, do) differ in the implementation expense of exceptions, but other points should still hold.

编辑:明确地说,上面的答案是在 Java 的上下文中编写的。其他语言可能(并且显然确实)在异常的实现成本上有所不同,但其他点应该仍然成立。

回答by Ernest Friedman-Hill

Throwing an exception is a relatively expensive operation in C++, and an extremely expensive one in Java. On efficiency grounds alone, it never makes sense to avoid an explicit check and accept an exception instead. I suppose you might be able to justify it in some rare cases where checking whether an exception would be thrown is very complex or nearly impossible, but otherwise, I'd say the answer is "pretty much never."

抛出异常在 C++ 中是一种相对昂贵的操作,而在 Java 中则是一种极其昂贵的操作。仅从效率的角度来看,避免显式检查并接受异常是没有意义的。我想您可能会在极少数情况下证明它是合理的,在这种情况下,检查是否会抛出异常非常复杂或几乎不可能,但除此之外,我会说答案是“几乎永远不会”。

回答by AK_

This is really a discussion question, and the answer depends on the design of your system.

这确实是一个讨论问题,答案取决于您的系统设计。

My instinct is always a blanket never, but i've seen several systems implement business errors using exceptions. I personally find it disgusting, but I really understand the advantage of breaking a business process as soon as you know that it failed, handling your failure ( e.g. rolling back your Unit Of Work), and returning the error to the caller, perhaps with added information.

我的直觉永远是一个毯子,但我见过几个系统使用异常来实现业务错误。我个人觉得这很恶心,但我真的理解一旦你知道它失败就打破业务流程、处理你的失败(例如回滚你的工作单元)并将错误返回给调用者的好处,也许添加信息。

one possible disadvantage, is that it's really straightforward to do the error handling across several different classes, so that the definition of what happens when the process fails is really hard to deduce from the code.

一个可能的缺点是,跨几个不同的类进行错误处理非常简单,因此很难从代码中推断出进程失败时发生的情况的定义。

Anyway there is no single answer here, you need to weigh both approaches, and sometimes combine them.

无论如何,这里没有单一的答案,您需要权衡两种方法,有时还需要将它们结合起来。

regarding your example, I don't see any advantages for using exceptions for flow control, especially in a "good" (designed to work) scenario.

关于您的示例,我认为使用异常进行流量控制没有任何优势,尤其是在“良好”(设计为工作)场景中。

回答by AK_

There is a reason exceptions are objects. There is also a reason designers of the Java language split all Throwables into 2 main types: checked and unchecked.

异常是对象是有原因的。Java 语言的设计者将所有Throwables 分为 2 种主要类型也是有原因的:已选中和未选中。

is it a good idea to rely on an exception happening for certain business logic to occur?

依靠发生某些业务逻辑的异常是一个好主意吗?

Yes. Absolutely. You should read Chapter 9of "Effective Java, Second Edition". It's all there. Nicely explained and waiting for you.

是的。绝对地。您应该阅读“Effective Java, Second Edition”的第 9 章。这一切都在那里。很好地解释并等着你。

回答by Ma99uS

If you are dealing with an error condition which is actually a part of the business logic, it is OK to use Exceptions. For example:

如果您正在处理实际上是业务逻辑一部分的错误条件,则可以使用异常。例如:

try{
   // register new user
   if(getUser(name) != null)
      throw new MyAppException("Such user already exists");
   //other registration steps......
}catch(MyAppException ex){
   sendMessage(ex.getMessage());
}