违反业务规则是否应该引发异常?
14 回答
不,它是程序中正常条件处理逻辑的一部分(通常只是用户错误的一种伪装形式)。
这取决于业务规则是什么,IMO。我会冒昧地说“不经常”,但我会根据具体情况来看待它。我不认为有任何一个答案,因为不同的业务规则可能需要它,而其他规则可能不会。
首先,引用Jeffrey Richter的 Applied Microsoft .NET Framework Programming(第 402 页)的第 18 章:
“另一个常见的误解是‘异常’标识了‘错误’。”
“一个例外是违反编程接口的隐含假设。”
如果我从您的问题中正确推断出违反业务规则的数据将超出某个范围(例如),那么您可以使用@ahockley 建议的条件来处理此错误。根据 Richter 对异常的定义,如果您的代码无法从您正在使用的任何存储库中检索业务规则,则适当使用异常。能够检索业务规则将是该接口具有的合理隐含假设,因此如果违反此假设,则应抛出异常。
Richter 的第一句话(异常!= 错误)的一个很好的例子是 ThreadAbortException。如果调用 Response.Redirect(url)(在 ASP.NET 中),即使重定向成功,也会引发 ThreadAbortException。为什么?ASP.NET 页面执行的隐含假设是页面将完全执行。Response.Redirect(url) 违反了这个假设,因此例外。
由于我进行验证的方式以及我对 ORM 的 LINQtoSQL 的使用,是的。如果实体在 OnValidate 方法期间未能通过业务规则验证,则通知调用代码的唯一方法是抛出异常。在这种情况下,我抛出了一个自定义 DataValidationException。在实体的部分类实现中使用 OnValidate 方法挂钩使我可以对更新/插入强制执行验证,因此只有有效的数据才会保存到数据库中。
编辑我应该明确一点,我通常会在客户端验证用户输入,因此持久层验证通常更保险,并且很少(如果有的话)失败。我不将客户端验证作为异常处理,而是使用条件逻辑处理。
否 违反业务规则是业务问题,例外是技术问题。违反业务规则是系统应该将其视为正常操作并且应该有程序响应的事情,而不是例外。
你的意思是,例如,一个值应该在 0-99 范围内,但不知何故最终是 105?
如果它来自用户,那就是验证问题。是否使用异常处理取决于您的语言习语。
如果它来自您的数据存储,那么是的,抛出异常似乎是合理的。这意味着你有错误的数据,你需要弄清楚它是如何到达那里的,并防止它再次发生。
作为大多数答案的另一种观点......
从业务逻辑中抛出异常可能很有用,特别是如果它们是由验证失败引起的。如果您期待一个对象并且您得到一个空值,则表明某些问题已在用户界面(或其他界面)中规避了检测。此时抛出异常可能是完全有效的。实际上,当有多个接口时,您可能会决定将这种类型的验证放在业务逻辑中。
在某些语言/框架(我认为 .NET)中抛出异常可能代价高昂,但这不应该立即让您担心。顾名思义,这确实意味着它们用于特殊情况,而不是作为程序标准流程的一部分。你当然不应该仅仅为了退出一个方法就抛出一个异常。您还应该尽可能考虑优雅的恢复,其中可能不包括引发异常。
所以,总结一下......这取决于......
我通常会说不是,但我认为你不能说从不。
例如,它取决于谁/什么正在处理失败的规则。如果它是用户界面/用户,那么我将使用条件逻辑来适当地处理故障。但是,如果它是业务规则失败,例如,将任何错误记录到将由技术资源监控的事件日志的不露面流程中,则异常可能是适当的。在后一种情况下,适当命名的异常可能与格式良好的消息一样有用。
业务规则不应抛出异常,除非它们用于验证某些 API 的参数(即:检查请求有效性)或用于单元测试(即:使用业务规则来简化 .NET 单元测试)。
不过,通常业务规则会向验证范围输出错误和警告消息。
通常我将条件放在实现的规范对象中
bool IsVerfiedBy(T entity);
因此,您可以毫无例外地检查条件。
如果您的代码中有一个地方应该事先验证规范,您可以抛出异常,因为这是您的功能的先决条件。
例如,如果您的实体在持久化之前必须处于特定状态,则在未验证规范时抛出异常,但在持久化之前使用规范,以便不会发生异常。
抛出异常可能是计算密集型的,它们超出了规范。例如,在 .net 中,您有递增的性能计数器 - 这是一个重量级的活动,因此不是您想要做的事情,而不是简单的条件。
这实际上取决于它是什么以及它在哪里。
如果是来自用户的一些数据,那么正如 levand 所说,这是一个验证问题。验证可以成功也可以失败,两者都是具有明确进一步行动方案的预期选项。
如果它类似于方法执行错误,最好在造成更多伤害之前抛出异常并停止(例如在数据库中产生不一致)。
这通常是一个观点和您的应用程序设计的问题。
业务规则可以抛出异常,但它们不应该。
如果您有另一种方式来传达有关常见和可预测的验证错误的信息,您应该使用它。