【问题标题】:Persisting references non-root entities outside of aggregate持久引用聚合之外的非根实体
【发布时间】:2012-07-12 08:06:36
【问题描述】:

DDD 上的所有材料都将其指定为严格的不,但我最近遇到了一个场景,它为以其他方式思考提供了令人信服的理由。想象一下 2 个聚合根模板和文档,其中 Template --> (1:n) TemplateParam, Document --> (1:n) ParamValue 和最后 2 个根有一个引用 Document --> (n:1) Template
给定聚合根约束ParamValue 不应该保留对TemplateParam 的引用,只有它可以通过通过Template 聚合根获得的临时引用来引用它。现在,如果我想强制执行一个规则,例如“文档的每个 ParamValue 应该引用一个有效的 TemplateParam,该 TemplateParam 属于其拥有的文档所引用的模板”。理想情况下,在数据库级别,我会让 ParamValue 对 TemplateValue 进行 FK,如何在 DDD 范式中做到这一点??

【问题讨论】:

    标签: domain-driven-design


    【解决方案1】:

    聚合根的存在是有原因的。它们充当一组相关实体的单个入口点,以强制执行它们的不变量。他们确保没有任何外部对象可以扰乱这些实体并可能违反它们的不变量。

    但是,在您的特定场景中,即使 ParamValue 直接引用 TemplateParam,TemplateParam 也不存在被 Document 聚合中的实体修改的风险。将修改与给定文档的参数关联的 ,但不会修改每个参数。

    为确保是这种情况,您可以将 TemplateParam 设为不可变值对象:

    (在 C# 中)

    public class TemplateParam
    {
        private readonly string name;
    
        public TemplateParam(string name)
        {
            this.name = name;
        }
    
        public string Name
        {
            get { return name; }
        }
    }
    

    因此,您可以将 TemplateParam 封装在 ParamValue 中,而不会因为 TemplateParam 的“外部化”而破坏模板聚合的不变量之一。

    从技术上讲,这可能违反了 DDD 的聚合根约束,但我不认为它在精神上是一个,只要您保持“外部化”实体不可变并且不修改它最初所属的对象图.

    【讨论】:

      【解决方案2】:

      解决此问题的一种方法是让Template 实体具有用于创建Document 实例的工厂方法,该方法可以强制所有ParamValue 实例与适当的TemplateParam 关联的约束。如果文档是不可变的,那么你就完成了。否则,您可以通过其关联模板将更新应用到文档。此模板可以直接从文档中引用,也可以使用 ID 引用,在这种情况下,封装应用程序服务将在操作需要时检索它。 AR 之间的直接引用并不严格违反 DDD,事实上蓝皮书规定这是唯一可以被外部 AR 引用的东西。由于一致性、性能、ORM 映射等其他考虑因素,它最近已成为一种约束。请查看 this series of articles 上的有效聚合设计以获得一些灵感。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-02-13
        • 2014-08-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多