Reputation: 751
This is a noob (I think) Event Sourcing question.
As an example we have:
Shoemaker Bob has:
Say we have a "shoe_repair_order" (Aggregate Root?)
We have a shoe repair order from Alice that happened sometime in July, before shoemaker Bob moved his business location down the block.
Let's say that Alice is looking at this order in December. Obviously she does not have to know that Bob moved his business. When she sees her order, I think she should see (at least) the old business location and/or "Ordered at 5 Baker Street (New address is 11 Baker street - updated on October 6)".
Question: How do we design the Event-Sourced system to show the old addresses for orders?
OR
Do we issue an "OrderLocationAdded" event with a reference to an address "88d8 AT VERSION 1", so that we know to look for VERSION 1 of our business location. We will have to replay events on "shoemaker_business_locations" until we see "version X" of our address (version 1 in our case). That is what we will have to do to all of older orders whose version of addresses are below the version that is set currently (version 1).
Some other way?
Maybe our read-model just stores all of the address information at different versions, and when queried for a certain version we don't have to replay events in our write-model, but simply grab an address that is at version 1 from our read-model?
Upvotes: 1
Views: 710
Reputation: 4002
Here are a few options:
Upvotes: 0
Reputation: 431
The answer to your problem certainly depends on how you have defined your domain models (specifically how your Aggregates are defined).The way I would approach this problem is to have two aggregates:
ShoeMaker Aggregate (which in your case stores all the information like name of the shoemaker business, info about this business' owners, list of all the addresses for this shoemaker where each address can have information like email, phone number, and a bool field called current which can be true for the current address. I imagine this AR would have a command called - "ChangeShoeMakerCurrentAddress" which would raise an event called "ShoeMakerAddressesChanged".
Order Aggregate (which would have all the information about an order like customer name, price, details, order date, delivery date etc.).
Let's say we have a read-model called "ShoeMakerOrderReadModel" which can subscribe to events raised by ShoeMaker Aggregate and Order Aggregate. This read-model listens to events and denormalize them into a POJO/POCO object. This POCO/POJO model can have a list of shoemaker addresses (where each address can have information like email, phone number, and a bool field called current which can be true for the current address.) This AR can definitely subscribe to "ShoeMakerAddressesChanged" events from ShoeMaker Aggregate and then update the list of shoemaker addresses.
I hope this helps!
Upvotes: 1
Reputation: 17683
The answer is very simple thanks to CQRS: you must not listen to BusinessMovedToANewLocationEvent
in the OrderDetailsReadModel
. You just lookup and store only once the current Business address
in the Order details
in this Read model
when the OrderPlacedEvent
happens.
In this way you don't have to include any Address value object
into the event. The Read model
does all the work.
You could listen to the event, if you need for other reasons, but just don't update the address. Fir example, the Read model
could be even smarter and additionally keep an addressChangedInTheMeanTime
boolean
flag in order to tell Alice
that the Address
that she sees is an old one but thus depends on your business needs.
Upvotes: 0
Reputation: 6510
I think the best way to do this will ultimately depend on how you've designed your Domain Model, but here's how I would approach the problem:
We need to represent Addresses in our Domain Model. This means, addresses will either be Value Objects, Entities, or Aggregates. Of the three, an Address could really only be a Value Object or an Entity in this Domain, since we are a shoe repair application and not an address book. Entities have certain properties, such as being distinguished by their ID, and certain restrictions, like only being part of one Aggregate, that Addresses don't seem to meet. Therefore, I would see an Address being a Value Object in this Domain.
When defining the OrderLocationAdded event on the "shoe_repair_order" Aggregate, you need to decide whether to include the full details of the Address on the event, or use a reference to the Address. Since the Address is a Value Object (it is defined by its data, not by an ID), the answer would be to include the Value Object on the event. This way, when you replay the events to build the current state of the order, it will still have the details of the original address.
If you want to also display the new address on the order, you can use another event, such as BusinessMovedToNewLocation, with the details of the new address, and add this to the order. This event would not replace the original address, it would just allow you display the informational message that the business is now located at a different location.
Upvotes: 1