【发布时间】:2021-10-12 15:36:22
【问题描述】:
我目前正在使用 DDD,我有一个关于应用程序服务 VS 域服务 VS 存储库接口的问题
据我所知:
-
应用程序服务用于处理用例流,包括域之上所需的任何其他问题。
-
域服务用于封装不适合单个域对象的行为。
因此,例如,考虑到这个用例:
"当您在系统中创建新的汽车实体(uuid,name) 时,汽车名称必须是唯一的(不存在具有此名称的汽车)或者汽车名称不能包含数据库中的另一个汽车名称作为子字符串“例如,这只是一个用例示例,它迫使我在创建对象时查看存储库中的其他实体
所以问题是:我应该在哪里进行检查和/或注入存储库接口?
- 选项 1) 在应用程序服务中,注入 RepositoryCarInterface,进行检查并保存 Car:
class CreateCarApplicationService
{
private carRepositoryInterface $carRepository;
public function __construct(CarRepositoryInterface $carRepository)
{
$this->carRepository = $carRepository;
}
public function __invoke(string $carUuid, string $carName): void
{
$this->ensureCarNameIsUnique($CarName);
$car = new Car($carUuid,$carName);
$this->carRepository->save($car);
}
private function ensureCarNameIsUnique(string $carName): void
{
$CarSameName = $this->carRepository->findOneByCriteria(['name' => $carName]);
if ($carSameName) {
throw ExceptionCarExists();
}
}
}
- 选项 2) 将此逻辑创建到域服务中(目的是使域逻辑靠近域对象)并从具有最终责任的更简单的应用程序服务中调用它保存与数据库交互的模型:
class CreateCarDomainService
{
private carRepositoryInterface $carRepository;
public function __construct(carRepositoryInterface $carRepository)
{
$this->carRepository = $carRepository;
}
public function __invoke(string $carUuid, string $carName): Car
{
$this->ensureCarNameIsUnique($CarName);
return new Car($carUuid,$carName);
}
private function ensureCarNameIsUnique(string $carName): void
{
$CarSameName = $this->carRepository->findOneByCriteria(['name' => $carName]);
if ($carSameName) {
throw ExceptionCarExists();
}
}
}
class CreateCarApplicationService
{
private carRepositoryInterface $carRepository;
private CreateCarDomainService $createCarDomainService;
public function __construct(CarRepositoryInterface $carRepository)
{
$this->carRepository = $carRepository;
$this->createCarDomainService = new CreateCarDomainService($carRepository)
}
public function __invoke(string $carUuid, string $carName): void
{
$car = $this->createCarDomainService($carUuid,$carName);
$this->carRepository->save($car);
}
}
我不太确定将存储库接口注入域服务的事实,因为正如 Evans 所说:
一个好的服务具有三个特征:
-该操作与不是实体或值对象的自然部分的域概念有关
-接口是根据领域模型的其他元素定义的
-操作是无状态的
但我想把我的领域逻辑推到我无法做到的深度
而且,正如我在其他 StackOverflow 帖子中所读到的,不允许/推荐在域对象中注入存储库:
【问题讨论】:
标签: dependency-injection repository domain-driven-design