gpt4 book ai didi

scala - 函数式编程 + 领域驱动设计

转载 作者:行者123 更新时间:2023-12-03 14:45:43 24 4
gpt4 key购买 nike

函数式编程促进了不可变类和引用透明性。

领域驱动设计由值对象(不可变)和实体(可变)组成。

我们应该创建不可变的实体而不是可变的实体吗?

让我们假设,项目使用 Scala 作为主要语言,我们如何将实体编写为 案例类 (不可变)如果我们正在处理并发,不会冒着陈旧状态的风险?

什么是好的做法?保持实体可变( var 字段等...)并避免使用 的语法案例类 ?

最佳答案

您可以在 Scala 中有效地使用不可变实体,并避免可变字段的恐怖以及源自可变状态的所有错误。使用不可变实体可以帮助您实现并发性,不会让事情变得更糟。您之前的可变状态将成为一组转换,它将在每次更改时创建一个新的引用。

但是,在您的应用程序的某个级别,您将需要具有可变状态,否则您的应用程序将毫无用处。这个想法是在你的程序逻辑中尽可能地插入它。让我们举一个银行账户的例子,它可能会因利率和 ATM 取款或
订金。

您有两种有效的方法:

  • 您公开可以修改内部属性的方法并管理这些方法的并发性(实际上很少)
  • 您使所有类不可变,并用可以更改帐户的“管理器”将其包围。

  • 由于第一个非常简单,我将详细介绍第一个。
    case class BankAccount(val balance:Double, val code:Int)

    class BankAccountRef(private var bankAccount:BankAccount){
    def withdraw(withdrawal) = {
    bankAccount = bankAccount.copy(balance = bankAccount.balance - withdrawal)
    bankAccount.balance
    }
    }

    这很好,但是天哪,您仍然坚持管理并发。好吧,Scala 为您提供了一个解决方案。这里的问题是,如果您将您对 BankAccountRef 的引用共享到您的后台作业,那么您将必须同步调用。问题在于您以次优的方式进行并发。

    并发的最佳方式:消息传递

    如果另一方面,不同的作业不能直接调用 BankAccount 或 BankAccountRef 上的方法,而只是通知它们需要执行一些操作怎么办?那么,你就有了一个 Actor,它是 Scala 中最喜欢的并发方式。
    class BankAccountActor(private var bankAccount:BankAccount) extends Actor {

    def receive {
    case BalanceRequest => sender ! Balance(bankAccount.balance)
    case Withdraw(amount) => {
    this.bankAccount = bankAccount.copy(balance = bankAccount.balance - amount)
    }
    case Deposit(amount) => {
    this.bankAccount = bankAccount.copy(balance = bankAccount.balance + amount)

    }

    }
    }

    该解决方案在 Akka 文档中有广泛的描述: http://doc.akka.io/docs/akka/2.1.0/scala/actors.html .这个想法是你通过向 Actor 的邮箱发送消息来与 Actor 进行通信,并且这些消息按照接收的顺序进行处理。因此,如果使用此模型,您将永远不会有并发缺陷。

    关于scala - 函数式编程 + 领域驱动设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14813416/

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