gpt4 book ai didi

scala - DDD功能方式: Why is it better to decouple state from the behavior when applying DDD with functional language?

转载 作者:行者123 更新时间:2023-12-02 05:17:27 25 4
gpt4 key购买 nike

我读过几篇文章(还有功能域建模一书),其中建议将域对象的状态与行为分离,但我无法理解这种方法相对于范围域模型的优势.

以下是覆盖域模型的示例:

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

我可以通过以下方式使用此帐户进行链式操作:

account.activate.freeze

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

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) => {
...
}
}

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

activate andThen freeze apply account

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

此外,在到达域模型的情况下,我将在单个类中强制执行不变量,但在“贫乏”模型的情况下,逻辑/不变量可以跨服务传播

最佳答案

我提供两个思维过程,可以帮助解释这个难题:

<小时/>

您的示例和书中的状态概念有所不同。(我确实希望我们都指的是 Functional and Reactive Domain Modeling )。

您的示例状态激活卡住可能是领域概念,而本书讨论的状态仅用作标记。它们不一定在域逻辑中发挥作用,其存在只是为了消除工作流状态的歧义。前任。 已申请已批准已丰富

<小时/>

函数式编程就是实现行为,这些行为独立于传递给它们的数据。

实现此类行为时有两个方面需要注意。

行为可以跨上下文重用。它可以是一个抽象特征,如果你愿意的话,可以是一个幺半群,它采用任何类型T,并在它。在您的示例中,卡住可能是这样的行为,适用于帐户贷款余额等。

该行为没有任何副作用。人们应该能够使用相同的数据集一次又一次地调用该行为,并收到相同的预期响应,而不会影响系统或引发错误。引用您的示例,对帐户重复调用卡住不应引发错误。

结合这两点,可以说将行为实现为跨不同上下文的可重用代码段(作为 Service),同时确保输入经过验证(即验证处理前作为输入提供的对象的状态)。

通过将对象的可接受状态表示为单独的类型并使用此显式类型参数化模型/对象,我们可以在编译时强制执行输入的静态检查。引用书中提供的例子,你只能批准然后丰富。任何其他不正确的序列都会引发编译时错误,这比使用防御性防护在运行时检查输入要好得多。

因此,第二种方法最终不仅仅是优雅的语法。它是一种基于对象状态构建编译时检查的机制。

<小时/>

因此,虽然输出看起来缺乏模型,但第二种方法是利用函数式编程带来的一些漂亮的模式。

关于scala - DDD功能方式: Why is it better to decouple state from the behavior when applying DDD with functional language?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56836243/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com