Cribbb基于DDD/Domain Event领域事件的开源PHP通知系统

Cribbb是一个使用DDD聚合根和领域事件Domain Events概念开发的PHP开源通知框架:cribbb/cribbb · GitHub

几乎所有Web应用都有一个通知提醒系统,这些通知系统都有共有的属性和功能:

一个发往用户的消息管道
Cribbb通知系统扮演一种消息管道,通知用户最近的事件,有许多不同的“钩子”可以触发通知添加到用户的消息管道中。

一个消息可以是任何类型
有许多不同的通知类型,针对应用中发生的不同的可能动作。

应当由可读和未读状态
通知消息应该有状态,一旦用户有打开动作从而改变通知消息的状态,这是很重要的用户界面设计。

发送Email和作为UI一部分现实
默认情况用户会收到一份Email,和用户界面提醒一样,用户可以关闭邮件通知。

一个动作可以引起许多通知
在Cribbb中一个动作可以引起发给一个或多个用户的通知,这意味着应当在动作和通知之间解耦。

通知消息应该被队列化
使用队列系统发送通知,因为针对一个动作可能有大量Email发送,通知发送不必即时。

通知是发送给用户的一个消息,告诉他们他们对应用中感兴趣的事件发生了,也许是一个用户follow了他,或回复了他的帖子。

Domain Events是易于针对应用中事件的发生实现相应的通知机制的,当一个领域事件发送时,注册的监听器类将自动引爆,这样动作和事件实现解耦,我们可以根本无需接触事件的触发动作而添加事件的监听器。

有界上下文

经过几周发现了区分不同的限定上下文Bounded Conext 重要性,一个有界的上下文是作为保护维护统一内部模型的层出现,这对于大型应用很重要。

Cribbb有一个身份方面的有界上下文,功能有:包括注册一个新用户 following其他用户,更新账户信息等。

那么通知功能是否有自己的有界上下文?或者是身份有界上下文的一部分?

通知功能其实应该属于身份有界上下文:

首先,通知是用户身份系统的一种重要概念,应用可以触发一个通知,但是通知仅仅对于注册有身份的用户是重要的。

其次,在通知模型和用户身份识别模型之间没有矛盾,如果有,那么我们可能就区分为不同的有界上下文。

最后,一个通知没有道理不和用户绑定,一个用户只能查看自己的通知,不能看其他用户的通知,我们为Cribbb建立一个获得通知的API,端点是:me/notifications.

通知实体和用户聚合
通知应该作为实体建模,通常你默认会建立为值对象 而不是实体,因为简单,但是这次我们没有选择。

通知没有必要知道用户上下文以外的事情,我们应当能够从数据库任意地接受消息,而不是只能从User对象获得一个用户的通知。

这意味着通知如果放在User聚合中很整洁合适。Notification通知实体也能非常简单。

首先,通知需要一个内容体需要保存通知的内容文本数据。

其次,我们需要一个 已读/未读的状态,我们需要通知消息被读的时间戳,这样我们能够判断这两个状态。

最后,我们分类通知以便可以过滤它们,在通知实体中使用一个关键词来标识。

Java编写的基于DDD/Domain Events的Jivejdon源码中也有一个通知消息机制。

具体功能是在自己“博客”中有收件箱和发件箱,这个消息通知系统不但可以收到别人发给你的消息,而且在你订阅了相关主题以后,一旦主题更新会发送消息给你,比如帖子有人回复或有人at你了。

两者可以对比学习。