1

我在社交网络网站的设计中使用 DDD(包括域事件)和 CQRS(没有事件溯源)。

我有聚合根,如User, FriendRequest, Friendship。我也有像UserAddressChanged,之类的领域事件FriendRequestAccepted。其中一些事件需要通知相关用户。所以我正在考虑Notification上课,比如:

public enum NotificationReason
{
    IncomingFriendRequest = 1,

    OutgoingFriendRequestAccepted = 2,

    // and many more ...
}

public class Notification
{
    public long Id { get; set; }
    public int UserId { get; set; }
    public string UserName { get; set; }
    public string AvatarUrl { get; set; }
    public DateTime Timestamp { get; set; }
    public NotificationReason Reason { get; set; }
    public bool Read { get; set; } //if user has read this notification.
}

但是我应该将Notification类建模为聚合根吗?如果是,则当User聚合更改地址并引发UserAddressChanged域事件时,在相应的事件处理程序中,Notification将创建一个新聚合并随后通过NotificationRepository. 但是在事件处理程序中创建新的聚合对我来说听起来很可疑

同时,我也觉得对于一个简单的类来说太重了Notification。我无法确定通知是域问题还是基础设施问题。

4

2 回答 2

1

根据您的描述,听起来“通知”是域事件发射(和订阅)的实现,这表明虽然每种通知都可能值得一个域对象(一个值对象,因为它们是不可变的),但与聚合+存储库相比,域事件的传输和接收更可能是基础架构问题

于 2016-02-11T04:40:39.227 回答
1

您域中的每个对象都应该是一个实体或一个值对象。域中的每个对象都应该存在于单个聚合边界内。

并非应用程序中的每个对象都是域中的对象。

同时,我也觉得它对于像 Notification 这样的简单类来说太重了。我无法确定通知是域问题还是基础设施问题。

我倾向于同意;CRUD 接口(你真的支持修改所有这些属性吗?甚至是 id?),缺少方法,缺少业务不变量。您说这些是由事件处理程序创建的——这是否意味着这些字段中的大多数只是原始事件的副本?

通知看起来更像是应用程序问题而不是域问题。更加努力地推动领域专家和无处不在的语言,以探索通知是否真的是领域的一部分。

但是在事件处理程序中创建新的聚合对我来说听起来很可疑。

呃……是的,但也不是。您不会期望事件处理程序创建新的聚合,不。但是,事件处理程序会安排命令来创建聚合是完全合理的。

这种技术通常用于长时间运行的进程(搜索关键字:进程管理器、sagas)。事件处理程序观察消息,并将它们传递给一个进程,该进程更新自己的状态并在聚合上运行命令,一轮又一轮。

于 2016-02-19T18:06:06.220 回答