For more complex cases you can use SOM approach (Streamlined Object Modeling).
An event in SOM is a Transaction over which multiple domain objects collaborate.
- To go from command to event the Aggregate Root creates the Event and adds collaborations (entities and value objects) to the event and let the event direct the collaboration;
- To go from event to collaborators again let the Aggregate find collaborators based on the event data (none found create), and call apply on each of them.
So for instance say we are calling changeProduct to an AR Order, we get the event ProductOrderChanged
changeProduct(Guid productid, int numberOfItems) ->
ProductOrderChanged e = new ProductOrderChanged() ->
Product p = this.listOfProducts[productId];
Customer c = this.customer;
e.addCustomer(c);
e.addProduct(p);
e.addNumberOfItems(numberOfItems);
e.addOrder(this);
e.apply();
apply() ->
e.product.apply(this);
e.order.apply(this);
e.customer.apply(this);
Don't have time to make an example, but read the implementation samples of SOM around transactions, and adapt accordingly with the pointer above.
Cheers,
Nuno
A few points here:
* An entity have no identity outside the aggregate, so a guid is an
overkill. Usually I find that entities have an external identifier
(e.g. name) that can be used instead. If this identifier is mutable
then usually either it's not the true identifier or it starts an
interesting conversation about what actually is the identity of this
entity.
* IME it's better to source all events from each Entity but decorate
them on the AR:
Activity.Rename(string newName) {
ApplyChange(new ActivityRenamed(newName));
}
Activity.Apply(ActivityRenamed evt) {
this.name = evt.NewName;
}
Project.Rename(Guid id, string newName) {
var activity = activities[id];
activity.Rename(newName);
}
Project.Apply(ActivityAdded evt) {
var activity = new Activity(this, e.Id, e.Name);
activities.Add(e.Id, activity);
activity.On(evt => ApplyChange(new ProjectActivityChanged(evt.Id, evt)));
}
External consumers can't see ActivityAdded without the external
ProjectActivityChanged envelope.
Best regards,
Daniel Yokomizo
Hmm I think I may have been thinking about Aggregates the wrong way,
so is it typical to just store lists of guid's inside the AR instead
of the actual entities?
--
------------
http://www.thepopeisdead.com