4
votes

As I am reading some CQRS resources, there is a recurrent point I do not catch. For instance, let's say a client emits a command. This command is integrated by the domain, so it can refresh its domain model (DM). On the other hand, the command is persisted in an Event-Store. That is the most common scenario.

1) When we say the DM is refreshed, I suppose data is persisted in the underlying database (if any). Am I right ? Otherwise, we would deal with a memory-transient model, which I suppose, would not be a good thing ? (state is not supposed to remain in memory on server side outside a client request).

2) If data is persisted, I suppose the read-model that relies on it is automatically updated, as each client that requests it generates a new "state/context" in the application (in case of a Web-Application or a RESTful architecture) ?

3) If the command is persisted, does that mean we deal with Event-Sourcing (by construct when we use CQRS) ? Does Event-Sourcing invalidate the database update process ? (as if state is reconstructed from the Event-Store, maintaining the database seems useless) ?

Does CQRS only apply to multi-databases systems (when data is propagated on separate databases), and, if it deals with memory-transient models, does that fit well with Web-Applications or RESTful services ?

3
I suggest you read up some more on CQRS and Event Sourcing, Commands and Events because they are totally different things. Your question mixes them up and adds persistence on top of that, making it even more blurry. Persistence is only an implementation detail in DDD, CQRS and Event Sourcing, you can and should first approach these techniques as if everything happened in memory.guillaume31
Thanks, another point in my question : have you experienced CQRS with an ASP.NET application ? As you can't maintain a context with ASP.NET applications between queries, do they fit well together ?Rénald
I didn't mean to do it in production ;) Just try to comprehend the basic principles of CQRS or ES without persistence to disk in mind. If you want to prototype it, in ASP.NET you can use static variables -- they last for the lifetime of the app domain. Again, I don't recommend it for real life applications (memory is volatile and the app domain can be restarted in a number of more or less well documented circumstances).guillaume31
Thanks for your feedback Guillaume... :-)Rénald

3 Answers

4
votes

1) As already said, the only things that are really stored are the events. The only things that commands do are consistency checks prior to the raise of events. In pseudo-code:

public void BorrowBook(BorrowableBook dto){
    if (dto is valid)
        RaiseEvent(new BookBorrowedEvent(dto))
    else
        throw exception
}

public void Apply(BookBorrowedEvent evt) {
    this.aProperty = evt.aProperty;
    ...
}

Current state is retrieved by sequential Apply. Since this, you have to point a great attention in the design phase cause there are common pitfalls to avoid (maybe you already read it, but let me suggest this article by Martin Fowler).

So far so good, but this is just Event Sourcing. CQRS come into play if you decide to use a different database to persist the state of an aggregate. In my project we have a projection that every x minutes apply the new events (from event store) on the aggregate and save the results on a separate instance of MongoDB (presentation layer will access to this DB for reading). This model is clearly eventually consistent, but in this way you really separate Command (write) from Query (read).

2) If you have decided to divide the write model from the read model there are various options that you can use to make them synchronized:

  • Every x seconds apply events from the last checkpoint (some solutions offer snapshot to avoid reapplying of heavy commands)
  • A projection that subscribe events and update the read model as soon event is raised

3) The only thing stored are the events. Infact we have an event-store, not a command store :)

Is database is useless? Depends! How many events do you need to reapply for take the aggregate to the current state? Three? Maybe you don't need to have a database for read-model

3
votes

The thing to grok is that the ONLY thing stored is the events*. The domain model is rebuilt from the events.

So yes, the domain model is memory transient as you say in that no representation of the domain model is stored* only the events which happend to the domain to put the model in the current state.

When an element from the domain model is loaded what happens is a new instance of the element is created and then the events that affect that instance are replayed one after the other in the right order to put the element into the correct state.

you could keep instances of your domain objects around and subscribing to new events so that they can be kept up to date without loading them from all the events every time, but usually its quick enough just to load all the events from the database and apply them every time in the same way that you might load the instance from the database on every call to your web service.

*Unless you have snapshots of you domain object to reduce the number of events you need to load/process

2
votes

Persistence of data is not strictly needed. It might be sufficient to have enough copies in enough different locations (GigaSpaces). So no, a database is not required. This is (at least was a few years ago) used in production by the Dutch eBay equivalent.