domain-driven-design - 具有重要不变量的潜在大型集合的 DDD 聚合

标签 domain-driven-design aggregate invariants

关闭。这个问题是opinion-based .它目前不接受答案。












想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题.

去年关闭。




Improve this question




我知道聚合应该很小并且它们应该保护不变量。
我也知道在聚合中保存大型集合会影响性能。

我有一个用例,需要保护它的不变量,但也会导致大量收集。

聚合是 供应商 ,并且它可以有多个事件 促销 (s)。每个促销 促销类型 , 开始日期 结束日期 .不变量是:

  • 在任何时候,每个 最多可以有一次促销事件促销类型
  • 在任何时间点最多可以有 2 个促销事件
  • public Vendor : Aggregate {
        public Guid Id;
        public List<Promotion> Promotions;
        // some other Vendor props here
    
        public void AddPromotion(Promotion promo) {
            // protect invariants (business rules) here:
            // rule_1: if 2 promotions are already active during any time between promo.Start and promo.End then throw ex
            // rule_2: if during any time between promo.Start and promo.End there is promo with same Type then throw ex
    
            // if all is ok (invariants protected) then:
            Promotions.Add(promo);
        }
    }
    
    public Promotion : ValueObject {
        public PromotionType Type; // enum CheapestItemForFree, FreeDelivery, Off10PercentOfTotalBill
        public DateTime Start;
        public DateTime End;
    }
    

    正如我们所见,Promotions在一段时间内添加新的促销事件时,收藏会增加,而旧的促销事件将过期。

    解决方案 1)
    一种可能性是使 Promotion一个单独的聚合,包含 供应商 ID ,但在那种情况下很难保护提到的不变量。

    解决方案2)
    另一种可能性是有一个维护工作,它将过期(EndDate 传递)移动到某个历史记录表,但它是 IMO 的臭解决方案。

    解决方案 3)
    另一种可能性是也使 Promotion聚合本身但保护域服务中的不变量,例如:
    public class PromotionsDomainService {
        public Promotion CreateNewVendorPromotion(Guid vendorId, DateTime start, DateTime end, PromotionType type) {
            // protect invariants here:
            // invariants broken -> throw ex
            // invariants valid -> return new Promotion aggregate object
        }
    }
    

    ... 但在 中保护它促销域服务 (并返回聚合)我们冒着竞争条件和不一致的风险(除非我们应用悲观锁)。

    在这种情况下,推荐的 DDD 方法是什么?

    最佳答案

    您的聚合应仅包含实现其目的所需的数据。阅读您的问题的描述,我认为供应商不需要任何东西的过期促销。因此,您只需要在集合中保留事件促销。

    在您的 AddPromotion 方法中,如果存在该类型的事件促销,您将返回错误。如果没有该类型的任何促销,您将添加它,如果该类型的促销已过期,您将替换它。除非您有大量的促销类型(情况似乎并非如此),否则每种类型最多只能有一个促销。似乎这将使集合保持在一个非常合理的大小。如果不是这种情况,请告诉我。

    您很有可能需要将过期促销作为历史数据。但是这些应该基于为此目的而设计的读取模型,而不是总体上。为此,聚合可以发布它接受新促销的每种类型的事件,并且监听器会对该事件使用react并在历史促销表中插入一条记录。

    更新:

    再次阅读问题后,我意识到您甚至不需要保留每种类型的促销。收藏中最多有 2 个促销事件,因此收藏的大小最多为 2,除非我误解了它。

    关于domain-driven-design - 具有重要不变量的潜在大型集合的 DDD 聚合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60167189/

    相关文章:

    r 按 id 聚合或折叠特定列值

    sql - COUNT() OVER 可能在 HIVE 中使用 DISTINCT 和 WINDOWING

    c++ - 为什么这个不变量会变成假呢?

    domain-driven-design - 用于域事件的 NoSql 数据库

    c# - 使用 DDD 和 AutoMapper,您如何在单个工作单元内处理多个服务中的同一个聚合根?

    r - 在R中,如何将data.frame的聚合转换为data.table的聚合?

    loops - 可能的循环不变式

    oop - 对于 OOP,不可变和不变是同义词吗?

    c# - DDD实体的Id与现有数据库建模

    php - 在 oneToMany 关系中创建和删除子项的正确 DDD 方法?