简体   繁体   English

在DDD / CQRS体系结构中处理伪聚合根

[英]Handling pseudo aggregate roots in a DDD/CQRS architechture

I have the following classes: 我有以下课程:

class AggregateRoot
{
  // Defines common properties, Id, Version, etc.
}

class Container : AggregateRoot
{
  public IEnumerable<User> Users { get; }

  public void AddUser(User newUser)
  {
    // ...
  }

  // ...
}

class User
{
  public void AddNotification(Notification newNotification)
  {
    // ...
  }

  // ...
}

class Notification
{
  public string Message { get; set; }
}

As you can see I have a Container that contains one or more Users and each User can have zero or more notifications sent to them. 如您所见,我有一个包含一个或多个用户的容器,每个用户可以有零个或多个通知发送给他们。

The most common operation in this scenario is adding new notifications, so I'll be retrieving a User quite often. 在这种情况下,最常见的操作是添加新的通知,因此我将经常检索User。 Getting the User from the Container is possible, but then I need to retrieve the Container object and search in the Users collection. 从容器中获取用户是可能的,但是随后我需要检索容器对象并在用户集合中搜索。 Which is fine if the Container is quite small and new. 如果Container很小又很新,那很好。 But as the Container gets older it gets more Users. 但是随着容器的变老,它会获得更多的用户。 So the Users collection can become quite big. 因此,Users集合可能会变得很大。 My issue is that the User class is a pseudo aggregate root, lots of operations are done on the User, but a User can't exist outside of a Container. 我的问题是,用户类是伪聚合根,对用户执行了许多操作,但用户不能在容器外部存在。 Solving the obvious performance problem with a new Repository storing Users presents another problem. 使用存储用户的新存储库解决明显的性能问题会带来另一个问题。 How do I keep the User in the Users Repository in sync with the User in the Container? 如何使用户在用户存储库中与容器中的用户保持同步?

I could store just the User Ids in the Container class, but that takes away the business logic in adding a new User to a Container because I can no longer do look up certain properties. 我可以只将User Ids存储在Container类中,但是这样就消除了将新用户添加到Container中的业务逻辑,因为我不再能够查找某些属性。 So, how do I this? 那么,我该怎么办?

I'm using MongoDb to store the events. 我正在使用MongoDb来存储事件。

Solving the obvious performance problem with a new Repository storing Users presents another problem. 使用存储用户的新存储库解决明显的性能问题会带来另一个问题。 How do I keep the User in the Users Repository in sync with the User in the Container? 如何使用户在用户存储库中与容器中的用户保持同步?

You can implement the model in a slightly different fashion. 您可以以略有不同的方式实现模型。 If the only behavior on Container is the adding of User instances then you could make User an aggregate as well. 如果对Container的唯一行为是添加User实例,则也可以使User成为聚合。 To express the constraint that a user must be part of a container, a user could reference a container by ID. 为了表达用户必须是容器一部分的约束,用户可以通过ID引用容器。

class User
{
  public int ContainerId { get; private set; }
  public void AddNotification() //...
}

The Container class can still provide some of the behavior associated with adding a user. Container类仍然可以提供与添加用户相关的某些行为。 It could for instance provide a factory method for creating new users, which would be used by an application service which implements the use-case: 例如,它可以提供一种用于创建新用户的工厂方法,该方法将由实现用例的应用程序服务使用:

class Container
{
  public int Id { get; private set; }
  public User CreateUser(string userName)
  {
    return new User(this.Id, userName);
  }
}

class UserAppService
{
  public void AddUserToContainer(int containerId, string userName)
  {
    var container = this.containerRepository.Get(containerId);    
    var user = container.CreateUser(userName);    
    this.userRepository.Add(user);
  }
}

In this implementation, Container doesn't store a collection of users. 在此实现中,Container不存储用户集合。 This is so because as you point out, the collection can get very large and therefore unfeasible to manage in memory. 之所以这样,是因为正如您所指出的那样,集合会变得非常大,因此无法在内存中进行管理。 In MongoDB, you'd have a container collection and a users collection. 在MongoDB中,您将有一个容器集合和一个用户集合。

Whenever you encounter this notion of a "pseudo-aggregate root" it is likely that you have two, possibly related aggregates. 每当您遇到“伪聚合根”的概念时,很可能就会有两个可能相关的聚合。 This is a common tactic for resolving these types of issues. 这是解决此类问题的常用策略。 For an in-depth treatment on the subject take a look at Effective Aggregate Design by Vaughn Vernon . 要对该主题进行深入处理,请查看Vaughn Vernon的“有效的骨料设计”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM