Exception 违反业务规则是否应引发异常?

Exception 违反业务规则是否应引发异常?,exception,exception-handling,rules,business-rules,Exception,Exception Handling,Rules,Business Rules,违反业务规则是否会引发异常?否。这是程序中正常条件处理逻辑的一部分(通常只是用户错误的伪装形式)。依我看,这取决于业务规则是什么。我冒昧地说“通常不会”,但我会逐案查看。我不认为有任何一个答案,因为不同的业务规则可能保证这一点,而其他规则可能不保证这一点。因为我进行验证的方式以及对LINQtoSQL for ORM的使用,是的。如果实体在OnValidate方法期间未能验证业务规则,则通知调用代码的唯一方法是引发异常。在本例中,我抛出一个自定义DataValidationException。在实

违反业务规则是否会引发异常?

否。这是程序中正常条件处理逻辑的一部分(通常只是用户错误的伪装形式)。

依我看,这取决于业务规则是什么。我冒昧地说“通常不会”,但我会逐案查看。我不认为有任何一个答案,因为不同的业务规则可能保证这一点,而其他规则可能不保证这一点。

因为我进行验证的方式以及对LINQtoSQL for ORM的使用,是的。如果实体在OnValidate方法期间未能验证业务规则,则通知调用代码的唯一方法是引发异常。在本例中,我抛出一个自定义DataValidationException。在实体的部分类实现中使用OnValidate方法钩子,使我能够在更新/插入时强制执行验证,以便只将有效数据保存到数据库中


编辑我应该明确指出,我通常在客户端对用户输入进行验证,因此持久性层验证通常更安全,很少失败。我不将客户端验证作为例外处理,而是使用条件逻辑。

例如,您的意思是,一个值应该在0-99范围内,但不知何故最终却为105

如果它来自于用户,那就是验证的问题。是否使用异常处理取决于语言的习惯用法


如果它来自您的数据存储,那么是的,抛出异常似乎是合理的。这意味着你有坏数据,你需要弄清楚它是如何到达那里的,并防止它再次发生。

抛出异常可能需要大量计算,它们超出了标准。例如,在.net中,性能计数器是递增的-这是一个重量级的活动,因此不是您想要做的事情,而是一个简单的条件。

这实际上取决于它是什么以及它在哪里

如果是来自用户的一些数据,那么正如levand所说,这是一个验证问题。验证可能会出现成功和失败两种情况,这两种情况都是预期的选项,具有明确的进一步行动方案

如果是类似于方法执行错误的情况,那么最好抛出一个异常并在造成更多伤害(例如在数据库中产生不一致)之前立即停止


这通常是一个透视图和应用程序设计的问题。

通常我将条件放在实现的规范对象中

bool IsVerfiedBy(T entity);
因此,您可以毫无例外地检查条件

如果代码中有一个地方需要事先验证规范,则可以抛出异常,因为这是函数的先决条件


例如,如果实体在持久化之前必须处于特定状态,则在规范未经验证时抛出异常,但在持久化之前使用规范,以便异常不会发生。

我会说不正常,但我认为您不能说从不


例如,这取决于谁/什么在处理失败的规则。如果它是一个用户界面/用户,那么我将使用条件逻辑适当地处理故障。但是,如果它是一个业务规则故障,例如,一个匿名流程将任何错误记录到一个事件日志中,该日志将由技术资源监控,那么异常也可能是适当的。在后一种情况下,适当命名的异常与格式良好的消息一样有用

作为大多数答案的另一种观点

从业务逻辑中抛出异常可能很有用,特别是在验证失败导致异常时。如果您需要一个对象,但得到一个空值,则表明某些问题在用户界面(或其他界面)中未被检测到。此时抛出异常可能是完全有效的。实际上,当存在多个接口时,您可能会决定将这种类型的验证放在业务逻辑中

在某些语言/框架(我认为是.NET)中抛出异常可能代价高昂,但这不应立即让您担心。这确实意味着,顾名思义,它们用于特殊情况,而不是作为程序标准流程的一部分。当然,您不应该仅仅为了退出方法而抛出异常。在可能的情况下,还应该考虑一个优美的恢复,这可能不包括抛出异常。


所以,总结一下。。。这取决于……

首先,引用《应用Microsoft.NET框架编程》(第402页)第18章中的几句话:

“另一个常见的误解是,‘异常’标识‘错误’。”

“例外情况是违反编程接口的隐式假设。”

如果我从您的问题中正确地推断出违反业务规则的数据将超出某个范围(例如),那么您可以按照@ahockley的建议使用条件来处理这个错误。根据Richter对异常的定义,如果您的代码无法从您正在使用的任何存储库中检索业务规则,则可以适当地使用异常。能够检索业务规则对于该接口来说是一个合理的隐式假设,因此如果违反此假设,则应抛出异常


Richter的第一个引号(exception!=error)的一个很好的例子是ThreadAbortException。如果调用Response.Redirect(url)(在ASP.NET中),即使重定向成功,也会引发ThreadAbortException。为什么?ASP.NET页面执行的隐含假设是页面将完全执行。Response.Redirect(url)违反了此假设,因此出现异常。

业务规则不应引发异常,除非它们用于验证某些API的参数(例如:检查)