Scala中的DDD:实体应该是不可变的吗?

时间:2016-11-10 23:36:05

标签: scala domain-driven-design immutability

在许多关于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方面是否可以使用不可变实体和上面的实现?

或者你能推荐一种更好的方法吗?

2 个答案:

答案 0 :(得分:1)

在DDD中,实体自然地表现出不同的生命周期阶段或状态。在上面的示例中,产品状态可以是“准备”,“实现”,“运输”,“交付时”等。由于此生命周期,有时会使用状态模式对实体进行建模。一些DDD从业者强烈反对对实体自由使用国家模式。原因是,它可能导致实体方法的副作用。副作用可能使代码更难测试,它们通常可能是错误的来源。上面的Product类必须能够明确指定它需要操作的状态。它无法运送尚未准备和实现的东西。

答案 1 :(得分:1)

  

实体应该是不可变的吗?

是的,可能应该。如果我持有对象的引用,并且你更改它,我应该看到这些更改。这几乎是我们使用实体而不是价值的原因。

回顾弗拉基米尔·霍里科夫关于entities vs values的帖子; Jimmy Bogard; Martin Fowler ....

  

或者你能推荐一种更好的方法吗?

为实体的创建单独的概念。让该状态成为价值对象。

class Product {  

    private State state;

    public void prepare() {
        this.state = this.state.updateStatus("Preparing"); 
    } 
}

Stuart Halloways关于Clojure time model的谈话有助于解释这里发生的事情;他的deck中的幻灯片31包含了身份连续状态的良好可视化。

或者,您可以完全放弃OO方法,并将更改表示为纯函数

newState = theModel.prepare(oldState);