我为我的应用程序不期望的每个条件创建了异常。UserNameNotValidException, PasswordNotCorrectException等。

然而,我被告知我不应该为这些条件创造例外。在我的UML中,那些是主要流程的异常,那么为什么它不应该是异常呢?

是否有创建异常的指导或最佳实践?


当前回答

for me Exception should be thrown when a required technical or business rule fails. for instance if a car entity is associated with array of 4 tires ... if one tire or more are null ... an exception should be Fired "NotEnoughTiresException" , cuz it can be caught at different level of the system and have a significant meaning through logging. besides if we just try to flow control the null and prevent the instanciation of the car . we might never never find the source of the problem , cuz the tire isn't supposed to be null in the first place .

其他回答

抛出异常会导致堆栈unwind,这对性能有一定影响(承认,现代托管环境在这方面有所改进)。仍然在嵌套的情况下反复抛出和捕获异常是一个坏主意。

可能比这更重要的是,例外是针对特殊情况的。它们不应该用于普通的控制流,因为这会损害代码的可读性。

一般来说,你想要为应用程序中可能发生的任何异常抛出一个"异常"

在您的示例中,这两个异常看起来都是通过密码/用户名验证调用的。在这种情况下,有人会输入错误的用户名/密码并不是什么例外。

它们是UML主要流程的“例外”,但在处理过程中是更多的“分支”。

如果您试图访问您的passwd文件或数据库,但无法访问,这将是一个异常情况,并需要抛出异常。

异常类就像“正常”类。当一个新类“是”一个不同类型的对象,具有不同的字段和不同的操作时,您可以创建一个新类。

As a rule of thumb, you should try balance between the number of exceptions and the granularity of the exceptions. If your method throws more than 4-5 different exceptions, you can probably merge some of them into more "general" exceptions, (e.g. in your case "AuthenticationFailedException"), and using the exception message to detail what went wrong. Unless your code handles each of them differently, you needn't creates many exception classes. And if it does, may you should just return an enum with the error that occured. It's a bit cleaner this way.

我的小指南很大程度上受到了“代码完成”这本伟大的书的影响:

使用异常来通知不应该被忽略的事情。 如果错误可以在本地处理,就不要使用异常 确保异常与例程的其余部分处于相同的抽象级别。 异常应该留给真正的异常。

To my mind, the fundamental question should be whether one would expect that the caller would want to continue normal program flow if a condition occurs. If you don't know, either have separate doSomething and trySomething methods, where the former returns an error and the latter does not, or have a routine that accepts a parameter to indicate whether an exception should be thrown if it fails). Consider a class to send commands to a remote system and report responses. Certain commands (e.g. restart) will cause the remote system to send a response but then be non-responsive for a certain length of time. It is thus useful to be able to send a "ping" command and find out whether the remote system responds in a reasonable length of time without having to throw an exception if it doesn't (the caller would probably expect that the first few "ping" attempts would fail, but one would eventually work). On the other hand, if one has a sequence of commands like:

  exchange_command("open tempfile");
  exchange_command("write tempfile data {whatever}");
  exchange_command("write tempfile data {whatever}");
  exchange_command("write tempfile data {whatever}");
  exchange_command("write tempfile data {whatever}");
  exchange_command("close tempfile");
  exchange_command("copy tempfile to realfile");

人们会希望任何操作的失败都能中止整个序列。虽然可以检查每个操作以确保操作成功,但如果命令失败,让exchange_command()例程抛出异常会更有帮助。

实际上,在上面的场景中,有一个参数来选择一些失败处理模式可能会有所帮助:从不抛出异常,仅为通信错误抛出异常,或者在命令没有返回“成功”指示的任何情况下抛出异常。