Имеет следующую структуру:
Уровень презентации:
Веб-интерфейс, REST API и командная строка — все они вызывают только OrderService.
Уровень приложений:
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;
}
}
}
Модельный слой:
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));
}
}
Уровень инфраструктуры:
PHP Doctrine 2 — реализовать ClientRepositoryInterface.
Моя задача — выполнить расчет скидок для коллекции клиентов.
(метод ClientRepositoryInterface :: findClientsByDataRange возвращает коллекцию для обработки)
Проблема в том, что мне нужно обработать до 100 000 записей. Я знаю, как это сделать технически, но как это сделать с точки зрения DDD? Возникают следующие вопросы:
По моему мнению, вы должны рассматривать пакетную операцию как часть вашего домена, а не просто как «тривиальную» операцию в стороне. Запишите требования, и вы увидите, что для этого также требуется некоторое моделирование предметной области. Например. вам нужно хранить базовые данные о каждом пакетном запуске (тип, когда, сколько записей обработано, результаты, связанные ошибки и т. д.), а затем вам нужно иметь возможность просматривать и планировать их (когда, какой пакетный запуск, повторный запуск и т. д.) ). Возможно, вы захотите иметь какой-нибудь инструмент для мониторинга их с точки зрения времени или ресурсов (сколько времени занимает каждый запуск, сколько памяти занимает и т. Д.).
Из того, что вы упомянули выше, я могу представить себе такие классы, как:
Тогда каждая из ваших пакетных операций будет реализовывать BatchInterface и будет управляться BatchRunner, а результаты будут сохраняться BatchResultRepository и т. Д.
Все операции будут использовать другие классы домена, как вы упомянули выше, например. CumulativeDiscountCalculator.
В терминах границ транзакций вы продолжаете использовать существующие границы — например. Совокупный корень. После каждой итерации вы увеличиваете количество результатов или регистрируете ошибку.
Других решений пока нет …