DDD功能方式:为什么在将DDD与功能语言一起使用时,为什么将状态与行为脱钩更好?

Tei*_*raz 5 domain-driven-design functional-programming scala aggregateroot

我已经阅读了几篇文章(也是这本书的书Functional domain modeling),他们提议将域对象的状态与行为分离,但是我无法理解这种方法在到达域模型上的优势。

这是一个到达域模型的示例:

case class Account(id: AccountId, balance: Money) {
  def activate: Account = {
   // check if it is already active, eg, enforce invariant 
   ...
  }
  def freeze: Account = ???
} 
Run Code Online (Sandbox Code Playgroud)

我可以通过以下方式对此帐户进行连锁操作:

account.activate.freeze
Run Code Online (Sandbox Code Playgroud)

这是他们建议的“贫血”方法的示例:

case class Account(id: AccountId, balance: Money)

object AccountService {
  def activate =  (account: Account) => {
   // check if it is already active, eg, enforce invariant 
    ...
  }

  def freeze =  (account: Account) =>   {
    ...     
  }
}

Run Code Online (Sandbox Code Playgroud)

在这里我可以像这样链接操作

activate andThen freeze apply account
Run Code Online (Sandbox Code Playgroud)

除了“优雅”的语法,第二种方法的优点是什么?

另外,在到达域模型的情况下,我将在单个类中强制执行不变式,但在“贫血”模型的情况下,逻辑/不变式可以跨服务分布

Mar*_*lic 2

一个优点可能是能够向链添加另一个链接,而无需修改和重新编译域模型。例如,假设我们想添加另一个验证步骤来检查欺诈行为

object AccountService {
  def fraud = (account: Account) => ...
}
Run Code Online (Sandbox Code Playgroud)

那么我们可以像这样组成这一步

(fraud andThen activate andThen freeze)(account)
Run Code Online (Sandbox Code Playgroud)

从概念上讲,添加fraud验证步骤并没有改变域模型的结构case class Account,那么为什么还要重新编译它呢?这是一种关注点分离的形式,我们希望将代码库的更改范围缩小到最小的相关部分。