Has for detailed description I'm not sure what it means. Is it the full description in the Product Catalogue?
If that is the case and maybe a simple link to another view is all that is necessary to be presented in the UI. If that is not the case you have two options:
1) Shared a product view within the Order BC with the Product Catalogue BC
2) Have the UI handling the Mashup between a view in the Product Catalogue BC and the Order BC
> Also, you would not want to persist the enriched event since your
> handler does not make use when applying / replaying. Except if your
> domain code enriches the event internally. (Good?)
Right.
Cheers,
Nuno
> In terms of the question “When should I enrich my events” it seems
> that @seagile (and Nuno) are pointing to publishing “rich events” from
> the domain itself... (right?)
No, that is not my opinion :) At least that is not what I wanted to write.
Cheers,
Nuno
In terms of the question “When should I enrich my events” it seems
that @seagile (and Nuno) are pointing to publishing “rich events” from
the domain itself... (right?) I think Rinat (and Greg?) also has this
opinion:
http://stackoverflow.com/questions/4064067/event-sourcing-and-read-model-generation
We do a mix of mass as they are called on the UI for writing information like who changed what (the username etc) and option 5 adding data at the command handler leveell. For us the command is a kind of coordinator validation additional rules and enriching the command for the domain.
We regularly publish events from the domains we don't really use in the domain at this time.
//---><8--------------------------- UI loads viewmodels and generates commands ---- UI.Viewmodel = ViewModelStore.Query(UI.SomeParameters); UI.HandleInput = GeneratedCommand => CommandStore.Add(GeneratedCommand); //---><8--------------------------- Commands to events ----------------------------------------- // This uses an iterator because a command should only be handled one time while(CommandStore.HasCommands) { var cmd = CommandStore.Next(); var cmdhandler = CommandHandlers.GetHandlerForCommand(cmd); cmdhandler.DecorateCommand(cmd); var AR = ARStore.CreateOrLoad(cmdhandler.GetARInfo(cmd)); cmdhandler.HandleCommand(AR,cmd); EventStore.AddRange(AR.NewEvents); } //---><8--------------------------- Events to viewmodel/AR updates or commands---------- // this uses a pointer instead of an iterator since events can be handled multiple times while(EventStore.HasNewEvents(ref someeventpointer)) { var evt = EventStore.Next(ref someeventpointer); foreach (var eventhandler in ARHandlers.GetHandlersForEvent(evt)) { var AR = ARStore.CreateOrLoad(eventhandler.GetARInfo(evt)); eventhandler.ProcessEvent(AR,evt); if (AR.HasChanges) ARStore.SaveChanges(AR); } foreach (var eventhandler in SagaHandlers.GetHandlersForEvent(evt)) { var saga = SagaStore.CreateOrLoad(eventhandler.GetSagaInfo(evt))); var cmd = eventhandler.ProcessEvent(saga,evt); if (cmd!=null) CommandStore.Add(cmd); if (saga.IsEOL) SagaStore.Purge(saga); else if (saga.HasChanges) SagaStore.SaveChanges(saga); } foreach (var eventhandler in ViewModelHandlers.GetHandlersForEvent(evt)) { var viewmodel = ViewModelStore.CreateOrLoad(eventhandler.GetViewModelInfo(evt)); var ischanged = eventhandler.ProcessEvent(viewmodel,evt); if (viewmodel.HasChanges) ViewModelStore.SaveChanges(viewmodel); } } //---><8---------------------------
//---><8--------------------------- Time triggers for sagas ---------- while (SagaStore.HasOverDueSagas()) { var saga = SagaStore.NextOverdueSaga(); var overduehandler = SagaHandlers.GetHandlerForOverdue(saga); var cmd = overduehandler.ProcessOverdue(saga); if (cmd!=null) CommandStore.Add(cmd); if (saga.IsEOL) SagaStore.Purge(saga); else if (saga.HasChanges) SagaStore.SaveChanges(saga);
Cheers,
Nuno
You need to know what defines something to be an Order in business terms. If an Purchase Order line is defined as (ProducRef, Name, base price, ....) that is what should be. So all this information is passed when the user declares the products he/she wants to order.
Notice, your are not enriching anything. You just stating what it is, not more, not less. If someone changes the description of the product in the order for Ferrari G40 to Potatoes someone would find incomprehensible that that have order a $300.000 bag of potatoes.
> 1) Enrich when publishing / persisting to the EventStore. Thus, add
> the description property to the event and fill it when publishing.
No
> 2) When handling the event use the read model / denormalizer also.
No
Cheers,
Nuno
> I have an event with only a reference to some data. For
> example ProductId in OrderLineItemAddedEvent. How and when should I
> resolve/get the ProductDetailedDescription when I need to populate the
> read model?
Has for detailed description, it can be a simple link to the UI to some other web page with the full product description.
Cheers,
Nuno
If you where to archive an Order what elements should be there? These are the elements that make up Order as such be in part of its definition.
On an another note. This make sound strange ... an Order is not an Order until placed :) So probably you should not have methods such AddOrderLine and so on.
Instead, use a separate concept that Builds the Order on behalf of the User. Once building process is concluded, the result is an Order.
Check the Builder Pattern (http://en.wikipedia.org/wiki/Builder_pattern).
You can have the Shopping Cart acting as the builder or some other concept.
Hope it helps,
Nuno
PS: A Plane is not a missile up until built. For instance, before being built a Plane cannot fly so how can it be a Plane before? Hope it helps.