在验证数据时抛出异常是好还是坏?

MoS*_*Slo 62 validation exception

在验证数据时,我养成了做以下事情的习惯

*注意:我每次检查都没有真正的布尔值.这只是一个例子.

*另一个注意事项:测试期间的任何错误处理都已正确完成.try-catch中抛出的唯一异常是我自己的.

try {
  if (validCheckOne = false) {
    throw new Exception("Check one is bad");
  }
  if (validCheckTwo = false) {
    throw new Exception("Failed because of check2");
  }
  if(validCheckTen = false) {
    throw new Exception("Yet another failure on your part: check10.");
  }
} catch(Exception e) {
  MessageBox.Show("Your stupid data is wrong! See for yourself: " + e.Message);
}
Run Code Online (Sandbox Code Playgroud)

这是不好的做法吗?抛出异常会减慢程序的执行速度还是不可取的?

Jon*_*noW 60

就个人而言,我喜欢为业务规则验证抛出异常(而不是用户输入验证),因为它会强制在上游处理问题.如果我的业务对象返回了某种验证结果,则调用者可以忽略它.如果你愿意,叫我牛仔:)

这里的每个人都在重复"例外情况适用于特殊情况"这一短语,但实际上并没有理解为什么在特殊情况下使用它们是不好的.我需要更多.抛出异常的性能是否真的那么糟糕?有没有可用的基准?

  • *"例外是针对特殊情况"*在我看来,这是一个被误解的引用.您的操作**无法继续**因为不符合业务规则,对于这么多人来说,这怎么不是特例? (4认同)
  • 对于应用程序程序员来说,习惯于仅几个特定的​​异常并适当地使用它们是很直观的,而不是使各种自发明的返回码甚至字符串混乱。我喜欢在上游放置异常处理程序的想法,这些处理程序可以完成它们的工作-将严重错误记录到数据库中,向系统管理员发送电子邮件,向最终用户显示有意义的消息,等等。服务器端数据验证也可以被认为是现代Web应用程序的例外,因为基本输入验证通常可以使用Javascript完成。 (3认同)
  • [this](http://stackoverflow.com/a/6828204/618281)答案描述了为什么在特殊情况下使用它们是不好的.简而言之,它会强制您处理异常,现在您必须区分SQL异常和验证异常.我不会像验证框架的可维护性那样关注性能. (2认同)
  • 验证应该与命令分开。第一个只是在更改系统状态之前检查数据是否有效,因此应该只返回验证结果。另一个实际上是在改变系统的状态,应该接收经过验证的数据。当验证的数据由于系统中的其他更改而不再有效时,这是抛出异常的好时机。 (2认同)

Mus*_*sis 33

我将在这里重复咒语:应该在特殊情况下抛出异常.无效的输入数据确实不是那么特别.

  • 典型的StackOverflow:解决困难,有趣的问题,然后让你的大部分代表成为第一个嘲笑一些简单规则的人.叹. (51认同)
  • 我从不同意这个口头禅,尤其是像Java这样的语言,带有检查异常(你可以强制调用者处理你的异常).另一种方法是返回错误并将错误处理程序滚动到调用者.为什么你会选择实现一个自定义错误处理程序,而不是以一种不仅可能比你要做的更好的语言免费获得一个好的实现错误处理程序,而是给你(用一种带有检查异常的语言)编译器执行 (21认同)
  • 这是一个关于文字的游戏,我还没有阅读任何有说服力的论据,为什么应该是这样的.使用异常并捕获它们可以真正清理代码,尤其是在多层系统中. (4认同)
  • 不同意,有时用户输入内容会破坏业务规则(并非所有用户输入验证都是关于检查他们输入的有效电子邮件地址等).在这种情况下,在应用程序代码中抛出异常,处理它然后从中显示验证错误. (3认同)
  • 这很糟糕,假设验证只针对"输入"数据,很可能是你在网络服务中工作,无效数据确实非常特殊,应该这样对待......我认为问题更有趣语义,比如,如果条件失败,断言必须抛出异常,通过语义,我们对验证有类似的理解吗?它应该返回true还是false或者抛出异常?似乎没有答案 (2认同)

KLE*_*KLE 20

我支持MusiGenesis的回答.

另外...


抛出异常的表现是一千条指令.与最终用户时间相比,它没什么,但在内部代码中它很慢.

另一个问题是,使用例外,您的验证仅限于报告第一次失败(并且您将不得不在下次再次完成所有操作以查找下一次失败).

  • 最后一点是不正确的。您可以执行所有验证并将所有错误消息保存在自定义验证对象(或 C# `ValidationResult`)中。然后,您可以抛出一个自定义异常(或 C#“ValidationException”),其中包含自定义验证对象(“ValidationException(ValidationResult, ValidationAttribute, Object)”)。 (4认同)

Dom*_*ger 13

除了经常重复的声明"例外是针对特殊情况"之外,这里还有一个额外的澄清规则:

如果用户造成它,那也不例外.

例外情况是系统方面的事情(服务器停机,资源不可用),而不是用户做奇怪的事情,因为所有用户都做奇怪的事情.

  • 但是,如果我在客户端(Web 浏览器)的 Web 应用程序中有一些基本验证怎么办?那么服务器端验证不能被视为例外吗?通常不希望用户绕过 Javascript 验证,因此为什么要使用多个错误代码、带有中断的奇怪循环、`if`s 和什么不是,如果抛出 `DataValidationException` 很诱人,然后将显示给用户作为一些通用消息“字段 X 的值错误”。 (2认同)
  • 这与我正在思考的问题相同。建立一个列表中的所有错误并抛出一个异常。然后你可以有一个通用的方法来处理它们,你只写一次。否则,编码器必须处理每个调用的响应,重复代码和错过检查的可能性。 (2认同)

Hen*_*man 7

在标题中,您将其称为"验证"数据.这可能发生在几个层面上.在您检查用户输入数据的GUI中(接近),您应该期待错误并有办法报告错误.在这种情况下,例外是不恰当的.

但是数据验证也可以发生在其他边界,比如业务规则类之间.在那里,数据中的错误是不常见和意外的.当你发现一个时,你应该扔掉.


TLi*_*ebe 6

这取决于 - 如果您希望数据存在并且没有数据是意外的,那么抛出异常就可以了.抛出异常非常昂贵(缓慢)但是处理意外情况的最佳方法.