我在社交网站的设计中使用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
,然后通过{{1 }}。 但是在事件处理程序中创建新的聚合对我来说听起来很可疑。
与此同时,我也觉得它对于像NotificationRepository
这样的简单类来说太重了。我无法确定通知是否属于域名关注或基础设施问题。
答案 0 :(得分:1)
根据您的描述,它听起来像是'通知'是域事件发射(和订阅)的实现,这表明虽然每种通知都可能值得域对象(值对象,因为它们是不可变的),域事件的传输和接收更多可能是基础设施问题,而不是聚合+存储库
答案 1 :(得分:1)
域中的每个对象都应该是实体或值对象。域中的每个对象都应存在于单个聚合边界内。
并非您应用中的每个对象都是您域中的对象。
与此同时,我也觉得它对于像Notification这样的简单类来说太重了。我无法确定通知是否属于域名关注或基础设施问题。
我倾向于同意; CRUD接口(你真的支持修改所有这些属性吗?甚至id?),缺少方法,缺乏业务不变量。你说这些是由事件处理程序创建的 - 这是否意味着大多数这些字段只是原始事件的副本?
通知看起来更像是应用程序问题,而不是域关注问题。在领域专家和无处不在的语言上更加努力,以探索通知是否真的是域的一部分。
但是在事件处理程序中创建新的聚合对我来说听起来很可疑。
呃...是的,但也没有。你不会期望一个事件处理程序来创建一个新的聚合,没有。但事件处理程序会安排命令来创建聚合是完全合理的。
此技术通常用于长时间运行的流程(搜索关键字:流程管理器,传奇)。事件处理程序观察消息,并将它们传递给进程,该进程更新自己的状态并在聚合上运行命令,并对其进行舍入和舍入。