【问题标题】:Domain Driven Design and batch processing领域驱动设计和批处理
【发布时间】:2015-03-30 11:59:19
【问题描述】:

具有以下结构:

  1. 演示级别:

    Web 界面、REST API 和命令提示符 - 都只调用 OrderService。

  2. 应用层:

    class OrderService
    {
      private $em;
      private $repository;
      private $calculator;
    
      public function __construct(
          \Doctrine\ORM\EntityManagerInterface $em;
          ClientRepositoryInterface $repository,
          cumulativeDiscountCalculator $calculator
      } {
          $this->em = $em;
          $this->repository = $repository;
          $this->calculator = $calculator;
      }
    
      public function calculateCumulativeDiscount($id)
      {
          $this->em->beginTransaction();
          try {
              $client = $this->repository->findClient();
              $this->calculator->calculate($client);
    
              $this->em->flush();
              $this->em->commit();
          } catch (\Exception $e) {
              $this->em->rollback();
    
              throw $e;
          }
      }
    }
    
  3. 模型层:

    interface ClientInterface
    {
        public function setDiscount($discount);
    }
    interface ClientRepositoryInterface
    {
        public function findClient($id);
        public function findClientsByDataRange($from, $to);
    }
    class cumulativeDiscountCalculator
    {
        public function calculate(ClientInterface $client)
        {
            $client->setDiscount(mt_rand(1, 50));
        }
    }
    
  4. 基础设施层:

    PHP Doctrine 2 - 实现 ClientRepositoryInterface。

我的任务 - 为一组客户执行计算折扣。 (ClientRepositoryInterface::findClientsByDataRange方法返回集合进行处理)

问题是我需要处理多达 100,000 条记录。我知道如何在技术上做到这一点,但如何在 DDD 方面做到这一点?出现以下问题:

  • 批处理使用哪个层?
  • 如何收集操作的结果:错误、成功客户端计数等?
  • 在哪里设置事务边界(每 N 个客户端 - 提交并开始一个新事务)?
  • 我有大约 10-20 个批处理操作,开发任何结构可能有意义吗?

【问题讨论】:

  • 您必须向我们提供有关域操作本身的更多信息。有没有不变量?什么是用来计算折扣的?为什么所有这些折扣必须一起计算?仅仅是为了方便吗?什么会触发折扣?
  • 每月(第一天)计算一次折扣。折扣的计算有很多规则。我有许多类似的(批量)操作,例如:删除特定制造商的所有产品、更改所有价格等。它们是否正确执行?对一般情况感兴趣。

标签: php doctrine-orm domain-driven-design batch-processing


【解决方案1】:

在我看来,您应该将批处理操作视为您域的一部分,而不仅仅是一些“琐碎”的操作。写下需求,你会发现它也需要一些领域建模。例如。您需要存储有关每个批次运行的基本数据(类型、时间、处理的记录数、结果、相关错误等),然后您需要具有预览和计划它们的功能(何时、哪个批次运行、重新运行等)。您可能需要一些工具来根据时间或资源(每次运行需要多长时间,需要多少内存等)来监控它们。

从你上面提到的我可以想象出这样的类:

  • BatchRunner
  • 批处理接口
  • ClientDiscountBatch { $scheduleDay, $scheduleTime }
  • BatchResultEntity { $itemProcessed, $itemErrors, $maxMemory, $duration }
  • BatchResultRepository
  • ...

然后您的每个批处理操作都将实现 BatchInterface 并由 BatchRunner 管理,结果将由 BatchResultRepository 等持久化。

所有操作都将使用您上面提到的其他域类,例如。累积折扣计算器。

在事务边界方面,您继续使用现有边界 - 例如。聚合根。每次迭代后,您都会增加结果数量或记录错误。

【讨论】:

    猜你喜欢
    • 2012-07-18
    • 1970-01-01
    • 1970-01-01
    • 2016-09-29
    • 1970-01-01
    • 1970-01-01
    • 2011-10-06
    • 2011-06-21
    • 2016-07-18
    相关资源
    最近更新 更多