Don*_*joe 1 doctrine domain-driven-design symfony
在Symfony 3中,您如何根据域驱动设计(DDD)区分以下内容?
我知道该学说与Symfony脱钩了(即可以完全省略)。但是,没有教义的Symfony项目中的存储库是哪一个呢?也许Symfony(没有教义)实际上不是真的遵循DDD吗?
编辑
我尝试模拟以下情况以使问题更清楚
控制器具有返回项目的所有可用经理的功能
class ManagementController
public function getAvailableManagers(Array $project)
{
...
}
}
Run Code Online (Sandbox Code Playgroud)
可用的经理意味着他们手头上没有任何项目,并且该项目属于其专业领域(例如,客户服务,业务关系,物流等)
但是,由于设计不佳,专用域未存储在数据库中,而是需要通过API调用被调用到单独的HR系统。稍后将其集成到数据库中
我本以为(随时可以纠正我)管理器应该是一个存储库类,因为它当前从2个不同的来源获取其信息。问题是……我应该为此使用教义存储库吗?还是应该只是普通实体或服务?
class ReplacementInstructionRepository extends \Doctrine\ORM\EntityRepository
{
private $id;
private $name;
private $speciality;
private $projects;
}
Run Code Online (Sandbox Code Playgroud)
我需要有关如何拆分的指南。谢谢
干杯,
尽管我对这个问题不太了解,但是这里有一些使用Symfony应用DDD原理的项目的示例。
https://github.com/PhpFriendsOfDdd/state-of-the-union/blob/master/README.md
编辑
经过您的最后描述,我想我可以给出更好的答案:-)。
我想说的是,规范模式非常适合您的情况。规范模式允许您将业务规则保留在“域”层中。在这种情况下,您提到了一条重要的业务规则:
可用的经理意味着他们手头上没有任何项目,并且该项目属于其专业领域(例如,客户服务,业务关系,物流等)
在这种情况下,您提到了我们需要处理的不良设计。在未开发的项目中,我将管理器的专用域保存在管理器中,因此所有内容都将驻留在同一聚合根(即管理器)中。
在您的情况下,我将通过存储库集成外部方(HR系统),如下所示:
nampespace xxx\infrastructure\persistence
class ManagersRepository
{
public function __construct(HrApiClient $apiClient)
{
$this->apliClient = $apiClient;
}
public function findWithoutProjects()
{
$sqlQuery = //find all managers without project
$managers = $this->execute($sqlQuery);
foreach ($managers as $manager) {
$projects = $this->apliClient->findProjectsOfManagerId($manager->id());
$manager->specialisedIn($projects); //This should be done with reflection
}
return $managers;
}
public function selectSatisfying(Specification $specification)
{
return $specification->satisfyingElementsFrom($this);
}
}
namespace xxx\Domain
class ManagersAvailableSpecification implements Specification
{
public function __construct($aNewProject)
{
$this->aNewProject = $aNewProject;
}
public function isSatisfiedBy($manager)
{
// business rules here...
if ($manager->isSpecialisedIn($this->aNewProject)) {
return true;
}
return false;
}
public function satisfyingElementsFrom(ManagersRepository $managersRepository)
{
$managers = $managersRepository->findWithoutProjects();
return array_filter(
$managers,
function (Manager $manager) {
return $this->isSatisfiedBy($manager);
}
);
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,第一类是存储库的具体实现(使用MySql,Postgre等),位于基础结构层中。尽管第二个仅取决于接口,但它与定义可用管理器的业务规则一起存在于域中。
现在您可以拥有类似的服务:
class FindAvailableManagersService
{
private $managersRepository;
public function __construct(ManagersRepository $managersRepository)
{
$this->managersRepository = $managersRepository;
}
public function execute(FindAvailableManagersRequest $request)
{
$managersAvailable = $this->managersRepository->selectSatisfying(
new ManagersAvailableSpecification($request->project())
);
return $managersAvailable;
}
}
Run Code Online (Sandbox Code Playgroud)
还要注意,如果将来您将专用域从第三方迁移到您自己的数据库,则只需修改一个类,而不会触及其他任何问题:-)