在多层体系结构中执行批量操作时处理错误和反馈

Ada*_*kin 12 error-handling business-logic bulk-operations

假设您有一个可以跨多个对象执行某些操作的业务逻辑方法.也许您想要为从列表中选择的每个人拨打一个抽奖号码选择网络服务.在Java中,代码可能如下所示:

Set<Person> selectedPeople = ... // fetch list of people
for ( Person person : selectedPeople ) {
    String lotteryNumber = callLotteryNumberWebService( person );
    // ...
}
Run Code Online (Sandbox Code Playgroud)

注意,彩票号码网络服务可能具有副作用,例如记录该人已请求彩票号码(可能对他们的账户收费),因此即使一个人的网络服务呼叫失败,其他人也可能成功.这些信息(彩票号码)需要反馈到更高级别(视图).

如果这是发生单个操作的情况,则业务逻辑方法可以返回单个值(例如,抽奖号码)或抛出异常以及失败的任何细节.但对于批量操作,一些操作可能会成功,一些操作可能会失败.

这似乎是许多应用程序中会出现的一种问题,应该有一种干净的方法来处理它.那么,将这种类型的信息从业务逻辑层反馈到应用程序中的另一层(如视图)的最佳方法是什么,最好是以可以重用于不同类型的数据和操作的通用方式?

Dan*_*anO 10

这个问题强调了异常处理,交易和想法工作流程"补偿"之间的重要区别,这是提问者试图获得的,当正确陈述时:

这似乎是许多应用程序中会出现的一种问题,应该有一种干净的方法来处理它.

这是一个常见问题,首先是您正在尝试的事务方法的一些背景知识:

数据交易最初是在复式会计后建模的 - 单个信用卡和相应的借记卡必须一起记录或根本不记录.随着事务变得越来越大,它们正确地实现越来越成问题,并且更难以处理失败.当您开始跨系统边界传递单个事务的想法时,您很可能接近它是错误的.它可以完成,但需要复杂且必然更高延迟的事务协调器.在某种程度上,交易是错误的心态,补偿开始变得更有意义.

这是您回过头来看看业务实际做了什么的地方.单个大型交易很可能不是商务人士看到的方式.通常他们会看到已完成的步骤,并且根据后续结果,可能需要采取不同的补偿措施.这就是工作流和薪酬的概念所在. 这是对这些概念的一个介绍

例如,如果您从亚马逊订购图书,他们可能不会在购物车中"锁定"记录,甚至在确认订单时使用严格的交易来确定图书是否仍然有库存.无论如何,他们会把它卖给你,并在可能的时候发货.如果他们在几周内没有设法将其存入库存,他们可能会向您发送一封电子邮件,告诉您他们正在努力满足您的需求,并且您可以继续等待他们将其存入库存,或者您可以取消您的订单.这称为补偿,在许多实际业务流程中都是必需的.

最后,没有任何例外.期望这可能发生并使用正常的控制流程.您不应该在此处使用您的语言的异常处理功能(何时抛出异常的良好规则).您也不应该依赖特定于工具(WCF?)的机制来查看或处理服务实现中发生的异常.沟通故障应该是数据合同的正常部分(故障合同).

不幸的是,通过"干净的方式来处理它"没有设置的标志会神奇地处理它,你必须继续分解问题并处理所有产生的碎片.希望这些概念能够将您与其他人在处理此问题时所做的事情联系起来.

摘要:

  • 您的问题超出了交易的概念 - >查看工作流程补偿.

祝好运 -


Sco*_*zie 2

如果我理解,您会遇到一些请求可以通过而有些请求可能失败的情况。我不确定您希望错误在哪里返回,但您可能有以下其中一项(或变体,或组合):

  • 错误和受影响的域对象的列表。基本域对象或具有持久 ID 的对象可能有助于重用。例如,涉及域对象的错误集合。
  • 您可以将某种错误对象/消息(AOP、DI)注入到 Person 对象中。例如 if (person.Errors){...}
  • 您可以将 Person 集合包装到带有标头、正文、错误信息的消息中
  • 您的所有域对象都可以包含可通过接口访问的错误集合;或 Person 支持 IHasErrors 接口。您可以使其通用并使用支持警告和验证以及所有方式的基本 Error 对象。

如果您处于真正的多层(而不是分层)系统中,那么您可能拥有一个基于消息的体系结构,可以轻松容纳某种通用错误/警告/验证机制。SOA/Ajax 系统适合于此。

如果您有一些具体问题,很乐意更深入地研究。