假设您有2类,分别是Person和Rabbit。一个人可以对兔子做很多事情,他/她可以喂兔子,买下来并成为它的主人,或者把它扔掉。一只兔子一次只能有一个拥有者,也不能有一个。如果一段时间不喂食,它可能会死亡。

Class Person
{
    Void Feed(Rabbit r);
    Void Buy(Rabbit r);
    Void Giveaway(Person p, Rabbit r);

    Rabbit[] rabbits;
}

Class Rabbit
{
   Bool IsAlive();
   Person pwner;
}

领域模型有以下几点观察:
  • Person和Rabbit可以相互引用
  • 对一个对象的任何操作也可以更改另一个对象的状态
  • 即使未调用任何显式操作,对象中的状态仍然会发生变化(例如,Rabbit可能饿死,并导致其从Person.rabbits数组中删除)

  • 就DDD而言,我认为正确的方法是同步所有可能更改域模型中状态的调用。例如,如果某人购买了Rabbit,则他/他将需要获得一个Person锁才能更改Rabbits数组,还需要获得Rabbit的另一把锁才能更改其所有者,然后再释放第一个。这样可以防止2个人声称是小兔子的所有者的比赛状况。

    另一种方法是让数据库处理所有这些同步。谁打第一个电话赢了,但是DB需要有某种业务逻辑来确定它是否是有效的交易(例如,如果Rabbit已经有一个所有者,除非该人将其放弃,否则它不能更改其所有者) 。

    两种方法都有优点/缺点,我希望“最佳”解决方案介于两者之间。在现实生活中您将如何做?您的经历和经验是什么?

    另外,是否确实存在域模型已经提交了更改但在数据库中完全提交更改之前存在其他竞争条件的担忧?

    对于第三次观察(即由于时间因素导致的状态变化)。你会怎么做?

    最佳答案

    这里有几个问题需要考虑,可以帮助您进行设计:

  • 实际上,兔子需要知道谁是谁吗?意思是,它需要参考吗?如果您要为域建模,那么兔子不太可能知道谁是所有者(如果由两个人共享,该怎么办)?
  • 一个人应该直接引用兔子吗?还是您认为拥有更通用的界面(例如动物)更有意义?这些操作似乎不是针对兔子的吗?
  • 关于线程和同步,您的应用程序是多线程的吗?您的应用中是否可能有两个人尝试同时成为兔子的所有者?例如,如果您正在为一家宠物店建模,那么这实际上是不可能发生的(同样,如果Rabbit没有对其所有者的引用,这种担忧可能就不复存在了)。
  • 如果两个对象确实确实需要相互引用,那么我可能会在对象级别(使用锁)进行同步。由于您可能会更新内存中的域模型,然后将其持久保存到数据库中(可能是在应用程序关闭时关闭,或者在桌面应用程序中关闭),因此您始终希望内存处于一致状态。
  • 通常,从最简单的解决方案开始并根据需要进行重构。考虑到您的问题以及开发的位置,我发现在对象级别或数据库上进行同步的差异不太可能是性能问题。
  • 关于database - 一般ORM设计问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2770493/

    10-11 10:22