首页 > 解决方案 > DDD建模,引用聚合根的子节点?

问题描述

我正在努力学习DDD。我正在建模一个物业管理域,我认为我有两个上下文(子域?):一个物业管理上下文和一个常驻上下文。

假设我有一个聚合根Apartment,它包含Floorplans 和Units。每个Apartment可以有很多Floorplans,每个Floorplan可以有很多Units。

public class Apartment : IAggregateRoot // for clarity
{
    public int Id { get; }
    public Address Address { get; set; }
    public ICollection<Floorplan> Floorplans { get; set; }
}

public class Floorplan
{
    public int Id { get; }
    public int ApartmentId { get; set; }
    public string Name { get; set; }
    public int Bedrooms { get; set; }
    public int Bathrooms { get; set; }
    public ICollection<Unit> Units { get; set; }
}

public class Unit
{
    public int Id { get; }
    public int FloorplanId { get; set; }
    public string Number { get; set; }
}

假设在物业管理上下文中,我现在介绍一个Resident分配给Unit. 我UnitResident班级现在看起来像这样:

public class Unit
{
    public int Id { get; }
    public int FloorplanId { get; set; }
    public string Number { get; set; }
    public ICollection<Resident> Residents { get; set; }
}

public class Resident // in the property management context
{
    public int Id { get; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public void UpdateBalance(...);
}

我现在的问题是,如果我Resident在常驻上下文中引入 a (可以PayRent()UpdateProfile()等),它们必须与Resident物业管理上下文中的 1:1 关系,但我认为我不能在不去所有的情况下引用非聚合根实体因为没有ApartmentaResident就无法存在Apartment

我对聚合根的理解不正确吗?在这Resident两种情况下都是聚合根吗?我不确定这将如何建模。

标签: c#architecturedomain-driven-design

解决方案


我现在的问题是,如果我在居民环境中引入居民(可以 PayRent() 或 UpdateProfile() 等),他们必须在物业管理环境中与居民有 1:1 的关系,但我认为我不能引用非- 聚合根实体而不一直通过公寓,因为没有公寓就不能存在居民。

这取决于您的架构。在大多数情况下,对我来说,在您的域之外有一个事件将由两个上下文处理(通过应用程序服务向下传递到聚合)并将通过“创建”适当的参与者(居民和物业经理客户?)。在这里确保 1:1 意味着确保所有事件都得到处理并优雅地处理故障(这听起来很有趣)。

所有上下文都有一个边界。边界将作为消费者的上下文“接口”。上下文之间的任何通信都应该通过这个“接口”。举个例子:如果你的上下文被实现为一个微服务(一个 REST API),你应该只通过发送 HTTP REST 命令与它进行通信。这种隔离使上下文保持干净。这就是拥有上下文的目的。


推荐阅读