Sponsored By Aspose - File Format APIs for .NET

Aspose are the market leader of .NET APIs for file business formats – natively work with DOCX, XLSX, PPT, PDF, MSG, MPP, images formats and many more!

A Different Frame of Reference

Writing this in the Web UI which kind of sucks because I have not found a good blogging utility in unix yet. I kinda miss livewriter.

 

One of the biggest advantages of using Event Sourcing with CQRS is that is drastically changes how we even think about our problems. Let’s go through an example.

 

When I have an inventory item that is in a deactivated state and I deactivate it, it should throw an alreadydeactivatedexception

Or let’s try another one:

When a gold customer makes a purchase they should receive a 15% discount on their purchase.

Basically all of our use cases can boil down to “given some state, when some action, expect something”

 

Making statements like these leaves off many things. How do we know that an inventory item can even get into a deactivated state? If it can’t is there any purpose in testing what happens if it is? When we represent current state we talk about any possible state the object could have, not the finite number of states an object can get into. What happens if we never implement a deactivate method?

We also are coupling our use cases to the concept of current state. Unfortunately our representation of current state has a funny way of changing over time. 

 

What happens when we Event Sourcing?

When an inventory item that has been deactivated is deactivated and alreadydeactivatedexception should be thrown

When a customer that has been marked as a gold customer purchases an item they should receive a 15% discount

 

These use cases are describing series of behavior not current state! We know that we are testing relevant items because we are giving series of behaviors that the object can do, as such the state that we end up with is necessarily a state the object could actually be in.

What is more important is that our use cases are being structured much differently. Instead of describing things as …

“given some state, when some action, expect something”

we are describing things as:

“given the system has done these behaviors, when some action, expect something”

 

The difference between these two is HUGE!!! 

 

1) The first method requires specialization for every type of object (eg: state representation) where as the second one is a generic one for all use cases.

Consider:

Given: A series of events

When: A command

Expect: A series of events

 

Since events and commands are simple messages this can be genericized in < 30 lines of code for all objects.

 

2) The first one couples our use case language to our internal domain structure where as the second one does not, it describes the actions in terms of a calculus of themselves. This is to me the most important part as we can freely change our internal structures without worry, and our tests will remain just as relevant.

 

Sorry for the run by posting but I hope some people gain something out of this.

This entry was posted in DDD, Event Sourcing, Testing. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

14 Responses to A Different Frame of Reference

  1. Pingback: The death of mocks? « Cav’s Weblog

  2. Greg says:

    David is that clunky or is that how the domain expert would actually talk about the situation? They tend to describe not how something is but how it got there. The reason for this is often that how it got there is VERY important.

    Is there a conceptual difference between a customer being marked/unmarked and them never having been marked in the first place?

  3. David says:

    “why would I ever be describing behavior that *didn’t* happen? :)”

    Fair comment!

    I’m trying to get to grips with how the sentence “given the system has done these behaviors, when some action, expect something” is conceptually different from thinking about state. In my mind, replaying behaviours is a way of reproducing state.

    I suspect I’m missing something and I’m trying to work out what that is.

    So when you had:
    “When a customer that has been marked as a gold customer purchases an item they should receive a 15% discount”

    I thought of the logical but rather clunky counterpart:
    “When a customer that has been marked as a gold customer _and then been unmarked as a gold customer_ purchases an item they should _not_ receive a 15% discount”

    I suspect I’m looking at that the wrong way, but I’m not exactly sure how…

  4. Dirk says:

    Code will definitely help :-)
    I’m not that familiar with the terminology, so I’m sure I’m missing something, but in the post I read “… we are giving series of behaviors that the object can do …”, so I was assuming that there was more happening behind the scenes than just setting the state.
    From your comments I understand you are rather talking about the last option I mentioned, i.e. having events for each of the properties (or combinations of them) that define the state, but then I have difficulty seeing how there is a huge difference between setting the state by running an event that sets properties or by setting the properties directly; I will still have to apply specific manipulations for the behaviors I am trying to mimic.
    But I look forward to being enlightened :-)

  5. Stacy Murray says:

    Looking forward to the code – and maybe a flow diagram too. It just hit me when you explained that we replay events just to set state. For some reason I thought of replaying events would kick-off “command” logic some how, and create a mess, but that’s obviously not the case. I’m starting see value in the event store far beyond hydrating domain objects, e.g. metrics, integration testing, user activity feed, etc. Great! Thanks for the concept.

  6. Greg says:

    hey guys I will put a post with code … sometimes that makes things easier :)

  7. Greg says:

    @dirk what are the “errors” that could be in the events? There is no logic when replaying an event just the setting of state internally. behaviors only exist when processing a command …

    and how are these not unit tests? The object is being tested in complete isolation.

  8. Greg says:

    @David why would I ever be describing behavior that *didn’t* happen? :)

  9. Greg says:

    @stacy

    With CQRS you could ask the read model the current state.

  10. Dirk says:

    Interesting statement, but I am not sure I get the practical consequences of the picture you are painting here.
    If this is about how to build your domain, I do not quite see the difference; that client may have acquired his gold status years ago, so I am sure there will be some state stored somewhere.
    If it is about how to test your software, you seem to propose to ditch unit tests in favor of integration tests because instead of “simply” setting some initial state on domain objects, you actually run a number of events that may or may not have flaws in them.
    If on the other hand this requires us to have a simple SetProperty event for each property, I do not really see how this decouples from internal domain model
    What am I misunderstanding?

  11. Szymon Kulec says:

    Hello,
    I do agree, that your point of view is a paradigm shift and making series of events the “given” makes logic look much different. Hence, how would you check, in terms of code”, that series of events took place? I hope you doesn’t mean going through the event store;-)

    Take care

  12. David says:

    I can see the difference (and I’m attracted to the Event Sourcing model), but at first glance it’s not obvious to me that describing behaviour is necessarily simpler than describing state.

    eg:
    “When a customer that has been marked as a gold customer purchases an item they should receive a 15% discount”

    Wouldn’t that quickly become something more like:

    “When a customer that has been marked as a gold customer _and not been unmarked as a gold customer_ purchases an item they should receive a 15% discount”

    and easily end up as something like:
    “When a customer that has been marked as a gold customer _and not been unmarked as a gold customer and has not cancelled their account and …_ purchases an item they should receive a 15% discount”

  13. Stefan Moser says:

    I’ve been thinking about this for the past little while and the mechanics of writing tests in this style. I think it makes a lot of sense, but what happens in the case where it takes *a lot* of events to get an object into a given state. Can we somehow use the concept of snapshots? The gold customer example made me think of it, what if our customer is considered gold once he has bought 1000 items from our store? It seems excessive to pump 1000 orders through the customer just to get the expected state.

  14. Stacy Murray says:

    Event sourcing does not seem practical except in special use cases. Since you have eliminated domain state storage, now you need the db/storage AND domain code AND runtime OS to answer any customer question about state. Normally, you could just query the db and get state. I can easily see EV running along side of state as metadata to support website metrics, for example. But not as a wholesale replacement for state in most cases.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>