假设您有2个类,Person和Rabbit.一个人可以为兔子做很多事情,他/她可以喂它,买它并成为它的主人,或者放弃它.一只兔子一次可以没有或最多只有1个主人.如果它没有喂一段时间,它可能会死亡.
Class Person
{
Void Feed(Rabbit r);
Void Buy(Rabbit r);
Void Giveaway(Person p, Rabbit r);
Rabbit[] rabbits;
}
Class Rabbit
{
Bool IsAlive();
Person pwner;
}
域模型有一些观察结果:
>人和兔子可以互相引用
>对1个对象的任何操作也可以更改其他对象的状态
>即使没有调用任何显式动作,对象中的状态仍然会发生变化(例如,Rabbit可能会被饿死,导致它从Person.rabbits数组中删除)
就DDD而言,我认为正确的方法是同步所有可能改变域模型中状态的调用.例如,如果一个人购买了一只兔子,他/她将需要在Person中获取一个锁以对兔子阵列进行更改,并且还需要在Rabbit中另一个锁定以在释放第一个之前更改其所有者.这可以防止2人声称是小兔子的拥有者的竞争条件.
另一种方法是让数据库处理所有这些同步.谁使第一次调用获胜,但是数据库需要具有某种业务逻辑以确定它是否是有效的事务(例如,如果Rabbit已经拥有所有者,除非Person将其删除,否则它不能更改其所有者) .
两种方法都有优点/缺点,我希望“最佳”解决方案介于两者之间.你会如何在现实生活中做到这一点?你有什么需要和经验?
此外,域模型是否已提交其更改但在数据库中完全提交之前,是否存在另一种竞争条件?
并且对于第三次观察(即由于时间因素引起的状态变化).你会怎么做?
最佳答案 这里有几个需要考虑的问题,可以帮助您进行设计:
>实际上,兔子需要知道它的主人是谁吗?意思是,它需要参考吗?如果您正在尝试对域进行建模,那么兔子可能不太可能知道它的所有者是谁(以及如果它由两个人共享的话)?
>一个人应该直接提到兔子吗?或者你认为拥有一个更通用的界面更有意义,比如动物?这些操作似乎不是兔子特有的吗?
>关于线程和同步,您的应用程序是多线程的吗?您的应用中是否有可能让两个人同时成为兔子的主人?例如,如果您正在为宠物商店建模,那么这种情况实际上是不可能发生的(如果兔子没有对其所有者的引用,则此问题可能不再存在).
>如果两个对象确实需要相互引用,我可能会在对象级别(带锁)进行同步.由于您可以在内存中更新域模型,然后将其保存到数据库(可能在应用程序关闭或其他东西,如果它是桌面应用程序),您总是希望内存处于一致状态.
>通常,根据需要从最简单的解决方案和重构开始.鉴于您的问题以及您在开发中的位置,我发现在对象级别或数据库中同步的差异可能不太可能是性能问题.