你好stackoverflow成员,
我正在使用纯PHP来实现域模型。我有两个实体,实体dog
和实体human
,是狗的主人。
这是一个多对多的关系。一个owner
可以有多个dog
,而一个dog
由许多humans
拥有(假设这只狗属于一个家庭或一对夫妇)。
我有一个dog
和human
的数据库表以及n:n连接表。我有两个实体,即POPO。而且我还有两个存储库,一个用于dog
,一个用于human
。这些存储库具有原始操作,并负责数据库查询。
哪个存储库负责管理n:n表?
实体dog
具有一个属性数组,该属性数组包含所有连接的human
,反之亦然。如果我创建一个像human
这样的新$human = new Human('name');
并让他拥有一个像dog
这样已经存在的$human->addDog($dog);
,谁来负责n:n连接?
我可以执行$dogRepo->Update($human->getDogs()[0]);
来更新数据库中的狗,也可以执行$humanRepo->Insert($human)
。 DogRepo是否也应该插入新的human
(利用HumanRepo)? HumanRepo是否还应该更新dog
(利用DogRepo)。还是业务逻辑对此负责? (分别从业务逻辑中调用insertHuman()
和updateDog()
)。
在所有这些方法上,我都不知道哪个存储库对n:n表负责?
听起来像是一个常见问题,但我在网络上找不到合适的解决方案。
谢谢!
答案 0 :(得分:1)
在DDD中,我们根据业务规则设计汇总。每个集合保护自己的不变量。设计它们时,我们的头脑中没有表或关系表,只有不变性和一致性要求。
话虽这么说,但您遇到了困难,因为您尚未确定不变式或没有不变式。
养狗的人的行为是否有某些特殊行为?如果人类没有/没有狗,是否会拒绝某些人类命令?然后,您将{@ 1}}所拥有的狗ID(而不是狗实例!)的列表汇总。
人拥有的狗的行为与没有主人的狗的行为不同吗?然后将{@ 1}}添加到所有者ID列表。
还是它们之间的这种关系仅在用户界面中显示?然后将其添加为单独的聚合,即Human
,以免用不需要的数据污染Dog
或DogOwnershipByAHuman(id, dogId, humanId)
聚合。
答案 1 :(得分:0)
两个存储库都应该只更改其对应的表,因为这是它们的主要功能(在Single responsibility principle
之后)。这些存储库将由Service
(具有用于管理关系的实用程序功能的包装器类)包装,其中该服务将负责正确地更改两个数据库。因此,该服务可以具有类似assignDogToHuman($humanId, $dogId)
的功能,该功能将调用两个存储库并相应地更改其数据。
通过执行此操作,可以确保存储库有一个责任(更新其自己的表),并且服务具有管理dogs
和humans
之间的关系的责任。
这还为您提供了额外的好处,即存储层现在可以更换了。即如果您决定更改数据库(例如,从Mysql更改为MongoDB),则仅需交换/更新存储库,因为assignDogToHuman
调用的函数的实现应保持不变,并且对于此服务,它不底层数据库是什么。
如果您有任何疑问,希望对您有帮助