业务规则的违反是否应该抛出异常?

20

业务规则违反是否应该抛出异常?


啥?这对我来说并不清楚! - Maurice Flanagan
为什么“exceptional”要大写?请定义“exceptional”。 - alphadogg
5
我理解他的意思是“违反业务规则会导致持久层抛出异常,还是您通过返回值处理成功/失败。” - tvanfosson
14个回答

18

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


2
那么,在需要同步响应的应用程序中,您如何通知用户界面业务规则已被违反?例如,桌面应用程序。 - devanalyst

8

我认为这取决于具体的业务规则。一般来说,我倾向于认为不需要使用html标签,但需要根据具体情况来判断。不同的业务规则可能需要使用,而有些则可能不需要。


6

首先,摘自Jeffrey Richter的《应用Microsoft .NET Framework编程》第18章(第402页)的两个引用:

"另一个常见误解是'异常'标识了'错误'。"

"异常是违反编程接口隐含假设的行为。"

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

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

4
由于我的验证方式以及使用LINQtoSQL进行ORM,如果实体在OnValidate方法期间的业务规则上失败,则通知调用代码的唯一方法是抛出异常,我会抛出一个自定义的DataValidationException。通过在实体的部分类实现中使用OnValidate方法钩子,使我能够在更新/插入时执行验证,以便只有有效数据才保存到数据库。
编辑:我应该明确表示,我通常在客户端对用户输入进行验证,因此持久层验证通常更像是保险,很少失败。我不会将客户端验证作为异常处理,而是使用条件逻辑来处理。

3

你的意思是,比如说一个值应该在0-99的范围内,但最终却变成了105?

如果这个值是来自用户输入,那么就需要进行验证。是否使用异常处理取决于你所使用语言的惯例。

如果这个值来自于你的数据存储,那么抛出异常似乎是合理的。这意味着你有错误的数据,需要找出它是怎么出现的,并防止再次发生。


3
不违反业务规则是一个商业问题,而异常是技术问题。违反业务规则应被系统视为正常操作,并应有编程响应,而不是异常。

2
作为大多数答案的替代观点,从业务逻辑中抛出异常可能是有用的,特别是如果它们由验证失败引起。如果您期望得到一个对象,但是得到了null,那么这表明某些问题已经逃脱了用户界面(或其他界面)的检测。此时抛出异常可能是完全有效的。实际上,在存在多个接口时,您可能决定将此类验证放在业务逻辑中。
在某些语言/框架中(我正在考虑.NET),抛出异常可能是代价高昂的,但这不应立即让您担心。这意味着,正如名称所示,它们用于异常情况,而不是程序的标准流程的一部分。您绝不能仅仅为了退出一个方法而抛出异常。在可能的情况下,您还应考虑优雅的恢复,这可能不包括抛出异常。
因此,总结一下...... 这取决于......

1

业务规则可能会引发异常,但它们不应该这样做。

如果您有另一种方式来传递有关常见和可预测的验证错误信息,您应该使用它。


1

我认为通常情况下不会这样做,但我不认为你可以说永远不会这样做。

例如,这取决于谁/什么来处理失败的规则。如果是用户界面/用户,则我会使用条件逻辑来适当地处理失败。然而,如果是业务规则失败,例如在一个无面孔的过程中记录任何错误到事件日志中,将由技术资源监视,则异常可能同样适用。在后一种情况下,一个恰当命名的异常可以像一个漂亮格式化的消息一样有帮助。


0

在《97件每个项目经理都应该知道的事情》这本书的维基百科中有很好的指导,特别是在区分业务异常和技术异常这一章节中。

因此,如果您的编程语言支持它,最好创建自定义异常类,以便它们的工作流程和处理方式与技术异常不同。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接