在许多关于DDD的java教程中,实体是可变对象。
class Product {
private String status;
public void prepare() {
this.status = "Prepearing";
}
}
在上面的例子中,prepare方法改变了对象的内部状态。
但是在scala中,我希望我的实体是不可变的:
case class Product(status: String) {
def prepare: Product = {
this.copy(status = "Prepearing");
}
}
所以我没有改变对象,而是返回一个新的实体。
在DDD方面有不可变实体和以上实现是可以的吗?
或者你能推荐一个更好的方法吗?实体应该不可变吗?
是的,也许应该。如果我持有一个对象的引用,而你改变了它,我应该能看到这些改变。这就是我们使用实体而不是值的原因。
评论Vladimir Khorikov关于实体vs价值观的帖子;吉米伯加德;Martin Fowler…
或者你能推荐一个更好的方法吗?为实体的状态创建一个单独的概念。让该状态为值对象。
class Product {
private State state;
public void prepare() {
this.state = this.state.updateStatus("Preparing");
}
}
Stuart Halloways关于Clojure时间模型的演讲有助于解释这里发生的事情;他的幻灯片31包含了一个很好的将身份可视化为一系列状态。
或者,您可以完全放弃OO方法,并将更改表示为纯函数
newState = theModel.prepare(oldState);
在DDD中,实体自然表现出不同的生命周期阶段或状态。在上面的例子中,产品状态可以是"准备"、"完成"、"发货"、"交付"等。由于这个生命周期,有时会有使用状态模式建模实体的倾向。一些DDD从业者强烈反对自由地使用实体的状态模式。原因是,它会导致实体方法的副作用。副作用会使代码更难测试,而且它们通常是bug的来源。上面的Product类必须能够显式地指定它需要操作的状态。它不能发布尚未准备和完成的东西