Where should an object in CQRS+ES be fully initialized: in the constructor, or when applying the first event?

There appears to be widespread agreement in the OOP community that the class constructor should not leave an object partly or even fully uninitialized.

What do I mean by “initialization”? Roughly speaking, the atomic process that brings a newly created object into a state where all of its class invariants hold. It should be the first thing that happens to an object, (it should only run once per object,) and nothing should be permitted to get hold of an un-initialized object. (Thus the frequent advice to perform object initialization right in the class constructor. For the same reason, Initialize methods are often frowned upon, as these break apart the atomicity and make it possible to get hold of, and use, an object that is not yet in a well-defined state.)

Problem: When CQRS is combined with event sourcing (CQRS+ES), where all state changes of an object are caught in an ordered series of events (event stream), I am left wondering when an object actually reaches a fully-initialized state: At the end of the class constructor, or after the very first event has been applied to the object?

Note: I’m refraining from using the term “aggregate root”. If you prefer, substitute it whenever you read “object”.

Example for discussion: Assume that each object is uniquely identified by some opaque Id value (think GUID). An event stream representing that object’s state changes can be identified in the event store by the same Id value: (Let’s not worry about correct event order.)

interface IEventStore
{
    IEnumerable<IEvent> GetEventsOfObject(Id objectId); 
}

Assume further that there are two object types Customer and ShoppingCart. Let’s focus on ShoppingCart: When created, shopping carts are empty and must be associated with exactly one customer. That last bit is a class invariant: A ShoppingCart object that is not associated to a Customer is in an invalid state.

In traditional OOP, one might model this in the constructor:

partial class ShoppingCart
{
    public Id Id { get; private set; }
    public Customer Customer { get; private set; }

    public ShoppingCart(Id id, Customer customer)
    {
        this.Id = id;
        this.Customer = customer;
    }
}

I am however at a loss how to model this in CQRS+ES without ending up with deferred initialization. Since this simple bit of initialization is effectively a state change, wouldn’t it have to be modelled as an event?:

partial class CreatedEmptyShoppingCart
{
    public ShoppingCartId { get; private set; }
    public CustomerId { get; private set; }
}
// Note: `ShoppingCartId` is not actually required, since that Id must be
// known in advance in order to fetch the event stream from the event store.

This would obviously have to be the very first event in any ShoppingCart object’s event stream, and that object would only be initialized once the event were applied to it.

So if initialization becomes part of the event stream “playback” (which is a very generic process that would likely work the same, whether for a Customer object or a ShoppingCart object or any other object type for that matter)…

  • Should the constructor be parameter-less and do nothing, leaving all work to some void Apply(CreatedEmptyShoppingCart) method (which is much the same as the frowned-upon Initialize())?
  • Or should the constructor receive an event stream and play it back (which makes initialization atomic again, but means that each class’ constructor contains the same generic “play back & apply” logic, i.e. unwanted code duplication)?
  • Or should there be both a traditional OOP constructor (as shown above) that properly initializes the object, and then all events but the first are void Apply(…)-ied to it?

I do not expect of answer to provide a fully working demo implementation; I’d already be very happy if someone could explain where my reasoning is flawed, or whether object initialization really is a “pain point” in most CQRS+ES implementations.

0

When doing CQRS+ES I prefer not having public constructors at all. Creating my aggregate roots should be done via a factory (for simple enough constructions such as this) or a builder (for more complicated aggregate roots).

How to then actually initialize the object is an implementation detail. The OOP “Don’t use initialize”-advice is imho about public interfaces. You should not expect that anyone that uses your code knows that they must call SecretInitializeMethod42(bool,int,string) – that’s bad public API design. However if your class does not provide any public constructor but instead there is a ShoppingCartFactory with the method CreateNewShoppingCart(string) then the implementation of that factory may very well hide any kind of initialization/constructor magic which your user then don’t need to know about (thus providing a nice public API, but allowing you to do more advanced object creation behind the scenes).

Factories get a bad rep from people thinking there’s too many of them, but used correctly they can hide away a lot of complexity behind a nice easy-to-understand public API. Don’t be afraid to use them, they’re a powerful tool which can help you make complex object construction much easier – as long as you can live with some more lines of code.

It’s not a race to see who can solve the problem with the least lines of code – it is however an ongoing competition as to who can make the nicest public API’s! 😉

Edit: Adding some examples on how applying these patterns could look

If you just have an “easy” aggregate constructor that has a couple of required parameters you can go with just a very basic factory implementation, something along these lines

public class FooAggregate {
     internal FooAggregate() { }

     public int A { get; private set; }
     public int B { get; private set; }

     internal Handle(FooCreatedEvent evt) {
         this.A = a;
         this.B = b;
     }
}

public class FooFactory {
    public FooAggregate Create(int a, int b) {
        var evt = new FooCreatedEvent(a, b);
        var result = new FooAggregate();
        result.Handle(evt);
        DomainEvents.Register(result, evt);
        return result;
    }
}

Of course, exactly how you divide creating the FooCreatedEvent is in this case up to you. One could also make a case for having a FooAggregate(FooCreatedEvent) constructor, or having a FooAggregate(int, int) constructor that creates the event. Exactly how you choose to divide the responsibility here is up to what you think is the cleanest and how you have implemented your domain event registration. I often choose to have the factory create the event – but it’s up to you since event creation is now an internal implementation detail that you can change and refactor at any time without changing your external interface. An important detail here is that the aggregate does not have a public constructor and that all the setters are private. You don’t want anyone to use them externally.

This pattern works fine when you’re just more or less replacing constructors, but if you have more advanced object construction this may become way too complex to use. In this case I usually forego the factory pattern and turn to a builder pattern instead – often with a more fluent syntax.

