拥有ID或不拥有ID - 关于价值对象

时间:2017-06-21 01:30:24

标签: domain-driven-design

假设有两个域对象:Product和ProductVariety(包含颜色,大小等数据)。这两者之间的关系是一对多的。从概念上讲,在域驱动设计中,ProductVariaty应该是一个值对象,一旦数据被更改,它就不是同一个对象。但是,从实现的角度来看,最好为ProductVariaty添加一些排序标识,以便我们知道选择了哪个ProductVariety等等。是将其转换为实体类的唯一解决方案吗?

以下是说明这种情况的代码段。

@Embeddable
class ProductVariety {...}

@Entity
class Product {

  @ElementCollection
  private Set<ProductVariety> varities;

  ...
}

1 个答案:

答案 0 :(得分:1)

  

从概念上讲,在域驱动设计中,ProductVariaty应该是一个值对象,一旦数据被更改,它就不是同一个对象

这不是相当正确的拼写。在几乎所有情况下(许多9),Value Object应该是不可变的;它的数据永远不会改变。

  

是将其转换为实体类的唯一解决方案吗?

“这取决于”。

将标识符作为对象的不可变状态的一部分,概念上没有任何错误。例如,PANTONE 5395 CIdentifier(值类型),对于特定的Color(值类型)是唯一的。

但是,对于像PANTONE 5395 C这样的标识符有值,它需要在语义上稳定。将标识符的映射更改为实际的色谱元素会破坏先前关于颜色的消息的含义。如果标识符是“错误的”,那么正确的做法是弃用标识符并指定替换标识符。

简单地说,你不能通过从旧油漆罐上取下标签并将其放在新的油漆罐上来重新粉刷房屋。

在这种情况下,使用标识符与整个值对象没有太大的好处。但这样做也没错。

另一方面,如果你真的在建模一个映射,并且你想跟踪随时间发生的变化 - 那就是那个实体的定义。

它真正取决于“业务成本”。在您试图解决的问题的背景下,涉及的权衡是什么?

注意:如果您确实发现自己正在考虑这样的情况,请确保记录您的成本效益分析,以便下一个开发人员有一串面包屑从中工作。