【发布时间】:2014-06-07 00:15:45
【问题描述】:
我目前正在根据领域驱动设计重构我的软件。问题是我对 DataMapper 部分的理解,特别是如果某些数据通过连接表具有m:n 关系(在 SQL 的情况下)。
在这种情况下,我有一个域对象:
class UserGroup extends DomainObject {
public $title;
public $description;
}
现在在我的理解中,我会这样得到一个对象:
$userGroup = UserGroupMapper::instance()->findById(42);
$userGroup->title = 'Foo';
$userGroup->description = 'Bar';
UserGroupMapper::instance()->save($userGroup);
我现在走对路了吗?
那么问题来了:
我有 3 张桌子:
core_users
id | etc
core_usergroups
id | title | description
core_usergroups_dependencys
usergroup_id | user_id
基本上,目标是找到特定组中的所有用户(或反向方式)
我想到的第一件事:
$userGroup = UserGroupMapper::instance()->findById(42);
$userCollection = UserGroupMapper::instance()->findUsersByGroup($userGroup);
DataMapper 知道 2 个表和 2 个域对象,但这感觉不对,是吗?
我不了解 DDD 的服务部分。根据它(以我的理解)我会写
UserGroupService::instance()->findUsers($userGroup);
但在这种情况下,服务需要一个自己的数据映射器。为什么我不应该打电话
UserGroupDependencyMapper::instance()->findUsersByGroup($userGroup);
UserGroupDependencyMapper::instance()->findGroupsByUser($user);
我一般不理解依赖关系的映射。 DataMapper 应该每次都返回一个对象实例或相同类型的对象实例的集合。但在这里,映射器可以返回用户或组。
那么,对于这样一个常见的问题,我应该采取什么方法呢?奖励:在这个示例中我的服务应该做什么?
更新以澄清
我的问题不在于使用领域驱动设计中的数据。它是关于如何在不获取全部的情况下获取 m:n 关系中的数据列表。界面应该是怎样的?
根据 DataMapper 模式,我基本上需要这个:
select * from core_users
join core_usergroups_dependency on core_users.id = core_usergroups_dependency.user_id
where core_usergroups_dependency.usergruop_id = 42
但是呼叫findUsersByUserGroup($myGroup) 呼叫的位置在哪里?用户映射器?
如果我有那个 Mapper 或者我们怎么称呼它,哪一部分知道它?域存储库?
【问题讨论】:
-
您的主要问题是您说要使用 DDD,但您谈论的是表、持久性细节。 DDD忽略db,你只有repository接口
-
当然。但我的问题不是 DDD。问题在于作为 DDD 一部分的持久层的实现。
-
@MikeSW 我的意思是,我的问题是关于存储库接口以及它的实现。
-
DDD 不关心持久性,它是关于根据领域对业务逻辑进行建模。如何实现持久化是你的事,DDD 与它无关。唯一与持久性相关的是存储库接口,它在 DDD 中始终与聚合根一起使用。在处理持久性时,一旦定义了存储库接口,DDD 就结束了。因此,您可以疯狂地执行实现,并且永远不会更改接口以适应实现。
-
@MikeSW 好的,但是如果这是我的业务逻辑,您要求我查找所有 42.000.000 个用户和 42.000 个用户组以检查业务逻辑彼此之间的关系吗?还是我理解错了?理论上有 100 条记录还可以,但在拥有数十亿条记录的现实世界中,性能会大打折扣。
标签: php service domain-driven-design relationship datamapper