I’m still fairly new to DDD applications. I’m reading Eric Evan’s “Domain Driven Design” and have read Employing the Domain Model Pattern by Domain Events Salvation by Udi Dahan…
One thing I can’t make out though is how should information about the successful or unsuccesful completion of Domain Events be returned as feedback to the user (i.e. UI Layer)?
For example, we could have the following Application Layer code:
// Application Layer
public void SubmitOrder(OrderData data)
{
var customer = GetCustomer(data.CustomerId);
var shoppingCart = GetShoppingCart(data.CartId);
customer.Purchase(shoppingCart);
}
// Domain Model
public class Customer
{
public void Purchase(ShoppingCart cart)
{
// something done with the cart...
DomainEvents.Raise(new CustomerPurchaseCompleted() { Customer = this, ShoppingCart = cart });
}
}
Now let’s say we have the following event handler that sends a confirmation email to the customer if the customer has an email address specified.
public class CustomerPurchaseCompletedHandler : Handles<CustomerPurchaseCompleted>
{
public void Handle(CustomerPurchaseCompleted args)
{
if (args.Customer.Email != null) {
// send email to args.Customer
}
else {
// report that no email will be sent...
}
}
}
My question is: How should I “bubble up” a feedback message to the UI layer saying that no email will be sent because the customer doesn’t have an email set?
The options as I see them today are along the lines of:
-
Have the UI layer check if the Customer has an email and react accordingly with a message. This seems bad since the UI would be aware that an email is supposed to be sent, which is a application level information.
-
Throw a
UserHasNoEmailExceptionwhen no email is present and catch that information somewhere. That’s really bad because exceptions should not be used to return information, plus it’s not a fatal error and should not abort other handlers… -
Have
SubmitOrder()return someList<FeedbackMessage>. This would require changing thePurchase()andDomainEvents.Raise()methods to also return this list. This leads to the Domain Model knowing what the UI should of should not display…
Neither of these three options seems really good and practical. So how do DDD experts do it?
Thanks.
Another option you have is to implement another event handler which is specifically responsible for notifying the UI that a customer doesn’t have an email address. So where CustomerPurchaseCompletedHandler doesn’t send an email, this handler would notify the UI. This handler would be part of the UI layer. A good way to notify the UI would be to inject an event aggregator into this handler:
Overall, this is essentially approach 1. True, the UI layer is now aware that an email is to be sent, however the UI has to have that knowledge regardless because it needs to render a message stating that no email is to be sent. Display a message is a UI concern and by leaving the handler implementation as part of the UI layer you keep it as such. The problem with this approach is that you are checking whether the customer has an email twice. Additionally, the sending of an email is not directly tied to the UI notification.
Another option is to introduce another event to indicate that a purchase was completed for a customer that doesn’t have an email. The UI could then subscribe to this event. The downside of this approach is that you are creating an event specifically for a UI requirement not to express domain knowledge.