Validation 验证数据时抛出异常是好主意还是坏主意?

Validation 验证数据时抛出异常是好主意还是坏主意?,validation,exception,Validation,Exception,验证数据时,我养成了以下习惯: 注意:我并不是每次检查都有单独的布尔值。这只是一个例子 另一个注意事项:测试期间的任何错误处理都已正确完成。try-catch中抛出的唯一异常是我自己的 try { if (validCheckOne = false) { throw new Exception("Check one is bad"); } if (validCheckTwo = false) { throw new Exception("Failed because

验证数据时,我养成了以下习惯:

注意:我并不是每次检查都有单独的布尔值。这只是一个例子

另一个注意事项:测试期间的任何错误处理都已正确完成。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);
}

这是坏习惯吗?抛出异常是否会降低程序的执行速度,或者是不可取的?

我要在这里重复一句咒语:抛出异常应该在异常情况下进行。输入的无效数据并不是那么例外。

这是一种不好的行为。例外情况适用于例外情况。它们需要资源来生成堆栈等。不应使用异常来指示流程。

这取决于-如果您希望数据在那里,而没有数据是意外的,那么抛出异常是可以的。抛出异常代价很高(速度很慢),但却是处理意外情况的最佳方法。

我支持MusiGenesis的答案

另外


抛出异常的性能是一千条指令。与最终用户时间相比,这算不了什么,但在内部代码中,它的速度很慢


另一个问题是,使用异常时,您的验证仅限于报告第一个故障(下次您必须再次进行验证才能找到下一个故障)。

一般来说,使用异常来实现条件流是不可取的。这样做会更好

  error = false;
  while(true) {
    if(validCheckOne == false) { 
       msg = "Check one is bad"; 
       error = true;
       break;
    }

    if(validCheckTwo == false) { 
       msg = "Check two is bad"; 
       error = true;
       break;
    }
    ...
    break;
  }
  if (error) {
     ..
  }
当出现无法处理的情况时,应该抛出异常。更高层的软件将有机会捕获异常并对其进行处理,即使这只是使应用程序崩溃。

在标题中,您称之为“验证”数据。这可以在几个层面上发生。在(靠近)检查用户输入数据的GUI中,您应该预期会出现错误,并且有方法报告错误。例外情况在这种情况下是不合适的


但数据验证也可以发生在其他边界,比如业务规则类之间。在那里,数据中的错误是不常见和意外的。当您检测到一个时,您应该抛出。

只有当您的数据验证处于一个紧密的循环中时,它才真正重要。在大多数情况下,选择什么并不重要,只要代码是一致的

如果您有很多代码看起来像上面的示例,那么您可能希望通过引入一个helper方法来抛出

private void throwIf( bool condition, String message )
{
    if( condition )
        throw new ApplicationException( message );
}

(此外,这样做将有助于将错误归零,例如“ValidCheckKone=false”与“ValidCheckKone==false”:)

除了经常重复的“例外情况适用于例外情况”的说法之外,我还喜欢一条进一步澄清的规则:

如果是用户造成的,也不例外


例外是针对系统端的事情(服务器停机,资源不可用),而不是针对做奇怪事情的用户,因为所有用户都做奇怪的事情。

就个人而言,我喜欢为业务规则验证抛出例外(而不是针对用户输入验证),因为这会迫使问题向上游处理。如果我的业务对象返回某种验证结果,调用方可能会忽略它。如果你愿意,可以叫我牛仔:)


这里的每个人都在重复“例外情况适用于例外情况”这句话,但这并不能解释为什么在非例外情况下使用它们是不好的。我需要的不止这些。抛出异常的性能影响真的那么糟糕吗?有可用的基准吗?

我通常同意“异常应该是异常的”规则,但我可能会为Python做一个例外(哈!),在这里使用try既有效又被认为是良好的实践。。。除了控制流量


例如,见

因此,在某些语言中,抛出和捕获异常可能是“昂贵的”,但在其他语言中,抛出和捕获异常正是需要的

例如,在Smalltalk中,可以快速构建多层异常捕获解决方案。验证过程可以收集任意数量的异常,这些异常表示特定输入数据集的所有错误。然后,它会把它们都交给一个更高级别的捕获者,负责格式化一个可读的解释,再次说明输入中的所有错误。反过来,它将抛出一个更高层次的异常,以及格式化的解释


所以。。。我想我要说的是,如果没有异常处理架构支持捕获它们并使用它们做合理的事情,那么抛出异常是不好的,而捕获者要做的就是退出或做其他同样不合适的事情。

我建议使用问题中描述的异常(对于函数中的流控制)是错误的,这通常不是最好的主意。我更进一步地说,验证引发异常不是最好的方法;相反,返回一个布尔值并存储可访问的验证错误消息列表。如果对无效对象调用,附带的save方法可能/应该引发异常

因此,如果验证失败,则可以向用户显示验证错误消息(已记录,已返回。无论什么)。如果验证通过,则可以调用save。 如果对无效对象调用save,则会获得适当的异常

示例代码的另一个潜在问题(当然取决于需求)是,它只会抛出发生的第一个验证错误。从用户角度想象一下:

  • 单击保存
  • 获取错误消息
  • 纠正错误
  • 再次单击“保存”
  • 获取不同的错误消息。令人讨厌
作为一个用户,我更喜欢t