【问题标题】:DDD: Aggregate and entities relationshipDDD:聚合和实体的关系
【发布时间】:2021-10-20 15:42:53
【问题描述】:

我阅读了一些关于 DDD 的出版物和主题。关于聚合体和实体之间的联系有很多声音。我知道聚合应该尽可能简单(每个聚合一个实体)。但是聚合有实体集合的情况呢?

假设我们有一个名为“Month”的聚合,其中包含“Day”对象的集合(它们是域实体,因为它们需要一个身份 可区分 - 让聚合知道要修改哪个“日”)。

所以我有两个问题:

  1. 这是正确的方法吗?只是正常情况,我不应该担心吗?
  2. 外面的“能见度”呢?在我的方法中,聚合是“包私有的”,不允许任何人在系统的不同部分使用它。 但是实体呢?它们是否应该像系统不同部分的值对象一样可见?或者只是创建另一个 VO 来表示外部实体(例如:当实体存储在事件中时)?

谢谢大家的回答

【问题讨论】:

    标签: java architecture package domain-driven-design entities


    【解决方案1】:

    将日期和月份建模为实体在很大程度上取决于上下文。这可能不是解释聚合和实体的最佳示例,但让我们尝试一下。

    让我们假设在我们的上下文中,一天不能单独存在。必须在一个月内。如果要引用一天,则必须先指定月份。这就是我们在现实生活中使用日期的方式,1 月 1 日、5 月 8 日……即使这些日子是实体,它们也不需要全局唯一标识符。他们只需要 [1 .. 31] 月内的标识符。

    聚合应尽可能小,但并不是每个聚合只能有一个实体。您只需要拥有一个在所有系统中具有唯一标识符的聚合根(月)。在聚合中,您可以拥有在聚合中具有唯一标识符的实体(天)[1 .. 31]。如果您想引用或访问这些实体,您应该始终通过聚合根。

    【讨论】:

    • 是的,我同意。我举了一个不幸的例子,因为“日”本身就是可以识别的。谢谢你的回答,我觉得很有帮助
    【解决方案2】:

    聚合、实体和值对象

    在我看来,一个实体是一个 child,其名称 (Id) 是一个 Aggregate,而后者又是 Father带有名称 (Id)。

    聚合不能有实体。 你可以认为是一个实体,不:一个实体只存在于一个聚合中。

    实体(子)是一个小聚合(父),没有其他实体(子)。

    父亲和孩子可以使用透明框(我没有更好的办法来翻译ValueObject的概念,抱歉):当您创建一个透明框时,您无法更改任何内容,但您可以阅读内容,如果您想更新该框,您必须创建一个新框。

    聚合负责管理实体,这意味着:添加、更新、删除和查询。

    如果您想与一个或多个实体交谈(查询),您必须询问聚合,因此,当您加载聚合时,您必须加载所有实体。

    一个聚合可以有多种类型的实体,有多少?嗯,这取决于您、设计和系统。

    显然,包含许多实体且每个实体很多行的许多字段的大聚合可能效率不高,在这种情况下,也许您可​​以选择最大的实体并上交具有或不具有子级的聚合。

    实例

    我在 csharp 上写了示例,但与 Java 没有太大区别。

    
    class Invoice : ValueObject
    {
        public string Number { get; private set; }
    
        public DateTime Date { get; private set; }
    
        public decimal TaxableAmount { get; private set; }
    
        public decimal VatAmount { get; private set; }
    
        public decimal TotalAmount => TaxableAmount + VatAmount;
    
        public Invoice(string number, DateTime date, decimal taxableAmount, decimal 
             vatAmount)
        {
             // validation
             Number = number;
             [..]
        }
    
    }
    
    class Taxonomy : Entity 
    {
       public int Id {get; private set;}
    
       public decimal Amount {get; private set;}
    
       public string Classfication {get; private set;}
    
       public Taxonomy(int id, decimal amount, string classification)
       {
          // validation
          Id = id;
          [..]
       }
    }
    
    
    class SaleAggregate : AggregateRoot
    {
       private List<Taxonomy> _taxonomies;
    
       public int Id {get; private set;}
       
       public Invoice Invoice {get; private set;}
    
       public IReadOnlyCollection<Taxonomy> Taxonomies => _taxonomies.AsReadOnly();
    
       public SaleAggregate(int id, string number, DateTime date, decimal 
               taxableAmount, decimal vatAmount)
       {
           _taxonomies = new List<Taxonomy>();
        
           // I prefer to pass ALWAYS primitive types to not rely on valueObject
           // validation
           Id = id;
           Invoice = new Invoice(number, date, taxableAmount, vatAmount)
           [..]
       }
    
       public void AddTaxonomy(int id, decimal amount, string classification)   
       {
           // validation
           _taxonomies.Add(new Taxonomy(id, amount, classification);
       }
    
       public void UpdateTaxonomy(int id, decimal amount, string classification)
       {
           // validation
           var entity = _taxonomies.FirstOrDefault(p=> p.Id == id);
           entity.Amount = amount;
           entity.Classification = classification;
       }
    
       public void RemoveTaxonomy(int id)
       {
           // validation
           var entity = _taxonomies.FirstOrDefault(p=> p.Id == id);
           _taxonomy.Remove(entity);
       }
    
       public void UpdateVatAmount(decimal vatAmount)
       {
           // validation
           Invoice = new Invoice(Invoice.Number, Invoice.Date, 
                        Invoice.TaxableAmount, vatAmount);
       }
    }
    
    
    

    再次重申:这是我对 Aggregate、Entities 和 ValueObject 的看法,阅读本文的其他开发人员可以随时纠正我。

    【讨论】:

    • 是的,我明白多了,谢谢:)
    猜你喜欢
    • 1970-01-01
    • 2016-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-29
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    相关资源
    最近更新 更多