0

Short Version:

How do you collect the results of a complicated operation that is spread over several objects?

Long Version:

I am developing a data exchange system that will push customer orders from one system to another system. This will be done via an API and unfortunately this require 12 individual steps to be completed successfully in sequence before an order can be reported as successfully transferred.

Although each step can (and has) been broken down into individual units of code, each step HAS to be completed in sequence and some steps depend on the result from previous steps.

Is there a suitable design pattern or combination of patterns that fit well for this particular problem? If each step is dependant on the previous step then whats the best way to make it aware of the previous steps result.

I was thinking of a Composite/Macro Command design or perhaps modelling the OrderPush process as a Finite State Machine although I was hoping to keep it more simple.

This is a question about system design so there is no need to go into detail on what the API is or how it works and I'm only expecting to be pointed in the right direction.

The process is to read relevant data from a local system and push to a remote system via XMLRPC.

The steps are:

  • Create Customer
  • Create Order (header record)
  • Create Order Lines
  • Confirm Order (this creates an invoice)
  • Find Invoice
  • Confirm Invoice
  • Create Payment
  • Find Journal Item (Journal item relates to the invoice so that the payment line can be tied to the invoice)
  • Create Payment Line
  • Confirm Payment

Each step is a single XMLRPC call that will either succeed or fail. And this is the crux of it. If the customer failed to be created then none of the other steps will work. Similarly if the order failed to be created then the other steps will either fail or not be able to tie together (i.e. I should obviously stop execution if any previous step fails).

So has anyone got any tips?

4

3 回答 3

1

对于任何感兴趣的人,我终于偶然发现了一种适合我需要的设计模式。

我的问题可以简化为:

您如何收集分布在多个对象上的复杂操作的结果?

(我现在已经编辑了问题)

答案是收集参数设计模式。 http://sourcemaking.com/implementation-patterns/collecting-parameter

PHP 世界中没有太多示例,尽管它不是一个非常复杂的概念。确实是常识,但我想这就是所有设计模式的本质。

我解决它的方法是通过使用抽象单个操作的命令模式实现每个单独的操作,以便我可以使用通用接口(即“process()”或“run()”方法)调用它。

鉴于我现在有 12 个操作可以使用它们自己的 process() 方法调用,我按顺序触发它们并传入一个通用对象(为清楚起见称为 CollectingParameter),其工作只是记录每个操作的结果(因此CollectingParameter 对象必须由每个 process() 方法返回)。CollectingParameter 对象被传递到下一个操作中,然后该操作将可以访问它需要从之前的操作中获得的所有结果。

$operationList = array(new CreateCustomer, new CreateOrder, new CreateOrderLines ... etc)
$collectingParameter = new CollectingParameter;
foreach($operationList as $operation) {
    $collectingParameter = $operation->process($collectingParameter);
}

在各种流程方法中记录和处理错误,从而使 process() 方法可以自由地返回 CollectingParameter 对象而不是操作结果。

于 2013-07-29T09:31:27.767 回答
1

您真正描述的是一种完成某事的算法。如果这些步骤的顺序非常重要,但有时实现可能会有所不同,那么这可能会成为模板方法,其中步骤是静态的(即顺序必须相同),但实现可能会有所不同。

您应该查看命令模式组合,以组成一棵可以作为一个例如 process() 执行的离散步骤树。您还可以查看撤消命令,如果它在流程中途失败,这对您的情况可能很重要。

于 2013-07-29T09:51:00.633 回答
0

您如何做到这一点取决于您是否需要在故障点停止,或者如果任何部分发生故障,您是否希望取消整个批次。

对于前者,这很简单 - 只需在每个步骤中进行测试,如果有任何失败,则生成错误报告。

后者有点困难,取决于您使用的数据库。对于INNODB模式下的Mysql,你可以使用事务,在启动一系列事务之前关闭auto_commit,如果成功则在最后提交,如果不成功则回滚事务。

如果您提供有关您希望使用的数据库和访问权限的更多信息,您可能会获得更多帮助。我将 mysqli 和 mysql 用于我的代码,并且在创建具有跨多个数据库表的信息的用户时发现这很方便。

于 2013-07-18T10:23:29.357 回答