【问题标题】:DDD - injecting Factories in aggregate root Entity constructorDDD - 在聚合根实体构造函数中注入工厂
【发布时间】:2015-05-17 22:04:59
【问题描述】:

我正在编写一个考虑 DDD 的应用程序,并试图通过将域逻辑和行为委托给实体来避免出现贫乏的域模型。在构建作为聚合根的实体并且需要创建需要由工厂类处理的子实体时,我遇到了一个问题。这是一个例子:

我有以下实体:PageUrlLayout。在我的模型中创建页面的是 PageUrlLayout - 如果没有这两个,Page 对象将无效。在一个简单的模型中,Page 构造函数方法将简单地将这两个对象创建为私有属性。但是,Url 有一个特定的要求;它必须从页面的标题(或 slug)创建,并且必须是唯一的(通过附加“-1”、“-2”或类似的东西来确保)。这需要与存储库进行通信。

我最初的想法是将UrlFactory 对象传递/注入到Page 构造函数并让Page 创建它需要的Url,但我一直在阅读关于如何将服务注入实体是一个坏主意.

所以,我的问题是;有没有一种方法——或一种既定的模式——允许实体在没有贫乏的域模型的情况下构建其复杂的子实体,或者在这种情况下注入工厂是一种有效的解决方案?

【问题讨论】:

  • 并非所有东西都可以或应该进入实体。单一责任原则仍然适用。以下是您可以在应用程序服务中执行的操作:url = urlGeneratorService.fromPageTitle(title); page = new Page(title, url, layout)。然后您的PageUrl 值对象可以实现isDerivedFromTitle 方法,并且在Page 的构造函数中您可以执行...if (!url.isDerivedFromTitle(title)) throw ...urlGeneratorService 可以像 new PageUrl(pageTitle, rawUrl) 一样构造 PageUrl
  • 反对将服务注入实体的论据是什么?可以提供网址吗?

标签: entity domain-driven-design factory anemic-domain-model


【解决方案1】:

不要将工厂类注入聚合,而是使用工厂方法。然后在聚合中创建方法“validate(Validator)”(聚合只知道它可以被验证,但它不会实现如何做的逻辑)。

Validator 类将作为参数传递给您的 validate 方法,需要有一个方法 ->validateObject(this)。 您将聚合实例传递给 validateObject,以便它可以访问您的属性。

验证器类可以注入存储库。当您运行 validateObject 方法时,它将在数据库中搜索唯一性。

【讨论】:

    【解决方案2】:

    如果您将 URL 构造视为技术问题,则可以在基础结构层中使用 UrlFactory

    在 C# 中:

    public class UrlFactory 
    {
      public string CreateUrl(string title)
      {
        var url = // ... construct URL from the title here
    
        return _pageRepository.NextAvailableUrlLike(url);
      }
    }
    

    然后从您的应用层服务中调用它。

    如果您将其视为域问题,则 URL 构造逻辑可能位于域服务中。调用存储库的行将移至应用层服务:

    public void CreatePage(string title)
    {
      var potentialUrl = _urlService.CreateUrl(title);
      var realUrl = _pageRepository.NextAvailableUrlLike(url)
      new Page(title, realUrl, ...); // do whatever you want with the new Page instance
    }
    

    【讨论】:

    • 为什么要将调用存储库转移到应用层?由于 Repository 接口是 Domain 的一部分,因此应该可以在 Domain 范围内调用它。
    • 我想让域服务保持精简和内聚,但你说得对,你也可以在其中包含 URL“唯一化”部分。
    猜你喜欢
    • 2019-06-29
    • 1970-01-01
    • 2016-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-16
    相关资源
    最近更新 更多