【问题标题】:How to name and implement Result set rows in DDD?如何在 DDD 中命名和实现结果集行?
【发布时间】:2017-09-17 20:11:28
【问题描述】:

在 DDD 中,您有一个具有唯一标识符(ID 或 UUID)的实体。通常,实体表示数据库表中的可存储行。我的存储库可以加载单个实体 (findById) 或一次加载所有实体 (findAll)。

但是现在必须编写一个特殊且非常复杂的查询,并连接到其他表。结果集不再是一个特殊的(用户)实体,因为我已经从具有别名的多个表中选择了不同的字段等等。根据查询,结果可能不包含 id。

我已经成功地将这些行合并到一个新的对象集合中,但在为那个东西的名称(和类型)而苦恼。

我的问题是:

如何对来自 DDD 中的自定义查询的此类行进行命名和分类?

【问题讨论】:

  • 因此 DDD 名称中的名称为“域驱动”。如何命名事物 - 找到您的域人员并询问他们,您刚刚查询的是什么。

标签: php pdo domain-driven-design ddd-repositories


【解决方案1】:

看来你这里需要一个查询服务。

DDD 非常适合 CQRS,我相信您想要的结果是只读的。

在这种情况下,您可以根据需要创建一个特殊对象:UserData,如果用户包含一些其他关系,例如角色集合或权限,您可以将其称为 UserRightsData,并从 UserQueryService 中获取。

查询服务通常位于应用层。

如果您想要非只读结果,而是您可以操作和持久化的普通实体,那么您需要向我们提供更多详细信息。特别是,您应该能够从存储库加载此实体,调用域操作并通过应用程序服务将其持久化。

查询服务非常适合视图、表格和数据显示,具有排序、过滤等功能......

编辑:plalx 在对 Eben Roux 的帖子的回复中确定了这一点。

ProjectName/
    IdentityAndAccess/
        Application/
            Command/
                AuthenticateUserCommand.php
                ChangeEmailAddressCommand.php
                ChangeUserPasswordCommand.php
                ChangeUserPersonalNameCommand.php
                ...
            Data/
                UserData.php
                UserRightsData.php (POPO containing User infos and a list of rights)
                RightData.php (Single comment infos)
            UserApplicationService.php
            UserQueryService.php
        Domain/
            Model/

【讨论】:

  • 谢谢。所以我应该使用返回“读取模型”(DTO)的“查询服务”(应用层)。这是正确的吗?
  • 是的,你的阅读模型会适应你想要填充的视图。这样做的好处是你只渲染需要的东西,例如如果您不需要数据库 ID,而是需要域密钥,则不需要获取数据库 ID。
【解决方案2】:

首先,您应该避免查询您的域模型,除非您真正追求特定的聚合。即使这样,根据您的设计,您也可能无法获得所需的数据。

典型的建议是使用一个专门的查询层以及可能的代表所需数据的读取模型。该读取模型可能是您需要的类型或松散的。例如,如果名称/值对列表可以解决问题,那么您可能会选择 that

这些查询实际上并不是领域的一部分,因此在建模方面不属于领域驱动的设计。但是,它们作为您的整体架构/方法的一部分很重要。

更新

回应@Luca Masera 的评论:

我通常使用类似 (C#) 的东西来表示 Product:

public interface IProductQuery
{
    int ActiveCount();
    DataRow Details(Guid id);
    Query.Product Get(Guid id);
    IEnumerable<Query.Product> Matching(ProductSpecification specification);
}

Query 命名空间使读取模型Product 不会干扰我的实际域Product

根据我的要求,我将使用适当的返回对象/结构/类型。

【讨论】:

  • 因此,例如,您可以在界面中隐藏所有这些“额外域请求”。然后,在基础设施层,您以您认为更好的方式实现它。因此,您可以保持模型干净,并且所有额外的东西(不是领域的一部分,但需要满足您的业务流程)远离模型并且可以适应您使用的基础设施(稍后这些数据可能会使用 Solr 进行索引和查询)。
  • 您的规范是在域中定义的还是仅在查询层中定义的?如果在后者中,那么与更简单的方法(例如为每个查询使用专用查询方法)相比有什么好处?对于查询,我通常没有通用数据持有者,并且每个查询操作都返回不同类型的 DTO,从而使 Matching 操作不太有用。例如。 DashboardData data = queryService.dashboardDataForUser(userId)。以这种方式优化查询也容易得多。
  • 我使用了安全规则规范,其中规范可以通过将规则转换为 SQL(访问者模式)来进一步限制查询,但也限制命令,允许我只返回 AR 实例用户可以在不重复代码的情况下采取行动。
  • 您当然可以有专门的查询,但有时您可能有几个标准供用户填写,例如填写表格。但是您可以仍然让您的数据访问查询忽略某些“空”或null 值。当我实际构建动态查询与传入参数时,我发现规范最有用。
  • @EbenRoux 谢谢。所以我应该使用返回“读取模型”(DTO)的“查询服务”(应用层)。这是正确的吗?
猜你喜欢
  • 2016-05-17
  • 2010-10-19
  • 1970-01-01
  • 2013-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-31
相关资源
最近更新 更多