您是否在CQRS中为事件参数使用聚合根(AR)类型?

时间:2011-08-01 15:22:51

标签: cqrs

您是否将aggregate root(AR)类型用于事件参数?

例如,第一种方法适用于简单类型,但第二种方法使用复杂类型。你为什么喜欢第一个或第二个?

AggregateRoot()
{
    private SomeAR _someAR;

    public void DoSomething(SomeAR someAR)
    {
        // Validation and other similar stuff.
        ApplyEvent(new SomethingHappenedEvent(someAR.StringText));
    }

    public void DoAnything(SomeAR someAR )
    {
        ApplyEvent(new NothingHappenedEvent(this, someAR));
    }

    protected void OnDoSomething(SomethingHappenedEvent e)
    {
        _someAR = ???
    }
}

3 个答案:

答案 0 :(得分:2)

请问您为什么要传递该实体和/或汇总。你真的追求那些物品是什么?我会告诉你,这是他们的状态或副作用自由函数,它会产生你想要放在那个事件中的状态。

将您的事件与您的聚合/实体相关联对您的消费者来说很难,特别是如果涉及消息传递。很快你就会在聚合体/实体的状态(无论是字段还是属性)上撒上序列化属性。也许你会开始介绍状态,以便能够在序列化时为事件提供所需的数据。不好的想法,因为你给你的聚合/实体一个责任 - 为了自己的行为以外的目的跟踪状态 - 它们本来就不应该有。

这不仅仅是耦合和消息传递,它也是一个选择问题:在内部(聚合/实体)和外部(事件/命令)以不同方式表示事物的自由。内部的大多数域对象都是关于行为的,而在外部,事件/命令对象是关于携带状态和意图转发。

所有这一切都说,双重调度到一个对象以达到它的状态是没有错的。

答案 1 :(得分:1)

我会保持简单,只传递事件中的最小数据量。足以让事件处理程序对聚合根进行适当的状态更改。这有助于序列化事件以进行消息传递并存储到事件存储中。

答案 2 :(得分:0)

据我所知,事件只能有基本数据类型或最多只有值对象。我们在活动中不能拥有aggregate root(AR)。第二个建议是不在另一个AR中使用AR。如果说我有AR A和实体B,我会这样写:

public class A : AggregatRoot
{
    B b;

    public A()
    {
        b =  new B();
    }

    public void ChangeBsAttributes(int c)
    {
       b.ChangeMyAttributes(c);
    }
}


public class B : EntityMappedByConvention
{
    int _c;
    B()
    {
    }

    public void ChangeMyAttributes(int c)
    {
        ApplyEvent(MyAttributesChanged(c);
    }

    public void OnMyAttributesChanged(MyAttributesChanged evnt)
    {
        _c = evnt.C;
    }
}