组合领域模型
构建更大的模型
组合领域模型 是 CoddyKit 上的免费 Scala for Backend Engineering & Functional Programming 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Scala for Backend Engineering & Functional Programming 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Scala for Backend Engineering & Functional Programming 课程共包含 4 节课。
构建更大的模型
真实领域模型由更小的部分组合而成。组合领域模型是指将建模良好的 ADT、新类型和经过验证的值组合成更大且仍然正确的结构。
- 小而专注的类型可以组合成更大的类型。
- 每个部分都维护自己的不变量。
case class Money(cents: Long)
case class Product(name: String, price: Money)
object Main:
def main(args: Array[String]): Unit =
println(Product("Book", Money(1999)))嵌套积类型
通过嵌套 case class 来组合积类型。每一层都会增加结构,同时保持可读性。
case class Address(city: String, zip: String)
case class Customer(name: String, address: Address)
object Main:
def main(args: Array[String]): Unit =
val c = Customer("Ada", Address("London", "E1"))
println(c.address.city)使用集合进行组合
使用 List、Map 和 Set 来建模领域内部的一对多关系。
case class Item(name: String, qty: Int)
case class Order(id: Int, items: List[Item])
object Main:
def main(args: Array[String]): Unit =
val order = Order(1, List(Item("pen", 2), Item("ink", 1)))
println(order.items.map(_.qty).sum)组合和类型
更大的选择由更小的选择组合而成。枚举变体本身可以包含另一个 ADT,从而将多个决策分层组织。
enum Payment:
case Card(last4: String)
case Cash
enum Checkout:
case Completed(payment: Payment)
case Abandoned
object Main:
def main(args: Array[String]): Unit =
val c: Checkout = Checkout.Completed(Payment.Card("1234"))
println(c)组合领域模型的函数
领域操作是从输入类型映射到输出类型的纯函数。组合这些函数可以构建工作流。
case class Cart(total: Long)
case class Receipt(total: Long, tax: Long)
object Main:
def checkout(c: Cart): Receipt =
Receipt(c.total, (c.total * 0.2).toLong)
def main(args: Array[String]): Unit =
println(checkout(Cart(1000)))组合验证
当每个字段都由智能构造器创建时,可以使用 for 推导将它们组合起来。只有所有部分都通过验证,整个对象才会被创建。
object V:
def name(s: String): Option[String] = if s.nonEmpty then Some(s) else None
def age(n: Int): Option[Int] = if n >= 0 then Some(n) else None
case class Person(name: String, age: Int)
object Main:
def make(n: String, a: Int): Option[Person] =
for nm <- V.name(n); ag <- V.age(a) yield Person(nm, ag)
def main(args: Array[String]): Unit =
println(Main.make("Bob", 30))
println(Main.make("", 30))折叠组合数据
使用 fold,或结合 map 与 sum,来聚合组合结构。数据的形状会引导计算过程。
case class Line(price: Long, qty: Int)
case class Invoice(lines: List[Line])
object Main:
def total(inv: Invoice): Long =
inv.lines.foldLeft(0L)((acc, l) => acc + l.price * l.qty)
def main(args: Array[String]): Unit =
val inv = Invoice(List(Line(100, 2), Line(50, 4)))
println(total(inv))更新不可变模型
使用 copy 来组合变更;它会返回一个新值,并替换指定的字段。原始值保持不变。
case class Account(id: Int, balance: Long)
object Main:
def deposit(a: Account, amt: Long): Account =
a.copy(balance = a.balance + amt)
def main(args: Array[String]): Unit =
val a = Account(1, 100)
println(deposit(a, 50))建模状态机
组合和类型与状态转换函数,可以建模出只允许合法转换存在的状态机。
enum Light:
case Red, Green, Yellow
object Main:
def next(l: Light): Light = l match
case Light.Red => Light.Green
case Light.Green => Light.Yellow
case Light.Yellow => Light.Red
def main(args: Array[String]): Unit =
println(next(Light.Red))
println(next(Light.Green))分层组织领域与操作
保持数据类型纯粹,并将行为放入函数或方法中。组合后的模型加上一组变换,就构成了一个小型领域库。
case class Temp(celsius: Double):
def toF: Double = celsius * 9 / 5 + 32
object Main:
def main(args: Array[String]): Unit =
val t = Temp(25.0)
println(t.toF)综合运用
完整的模型会组合新类型、积类型、和类型、集合以及经过验证的构造过程。这样的结果难以被误用,也易于推理。
- 先构建小型类型。
- 将它们组合成聚合结构。
- 将操作表达为纯函数。
case class Sku(value: String)
case class Line(sku: Sku, qty: Int)
case class Basket(lines: List[Line]):
def count: Int = lines.map(_.qty).sum
object Main:
def main(args: Array[String]): Unit =
val b = Basket(List(Line(Sku("A"), 2), Line(Sku("B"), 3)))
println(b.count)快速检查
测试您对组合领域模型的理解。
回顾
您已经学会了如何组合领域模型。
- 嵌套积类型和和类型,以建模丰富的结构。
- 使用集合表示一对多关系。
- 使用
for推导组合验证过程。 - 使用
copy以不可变方式更新数据。 - 保持数据纯粹,并将操作表达为函数。
case class User(id: Int, name: String)
case class Post(author: User, text: String)
object Main:
def main(args: Array[String]): Unit =
val p = Post(User(1, "Ada"), "hello")
println(p.copy(text = "hi"))用 AI 导师学习 Scala — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 39
- 课程
- 143
常见问题解答
「组合领域模型」课时是免费的吗?
是的 — 「组合领域模型」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Scala for Backend Engineering & Functional Programming 课程的其余内容,请升级到 CoddyKit PRO。 Scala for Backend Engineering & Functional Programming 课程共包含 4 节课。
「组合领域模型」这节课中我会学到什么?
构建更大的模型 你通过在浏览器中直接运行的动手代码来练习 Scala for Backend Engineering & Functional Programming,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Scala for Backend Engineering & Functional Programming 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Scala for Backend Engineering & Functional Programming 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「组合领域模型」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Scala for Backend Engineering & Functional Programming 课中编写并运行代码吗?
能。每节 Scala for Backend Engineering & Functional Programming 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 使用代数数据类型建模
- 智能构造器
- 新类型
- 组合领域模型