Suppose you have 2 classes: Man and Rabbit. A person can do several things to a rabbit; he / she can either feed him, buy and become his owner, or give him away. A rabbit can have no more than one or no more than 1 owner at a time. And if he is not served for a while, he may die.
Class Person { Void Feed(Rabbit r); Void Buy(Rabbit r); Void Giveaway(Person p, Rabbit r); Rabbit[] rabbits; } Class Rabbit { Bool IsAlive(); Person pwner; }
There are several observations from the domain model:
- Face and Rabbit may have links to each other
- Any actions on 1 object can also change the state of another object
- Even if no explicit actions are called, there may still be a state change in the objects (for example, Rabbit can starve to death, and this forces him to be removed from the Person.rabbits array)
As a DDD, I believe that the right approach is to synchronize all calls that can change states in the domain model. For example, if a person buys a rabbit, he will need to purchase a castle in the face in order to make changes to the array of rabbits. And another castle in Rabbit to change ownership before releasing the first. This will prevent a race condition in which 2 people claim to own a small rabbit.
Another approach is to allow the database to handle all of these synchronizations. Who makes the first win of the call, but then the database should have some kind of business logic to find out if it is a valid transaction (for example, if the rabbit already has an owner, he cannot change his owner, unless the Person gives it away )
Both approaches have both pros / cons, and Id expects the “best” solution to be somewhere in between. How would you do this in real life? What do you take and worry about?
In addition, is it really important that another race condition may occur that the domain model has made, but before it is fully committed to the database?
And for the third observation (i.e., a change in state due to a time factor). How do you do this?
source share