Domain driven design 如何使用DDD对该场景进行建模?

Domain driven design 如何使用DDD对该场景进行建模?,domain-driven-design,Domain Driven Design,我在使用DDD建模此场景时遇到一些问题。 我在同一个BC中有两个实体:油和机器。有几种不同的油,其最终成本基于某些特性(密度、材料、采购价格等),并定期更新。所以它们不在同一个集合中。因为它们是不同的实体,所以机器只包含一个带有id的机油引用: class Oil id purchase_price density material ... class Machine id idOil cost addOil (Oil) ... 机器也有成本,这是基于

我在使用DDD建模此场景时遇到一些问题。
我在同一个BC中有两个实体:机器。有几种不同的油,其最终成本基于某些特性(密度、材料、采购价格等),并定期更新。所以它们不在同一个集合中。因为它们是不同的实体,所以机器只包含一个带有id的机油引用:

class Oil
  id
  purchase_price
  density
  material
  ...

class Machine
  id
  idOil
  cost
  addOil (Oil)
  ...
机器也有成本,这是基于机油的成本和一些其他机器属性。 油是可选的,因此当调用addOil方法时,机器保存其id并用油的成本计算机器成本。
机器中没有计算成本的方法机器有责任在其某些属性发生变化时更新其成本
当我需要重新计算没有油类的机器成本时,就会出现问题(我只有它的id)。哪种方法是最好的建模方法?我想了一些,但没有一个能说服我:

1) 在机器构造中注入机油等级。我认为这是不可能的,因为石油是一个实体,DDD不允许这样做。
2) 在机器构造器中注入油库。作为1,DDD不允许它。
3) 在机器构造函数中注入油值对象。这意味着在调用addOil方法时,我必须使用Oil实体的副本保存OilVO类,而不是仅保存其id。
4) 构建一个聚合。我不喜欢,因为油有它自己的id,还有一些其他类,如油,参与了机器成本。机器会变得太大。
5) 将机油成本计算器委托给域服务。这意味着每次创建机器对象时,我都必须在机器构造函数中注入此服务接口:

interface OilCostCalculatorService (OilRepository repo) {
  ...
  public double calculateCost (IdOil id) { 
     Oil oil = repo.getOil(id);
     double cost = .... // calculate cost from oil properties
     return cost;
  }
}

class Machine {
  public Machine (OilCostCalculatorService service, ...) { ... }
}
6) 也许我的类没有正确建模,但经过深思熟虑后,我发现这并不是最好的方法

当我需要重新计算没有机油等级的机器成本(我只有它的id)时,问题就出现了。哪种方法是最好的建模方法

由于机器和石油相互隔离(单独的集合),机器计算无法使用“当前”石油价格——如果没有相互锁定,当前石油价格可能会随着机器的变化而变化

因此,机器正在处理油价的缓存副本

因此,一个答案是在机器聚合中包含最近一次已知油价的缓存副本,并使用该副本来估算成本

另一种可能是将域服务传递给机器,其中域服务是一个接受机器id并返回成本缓存副本的函数。这看起来有点像您的选项#5,除了不将服务注入构造函数,而是在需要的地方将其作为参数传递


在这两种情况下,您可能需要调查您的领域是否需要明确的时间模型(周一的油价)。在许多领域中,都有报价的概念,在某个时间,可能在有限的期限内报价,在此期间,价格是固定的(报价的提供者基本上接受了任何实际价格变化可能无法盈利的风险)。

好吧,我只需要在计算机器成本时知道石油成本。当它的某些属性发生变化时,就会发生这种情况。如果不改变财产,费用不变。关于你的主张,机器有几个属性,所以我不喜欢在所有这些方法中传递域服务的想法。@user1151816“如果没有属性更改,成本保持不变”。所以,只要你不加更多的油,例如,那么机器的价格是静态的,即使油价上涨?您应该使用
机器
中的值对象来描述所需的所有机油特性。