将CQRS与DDD结合起来?

xvd*_*iff 6 architecture design-patterns domain-driven-design cqrs

对于我的大多数应用程序,我使用直接的DDD方法,这意味着分离洋葱架构的层,将域与基础架构分离等.两个经常重复的构建块,存储库和事件总线,看起来像这样(简化).

public interface IRepository<TEntity, TKey>
    where TEntity : EntityBase<TKey>
{

    void Add(TEntity entity);

}

public interface IEventBus {

    void Publish<TEvent>(TEvent @event)
        where TEvent : IEvent;

}
Run Code Online (Sandbox Code Playgroud)

最近,我开始研究CQRS,并且我认识到许多类似的模式,例如存储库,事件和命令总线.但是,例如CQRS中的存储库不负责存储/检索实体,而是负责管理聚合和构建事件流.

现在我想知道:他们俩一起工作吗?或者他们是完全不同的方法,只是分享一些常见的东西?

Ale*_*ger 18

是的,它们是完全不同的方法:CQRS并不意味着事件来源,而是意味着将写入与读取分开.您可以使用和不使用事件源来执行CQRS,这些概念彼此正交.

话虽如此,很明显,使用CQRS式架构,您的存储库仍然负责存储和检索实体:存储库是域语言的一部分,并且此语言不受CQRS或非CQRS等架构选择的影响.这是CQRS应用程序的典型存储库接口,与非CQRS应用程序的存储库接口相同; 此外,如果您使用的是事件来源,它仍然是相同的.

public interface IRepository<TEntity, TKey>
    where TEntity : EntityBase<TKey>
{

    void Add(TEntity entity);
    void Save(TEntity entity);
    TEntity retrieveByKey(TKey key);

}
Run Code Online (Sandbox Code Playgroud)

现在,如果你 使用事件货源,你的资料库的实现,这是基础设施建设,将,例如,查询关系数据库和组装从行中发现特定的密钥对数据的实体.如果您正在使用事件源,则您的存储库将负责查询事件存储,并将事件流投影到要返回的实体的当前状态.所有这些都是实现的一部分,而不是存储库接口的兴趣.