--
You received this message because you are subscribed to the Google Groups "DDD/CQRS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
- Ask the business how important this is. [we all assume "VERY" when the answer could be "very"].- Do what you can to validate the command to minimize the chance of failure downstream.- Discuss/define/document what [manual?] processes will be employed in the case of failure.- Measure how often you get into the failure state- Ask the business how important this is.......
On Tue, Jan 14, 2014 at 4:47 PM, Alexandre Potvin Latreille <alexandre.pot...@gmail.com> wrote:
I've read a lot of blog posts about error handling in DDD/CQRS and none every really explained (or perhaps I did not understand) most of the questions I had so here we go:The contextLet's say we take an example where the client issues a ChangeBillingInformation command that allows to modify the billing address, the customer name as it appears on the card as well as other related information such as the card number. There are various reasons this command might be rejected. For example, the card number might be invalid or the billing address might not match the one registered with the bank for this card.The problemWhile the UI could potentially validate the format of all fields by itself, it certainly couldn't know if the card number exists without invoking a remote service. Since I do not want to replicate business logic in the UI and limit roundtrips to the server as much as possible (web app), I believe these rules should be handled during the command handling process.However, I find it quite challenging to come up with an efficient and elegant solution to provide the client with all the necessary information so that the user knows all the reasons that made his request fail.In order to correctly perform this task, I believe the client must be provided a collection that states (for every error) what are the command properties involved, the error code and a default localized message. The propertie names would be useful for error placement in the UI while an error code would allow the UI generating a custom localized error message, however the service itself should probably return some default localized messages to avoid imposing this burden on the client.The angry clientIf you ever tried to change your billing information from your PS4 to access the Play Station Network (PSN), you know how frustrating it is when you recieve a message that is way too general such as "Invalid credit card information". I agree that's probably for security purposes, but you get the point. The client will get angry if you can't tell him exactly what has to be fixed.The solution?Does anyone have an idea how to implement such mechanism with CQRS? Is there already a pattern that I am not aware of or perhaps am I misunderstanding some concepts which leads to increasing complexity? So far I really do not see any other way than having the command handler itself (or using a validator object) validate all these details before manipulating the aggregate, but then what about rules that were perhaps already enforced by value objects or aggregate methods? Woudln't they have to be replicated? Is that acceptable?Thanks!
--
You received this message because you are subscribed to the Google Groups "DDD/CQRS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
Right. There's nothing particular to cars about validating inputs.
I suppose the op may mean handling eventual consistent errors assuming you're handling command off a queue? In that case, establish av back channel to communicate these errors to the users, assuming the user can correct the problem. Signalr, email, etc.
--
--
The difference is that I am trying to find a solution which won’t violates DDD principles and work well with tactical modeling tools such as value objects. The client could always get so smart that it could validate everything by itself, but it seems like an hacky fix for a domain that has the ability to enforce rules but the inability to report errors properly. I see very well how value objects could be used in the domain to enforce addresses format validity, customer's name validity, credit card number format and how specifications or another external validator mechanism could be used to validate that the billing information as a whole is valid for the given card, but not what would be the most efficient way of collection error details and report them.
Let’s take the following handler example (pseudo-code):
function handle(cmd) {
var customer = _customerRepository.getById(cmd.customerId);
customer.changeBillingInformation(new BillingInformation(
new VisaCreditCard(cmd.creditCardNumber, ...),
new Address(...),
...
));
...
}
There's no issue enforcing rules with such code. The handler doesn't even know that validation takes place and that's great, but the handler also can't return a detailed error report. At its best it can throw a meaningful exception, but that doesn't help with multiple rule violations.
So far the only solution I've seen was to duplicate all the rules already carefully enforced by value objects using a validation framework of some kind which would be used to validate commands from handlers, but then I'm asking myself if that wouldn't consist of a validate everywhere anti-pattern if I keep validating within the value objects as well? Not to say that wouldn’t be very DRY, especially when we take in consideration that some of these rules might have to be replicated on the remote client, and that there might be multiple client implementations.
Perhaps it would be easier without enforcing the always-valid entity paradigm? This way we could simply construct a BillingInformation object, declare rules that a framework can consume and have the command handler use the framework to validate the object? It seems to work for collecting simple data-oriented errors, but not so much for business rules enforced during processes such as (fictive rule) “a client cannot change his billing information more than twice a day”. I understand that these rules should be mutually exclusive, but it would be nice if the errors could still be reported the same way.
Another approach I thought of would be to pass an OperationResult object around through every method that might communicate an error. Errors would be added to the OperationResult instance as the process gets executed. Then the handler would have to check whether there were issues or not before persisting changes using the repository. We also need a mechanism to halt the process completely in case it doesn’t make sense to continue. In this case perhaps a method like recordErrorAndThrow could be added on the OperationResult object.
The code could look like:
function handle(cmd, result) {
var customer = _customerRepository.getById(cmd.customerId);
customer.changeBillingInformation(new BillingInformation(
new VisaCreditCard(cmd.creditCardNumber, result),
new Address(…, result),
result
), result);
if (result.ok()) _customerRepository.save(customer);
}
What about such an approach? Obviously that wouldn’t help with rules validation on the client, but would help to have good error reporting from domain operations.
--
Remember that being DRY via code reuse is a form of coupling. Use with caution. Those rules may not be as duplicative as they appear during the brainstorming phase.
Where/how to handle the billing address invariant is a question for stakeholders. Do you want me to reject the order in this case and possibly lose the customer completely or should accept the order and handle the billing issue through a different channel: email, phone call (chance to upsell!), etc.
--