我看到的大多数DDD示例都是用Java编写的,绝大多数使用Hibernate来持久化和获取实体.我真的没有任何经验,我假设Hibernate是一个足以解决依赖关系,处理值对象等的工具.我选择的ORM是Doctrine2,据我所知这是PHP目前最好的工具,但我认为支持DDD原则还不够.
以下是域层的示例:
/**
* Simple value object
*/
class ProductId
{
private $value;
function __construct($value)
{
$this->value = $value;
}
public function value()
{
return $this->value;
}
}
/**
* Example dependency
*/
class Dependency
{
public function doNothing()
{
}
}
/**
* Game class done in a DDD manner
*/
class Game
{
/**
* @var ProductId
*/
private $id;
/**
* @var string
*/
private $title;
/**
* @var Dependency
*/
private $dependency;
function __construct(ProductId $id, $title, Dependency $dependency)
{
$this->id = $id;
$this->title = $title;
// Validation
Assertion::minLength(25, $title);
}
/**
* @return ProductId
*/
public function getId()
{
return $this->id;
}
/**
* @return string
*/
public function getTitle()
{
return $this->title;
}
public function someBehavior()
{
$this->dependency->doNothing();
}
}
现在使用Doctrine,您可以使用XML或YAML映射映射Game
到某个表.然而,在调用$gameRepository->productOfId($someId);
你会得到的是一个格式错误的对象.原因如下:
由于Doctrine2不支持的值对象,打电话时getId()
,你会得到一个简单的int
,因为它的映射将指向一个整数列.最新的beta有点支持它们,但它仍然不是很灵活,在更复杂的场景中也不容易配置.
由于Doctrine2在调用someBehavior()
获取的实体时创建用于检索的代理对象,因此代理对象无法解析构造函数依赖性,因此会出现致命错误.这可以通过创建一些DomainRegistry
单例并从那里获得依赖来实际克服,但我真的不喜欢那些暗示在我身上.但是我们仍在跳过验证,因为没有调用构造函数,我不会仅仅依赖于数据库完整性.
我应该如何克服这个问题?我宁愿不在if is int return ProductId(int)
我的域模型中使用一些东西,因为我希望我的域层是持久性 - 无知的.
我想到的一件事是(假设我会坚持使用ORM,而不仅仅是DBAL)来处理像DTO这样的Doctrine实体(我希望我在这里正确使用该术语)并从中组装域对象.所以除了提到的课程,我还有类似的东西:
/**
* Doctrine entity treated like a pure value container
*/
class GameDTO
{
private $id;
private $title;
/**
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* @return string
*/
public function getTitle()
{
return $this->title;
}
}
class DoctrineGameRepository
{
/**
* @var Dependency
*/
private $dependency;
/**
* Doctrine's entity manager
*/
private $em;
function __construct(Dependency $dependency, $em)
{
$this->dependency = $dependency;
$this->em = $em;
}
public function productOfId($id)
{
/** @var GameDTO $gameDto */
$gameDto = $this->em->find($id);
return new Game($gameDto->getId(), $gameDto->getTitle(), $this->dependency);
}
}
这样我就克服了基础设施的限制,但它增加了另一层复杂性.另外,我应该如何处理需要反映到我的DTO的对象的更改,以便我可以更新我的数据库?
我的第二个想法是改编CQRS,但这对我来说只是一个流行语,因为我还没有对它进行太多的研究.我知道它的原则,但我不知道我应该为哪个类和存储库建模.
你会如何处理所有这些?