8

我正试图以Greg Young 的风格了解DDDD

有很多关于如何使用 CQRS+EventSourcing 实现 DDDD 的讨论,并且有一些示例实现......总之它可能会很混乱......

在 Gregs 视图中,聚合没有 getter 或 setter - 只是发出相应事件的状态更改方法。

基本上,一个事件描述了过去发生的状态转换。它的数据描述了发生了什么变化。

有人说,这些数据可以通过附加数据来“丰富” 。这些额外的数据
从哪里来

即我有UserUsergroup-两个聚合根(可以独立存在,有身份)。User有一个方法叫做AddToUsergroup.

public class User : AggregateRoot
{
    // ...
    public void AddToUsergroup(Usergroup usergroup)
    {
        // validate state
        RaiseEvent(new UserJoinedUsergroup(this.Id, usergroup.Id));
    }
    // ...
}

public class Usergroup : AggregateRoot
{
    private string _displayName;
    // ...
    public void ChangeDisplayName(string displayName)
    {
        // validate state
        RaiseEvent(new DisplayNameChanged(this.Id, displayName));
    }
    public void Apply(DisplayNameChanged e)
    {
        this._displayName = e.DisplayName;
    }
    // ...
}

如果我想用用户组的名称“丰富事件(出于调试原因或类似原因),我该怎么做?

  • 吸气剂存在
  • 用户组的内部状态不可访问

不允许将诸如存储库之类User的东西注入我在这里吗?!?),例如

  • 读取端存储库
  • 事件存储库

底线问题:

  • 是否应该注入诸如存储库之类的东西来聚合根?
  • 事件是否应该使用通过参数和聚合的内部状态可用的数据?
  • 事件是否应该包含描述状态变化的最少数据?

而且(有点离题,但样本在这里)

  • 应该AddToUsergroup采用Guid 而不是完整的聚合

期待您的回答!


华拉巴

4

1 回答 1

6

是否应该注入诸如存储库之类的东西来聚合根?

不,在这种情况下也没有必要。将域服务传递给聚合上的行为方法可能是合适的,但同样在这种情况下不需要。

事件是否应该只使用通过参数和聚合的内部状态可用的数据?

是的,原始领域事件应该可以很容易地由聚合构建,并且可以以确定性的方式重播。

事件是否应该只包含描述状态变化的最少数据?

是的。然而,为了满足外部订阅者的需求,这就是内容丰富器发挥作用的地方。要从外部分派域事件,首先将其提交到事件存储,然后您可以在同一个 tx 中分派或使用进程外机制将事件发布到外部。在外部发布时,您通常会为消息使用不同的合同,因为订阅者可能需要的不仅仅是域事件本身的内容。在这种情况下,您需要用户组名称。然后,发布者可以提取用户组名称并将该数据放入丰富的事件中。此发布者可以访问允许其检索名称的用户组的读取模型存储库。

AddToUsergroup 是否应该采用 Guid 而不是完整的聚合根?

是的。传递整个聚合可能是不可能的,并且还会产生一种错觉,即可以使用 ID 以外的东西,但事实并非如此。

于 2013-04-23T15:02:45.130 回答