This example is a bit forced since the class it builds isn’t very complex, but you can hopefully grasp the idea and see how it would ease more complex construction tasks

public class FooBuilder {
    private int a;
    private int b;   

    public FooBuilder WithA(int a) {
         this.a = a;
         return this;
    }

    public FooBuilder WithB(int b) {
         this.b = b;
         return this;
    }

    public FooAggregate Build() {
         if(!someChecksThatWeHaveAllState()) {
              throw new OmgException();
         }

         // Some hairy logic on how to create a FooAggregate and the creation events from our state
         var foo = new FooAggregate(....);
         foo.PlentyOfHairyInitialization(...);
         DomainEvents.Register(....);

         return foo;
    }
}

And then you use it like

var foo = new FooBuilder().WithA(1).Build();

And of course, generally when I turn to the builder pattern it’s not just two ints, it may contain lists of some value objects or dictionaries of some kind of maybe some other more hairy things. It is however also quite useful if you have many combinations of optional parameters.

The important takeaways for going this way is:

  • Your main objective is being able to abstract object construction so that the external user doesn’t have to know about your event system.
  • It’s not that important where or who registers the creation event, the important part is that it gets registered and that you can guarantee that – apart from that, it’s an internal implementation detail. Do what fits your code the best, don’t follow my example as some sort of “this is the right way”-thing.
  • If you want to, by going this way you could have your factories/repositories return interfaces instead of concrete classes – making them easier to mock for unit tests!
  • This is a lot of extra code sometimes, which makes many people shy away from it. But it’s often quite easy code compared to the alternatives and it does provide value when you do sooner or later need to change stuff. There’s a reason that Eric Evans talks about factories/repositories in his DDD-book as important parts of DDD – they are necessary abstractions to not leak certain implementation details to the user. And leaky abstractions are bad.

Hope that helps a bit more, just ask for clarifications in comments otherwise 🙂

1

In my opinion, I think the answer is more like your suggestion #2 for existing aggregates; for new aggregates more like #3 (but processing the event as you suggested).

Here’s some code, hope it is of some help.

public abstract class Aggregate
{
    Dictionary<Type, Delegate> _handlers = new Dictionary<Type, Delegate>();

    protected Aggregate(long version = 0)
    {
        this.Version = version;
    }

    public long Version { get; private set; }

    protected void Handles<TEvent>(Action<TEvent> action)
        where TEvent : IDomainEvent            
    {
        this._handlers[typeof(TEvent)] = action;
    }

    private IList<IDomainEvent> _pendingEvents = new List<IDomainEvent>();

    // Apply a new event, and add to pending events to be committed to event store
    // when transaction completes
    protected void Apply(IDomainEvent @event)
    {
        this.Invoke(@event);
        this._pendingEvents.Add(@event);
    }

    // Invoke handler to change state of aggregate in response to event
    // Event may be an old event from the event store, or may be an event triggered
    // during the lifetime of this instance.
    protected void Invoke(IDomainEvent @event)
    {
        Delegate handler;
        if (this._handlers.TryGetValue(@event.GetType(), out handler))
            ((Action<TEvent>)handler)(@event);
    }
}

public class ShoppingCart : Aggregate
{
    private Guid _id, _customerId;

    private ShoppingCart(long version = 0)
        : base(version)
    {
         // Setup handlers for events
         Handles<ShoppingCartCreated>(OnShoppingCartCreated);
         // Handles<ItemAddedToShoppingCart>(OnItemAddedToShoppingCart);  
         // etc...
    } 

    public ShoppingCart(long version, IEnumerable<IDomainEvent> events)
        : this(version)
    {
         // Replay existing events to get current state
         foreach (var @event in events)
             this.Invoke(@event);
    }

    public ShoppingCart(Guid id, Guid customerId)
        : this()
    {
        // Process new event, changing state and storing event as pending event
        // to be saved when aggregate is committed.
        this.Apply(new ShoppingCartCreated(id, customerId));            
    }            

    private void OnShoppingCartCreated(ShoppingCartCreated @event)
    {
        this._id = @event.Id;
        this._customerId = @event.CustomerId;
    }
}

public class ShoppingCartCreated : IDomainEvent
{
    public ShoppingCartCreated(Guid id, Guid customerId)
    {
        this.Id = id;
        this.CustomerId = customerId;
    }

    public Guid Id { get; private set; }
    public Guid CustomerID { get; private set; }
}

Well, the first event should be that a customer creates a shopping cart, so when the shopping cart is created you already have a customer id as part of the event.

If a state holds between two different events, by definition it is a valid state. So if you say that a valid shopping cart is associated to a customer, this means that you need to have the customer info when creating the cart itself

2

Note: if you don’t want to use aggregate root, “entity” encompasses most of what you are asking about here while side stepping the concerns about transaction boundaries.

Here’s another way of thinking about it: an entity is identity + state. Unlike a value, an entity is the same guy even when his state changes.

But the state itself can be thought of as a value object. By this I mean, the state is immutable; the history of the entity is a transition from one immutable state to the next — each transition corresponds to an event in the event stream.

State nextState = currentState.onEvent(e);

The onEvent() method is a query, of course — currentState isn’t changed at all, instead currentState is calculating the arguments used to create the nextState.

Following this model, all instances of Shopping cart can be thought of as starting from the same seed value….

State currentState = ShoppingCart.SEED;
for (Event e : history) {
    currentState = currentState.onEvent(e);
}

ShoppingCart cart = new ShoppingCart(id, currentState);

Separation of concerns – the ShoppingCart processes a command to figure out what event should be next; the ShoppingCart State knows how to get to the next state.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật