I have been pondering over this problem for quite a while and have not
come up with a satisfactory solution yet. Assume you have two ARs,
"customer" and "order". I don't want the order to be part of the
customer AR, because I don't think that two users working on orders
simultaneously should engage in a race for the customer AR. If the
order were part of the customer AR, then the customer AR would become
stale to other users working on an order of the customer as soon as
one user saves changes to one of the customers orders.

Now assume the customer has an "open order limit", stating that unpaid
orders cannot exceed $ X,-. When adding or saving an order for the
customer the customers order limit will be checked. In the order
entity Something like "if (this.Customer.OrderLimit <
this.Customer.TotalOrderValue) throw new Exception("Customers order
limit exceeded");" will do.

If I add or change an order, the orders invariants are protected by
the order aggregate root. The "order limit invariant" defined in the
customer, however, involves both the customer AR and the order AR.
Theoretically, the customers order limit could be reduced at the same
time an order is added. You could have the following situations:

I) Initally TotalOrderValue = 100, OrderLimit = 200. Now an order with
value 50 is added and at the same time the order limit is reduced to
150 (2 different users in 2 separate sessions). In this case the new
TotalOrderValue is 150, which is still inside the new order limit of
150. So in this case both changes should pass, the new order can be
saved and the change to the order limit can be saved as well.

II) Initally TotalOrderValue = 100, OrderLimit = 200. Now an order
with value 60 is added and at the same time the order limit is reduced
to 150. In this case the new TotalOrderValue is 160, which is outside
the new order limit of 150. So in this case either the new order
cannot be persisted, or the change in the order limit will be refused
- depending on which transaction finishes first.

If the order were to be part of the customer AR, the "order limit
invariant" would be fully protected. However, then case I) would lead
to either a rejection of the added order or to a rejection of the
changed order limit for the customer, because both changes make the
customer AR stale. That would be unreasonable, because the combined
effect of both changes does not violate the "order limit invariant",
so a stale object (customer) exception would be too restrictive here.
Worse yet, two users would not be allowed to add orders to the
customer AR simultaneously.

So I am thinking of inventing something like "Invariant Roots". The
"customer order limit" would be such an invariant root. Changes to the
customers order limit would check the invariant root and make it stale
by incrementing its version number. Similarly, changes to an order
would do the same. The difference to an aggregate root is that if an
invariant root has become stale, the action is not rejected. It is
simply repeated. This is what would happen in the above examples I)
and II):

I) Assume the change of the order limit from 200 to 150 is committed
first. When the new order checks the order limit initially, it sees a
limit of 200, compared to a total order value of 150. When committing
the new order, the order limit invariant has become stale because it
has been changed from 200 to 150. Now the action is not rejected, it
is simply repeated inside a cleared session. On the second try, the
order sees the customers order limit at 150, compared to a total order
value of 150. That's OK, and now the order limit invariant is not
stale at transaction time, and the new order can be persisted.

II) In this case, on the second try, the new order limit is 150, and
the total order value is 160. So now the order limit invariant is
violated and the new order cannot be saved with the error being "Order
limit exceeded.".

This is a hypothetical example, and one could argue for a better
model. However, assuming this were a realistic situation, are there
any standard, and especially easier ways to deal with a situation like
this?

Any help is greatly appreciated.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"nhusers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/nhusers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to