域名事件被提出时谁负责实体的变异?DDD

lex*_*eme 3 c# domain-driven-design servicebus cqrs domain-events

我一直在学习CQRS/ES.看一下小例子项目,我经常看到事件改变了实体状态.例如,如果我们查看Order 聚合根:

public class Order : AggregateRoot {
    private void Apply(OrderLineAddedEvent @event) {
        var existingLine = this.OrderLines.FirstOrDefault(
            i => i.ProductId == @event.ProductId);

        if(existingLine != null) {
            existingLine.AddToQuantity(@event.Quantity);
            return;
        }

        this.OrderLines.Add(new OrderLine(@event.ProductId, @event.ProductTitle, @event.PricePerUnit, @event.Quantity));
    }

    public ICollection<OrderLine> OrderLines { get; private set; }

    public void AddOrderLine(/*parameters*/) {
        this.Apply(new OrderLineAddedEvent(/*parameters*/));
    }

    public Order() {
        this.OrderLines = new List<OrderLine>();
    }

    public Order(IEnumerable<IEvent> history) {
        foreach(IEvent @event in history) {
            this.ApplyChange(@event, false);
        }
    }
}

public abstract class AggregateRoot  {
    public Queue<IEvent> UncommittedEvents { get; protected set; }

    protected abstract void Apply(IEvent @event);

    public void CommitEvents() { 
        this.UncommittedEvents.Clear();
    }

    protected void ApplyChange(IEvent @event, Boolean isNew) {
        Apply(@event);
        if(isNew) this.UncommittedEvents.Enqueue(@event);
    }
}
Run Code Online (Sandbox Code Playgroud)

何时OrderLineAddedEvent应用它会Order通过添加新的订单行进行变异.但我不明白这些事情:

  • 如果这是一个正确的方法,那么所做的更改是如何保持的?
  • 或者我应该以某种方式将事件发布到相应的处理程序中Order?我如何在技术上实现这一点?我应该使用服务总线传输事件吗?

Ebe*_*oux 5

我还在尝试ES,所以这仍然是一个意见而不是任何指导:)

在某些阶段,Jan Kronquist发现了这篇文章:http://www.jayway.com/2013/06/20/dont-publish-domain-events-return-them/

它的要点是应该从域返回事件而不是从域内调度.这真的引起了我的共鸣.

如果要采用更传统的方法,使用正常的面向持久性的存储库,应用层将处理事务和存储库访问.只需调用域即可执行该行为.

此外,域应始终坚持持久性无知.让聚合根维护一个事件列表对我来说似乎总是有点奇怪,我绝对不喜欢让我的AR继承一些共同的基础.感觉不够干净.

所以用你拥有的东西将它们组合在一起:

public OrderLineAddedEvent AddOrderLine(/*parameters*/) {
    return this.Apply(new OrderLineAddedEvent(/*parameters*/));
}
Run Code Online (Sandbox Code Playgroud)

在我的POC中,我还没有使用IEvent标记界面,而只是一个object.

现在,应用层重新控制了持久性.

我有一个实验性的GitHub存储库:

我有一段时间没有时间看它,我知道我已经做了一些改动,但欢迎你看一下.

基本思想是应用层将使用EventStore/ EventStream来管理聚合的事件,方式与应用层使用的方式相同Repository.在EventStream将被应用到总和.从域行为返回的所有事件都将添加到EventStream之后再次保留的事件.

这使得所有面向持久性的位都不在域之外.