发表于2024-11-27
传统的分布式应用不会切入微服务、快速数据及传感器网络的响应式世界。为了捕获这些应用的动态联系及依赖,我们需要使用另外一种方式来进行领域建模。由纯函数构成的领域模型是以一种更加自然的方式来反映一个响应式系统内的处理流程,同时它也直接映射到了相应的技术和模式,比如Akka、CQRS 以及事件溯源。本书讲述了响应式系统中建立领域模型所需要的通用且可重用的技巧――首先介绍了函数式编程和响应式架构的相关概念,然后逐步地在领域建模中引入这些新的方法,同时本书提供了大量的案例,当在项目中应用这些概念时,可作为参考。
Debasish Ghosh,软件架构师,是使用Scala和Akka来进行响应式设计的先行者。他同时也是DSLs in Action的作者,该书由Manning出版社于2010年出版。
李源,曾在华为技术有限公司工作8 年,经历过开发、SE、PM和PQA等多个岗位,目前在途牛旅游网担任研发总经理一职,是美国质量协会(ASQ)注册质量工程师(CQE);译者有丰富的开发、架构设计及研发管理经验,先后负责过多个大型项目的方案设计和系统规划,对于C++、Java 以及设计模式等领域都有比较深入的研究;曾翻译《Java 性能调优指南》一书。
1. 函数式领域建模:介绍 1
1.1 什么是领域模型 2
1.2 领域驱动设计介绍 4
1.2.1 边界上下文 4
1.2.2 领域模型元素 5
1.2.3 领域对象的生命周期 8
1.2.4 通用语言 13
1.3 函数化思想 14
1.3.1 哈,纯粹的乐趣 17
1.3.2 纯函数组合 21
1.4 管理副作用 26
1.5 纯模型元素的优点 28
1.6 响应式领域模型 31
1.6.1 响应式模型的3+1 视图 31
1.6.2 揭穿“我的模型不能失败”的神话 32
1.6.3 伸缩性与消息驱动 34
1.7 事件驱动编程 35
1.7.1 事件与命令 37
1.7.2 领域事件 38
1.8 函数式遇上响应式 40
1.9 总结 41
2 Scala 与函数式领域模型 42
2.1 为什么是Scala . 43
2.2 静态类型与富领域模型 45
2.3 领域行为的纯函数 47
2.3.1 回顾抽象的纯粹性 50
2.3.2 引用透明的其他好处 53
2.4 代数数据类型与不变性 53
2.4.1 基础:和类型与乘积类型 53
2.4.2 模型中的ADT 结构数据 56
2.4.3 ADT 与模式匹配 . 56
2.4.4 ADT 鼓励不变性 . 58
2.5 局部用函数,全局用OO 59
2.5.1 Scala 中的模块 60
2.6 用Scala 使模型具备响应性 64
2.6.1 管理作用 65
2.6.2 管理失败 65
2.6.3 管理延迟 67
2.7 总结 69
3 设计函数式领域模型 .70
3.1 API 设计的代数 . 71
3.1.1 为什么是代数方法 72
3.2 为领域服务定义代数 72
3.2.1 赋值抽象 73
3.2.2 组合抽象 74
3.2.3 类型的最终代数 76
3.2.4 代数法则 77
3.2.5 代数解释程序 79
3.3 领域模型生命周期中的模式 80
3.3.1 工厂――对象从何处来 . 82
3.3.2 智能构造器 82
3.3.3 通过更有表现力的类型进一步提升智能 84
3.3.4 用代数数据类型聚合 86
3.3.5 用透镜更新聚合功能 88
3.3.6 仓储与解耦的永恒艺术 94
3.3.7 高效地使用生命周期模式――结论 . 101
3.4 总结 102
4 领域模型的函数式模式 103
4.1 模式――代数、函数、类型的聚合 . 104
4.1.1 领域模型中的挖掘模式 106
4.1.2 用函数式模式使领域模型参数化 107
4.2 强类型函数式编程中计算的基本模式 112
4.2.1 函子――建立模式 . 112
4.2.2 加强版函子模式 114
4.2.3 单子作用――applicative 模式的变体 121
4.3 如何用模式对领域模型进行塑形 130
4.4 用代数、类型和模式演进API . 134
4.4.1 代数――第一稿 . 136
4.4.2 改进代数 137
4.4.3 最终组合――采用类型 . 138
4.5 用模式和类型增强领域的不变性 139
4.5.1 贷款处理模型 139
4.5.2 使非法状态不可表示 141
4.6 总结 142
5 领域模型的模块化 144
5.1 将领域模型模块化 145
5.2 模块化的领域模型――案例学习 . 146
5.2.1 模块的解剖 147
5.2.2 模块的构成 154
5.2.3 模块的物理组织 155
5.2.4 模块鼓励组合 156
5.2.5 领域模型中的模块化――结论 . 157
5.3 类型类模式――模块化的多态行为 . 157
5.4 边界上下文的聚合模块 160
5.4.1 模块与边界上下文 161
5.4.2 边界上下文间的通信 162
5.5 模块化的另一个模式――free monad . 163
5.5.1 账户存储 163
5.5.2 使它免费 165
5.5.3 账户存储――free monad 167
5.5.4 free monad 解释程序 . 169
5.5.5 free monad――重点回顾 172
5.6 总结 173
6 响应式模型 174
6.1 响应式领域模型 175
6.2 使用future 的非阻塞API 设计 177
6.2.1 异步作为堆叠作用 178
6.2.2 基于monad 转换器的实现 . 181
6.2.3 用并行存取降低延迟――一种响应式模式 183
6.2.4 使用scalaz.concurrent.Task 作为响应式构造 187
6.3 明确的异步消息传递 189
6.4 流模式 191
6.4.1 一个案例 191
6.4.2 领域管道图 195
6.4.3 后端压力处理 197
6.5 actor 模型 . 198
6.5.1 领域模型与actor . 199
6.6 总结 203
7 响应式流建模 . 205
7.1 响应式流模型 206
7.2 何时使用流模型 207
7.3 领域用例 208
7.4 基于流的领域交互 208
7.5 实现:前台 210
7.6 实现:后台 211
7.7 流模型的主要结论 214
7.8 使模型具有弹性 215
7.8.1 使用Akka Streams 监管 216
7.8.2 冗余集群 217
7.8.3 数据的持久化 217
7.9 基于流的领域模型与响应式原则 219
7.10 总结 220
8 响应式持久化与事件溯源 221
8.1 领域模型的持久化 222
8.2 关注点分离 224
8.2.1 持久化的读/ 写模型 . 225
8.2.2 命令查询责任分离 226
8.3 事件溯源 . 228
8.3.1 事件溯源领域模型中的命令和事件 229
8.3.2 实现CQRS 和事件溯源 231
8.4 实现事件溯源的领域模型(函数式) 232
8.4.1 作为头等实体的事件 233
8.4.2 命令是事件上的free monad 235
8.4.3 解释程序――隐藏所有有趣的东西 . 237
8.4.4 投影――读取端模型 . 242
8.4.5 事件存储 243
8.4.6 分布式CQRS――一个短信 . 243
8.4.7 实现的总结 244
8.5 其他持久化模型 245
8.5.1 将聚合作为ADT 映射到关系型表 245
8.5.2 操作数据(函数式) 247
8.5.3 到Akka Streams 管道的响应式获取 248
8.6 总结 249
9 测试领域模型 250
9.1 测试领域模型概述 251
9.2 设计可测试的领域模型 252
9.2.1 解耦副作用 253
9.2.2 为领域函数提供自定义解释程序 254
9.2.3 实现参数化与测试 255
9.3 基于xUnit 的测试 . 256
9.4 回顾模型的代数 257
9.5 基于属性的测试 258
9.5.1 建模属性 . . 258
9.5.2 验证领域模型中的属性 259
9.5.3 数据生成器 264
9.5.4 是否比基于xUnit 的测试更好 . 266
9.6 总结 267
10 核心思想与原则 268
10.1 回顾 268
10.2 函数式领域建模的核心原则 269
10.2.1 表达式思想 269
10.2.2 早抽象, 晚赋值 . 270
10.2.3 使用合适的抽象 270
10.2.4 发布要做什么,在组合器中隐藏如何做 270
10.2.5 从实现中解耦代数 271
10.2.6 隔离边界上下文 271
10.2.7 偏向future 而不是actor 271
10.3 展望未来 272
推荐序
开发人员正淹没在各种错综复杂的问题中,需要借助多核处理器以及分布式基础架构的优势,来应对产生数据越来越多的高要求用户规模的迅猛增长,以确保更低的延迟以及更高的吞吐率。所以开发人员不得不在消费者日益苛刻的紧张截止时间前按时交付。
开发人员的工作从来没有轻松过。为了能保持多产的同时又能享受工作,需要采用合适的工具集——这些工具可以通过优化资源的使用来管理日益增长的复杂性以及需求。通常,并不是简单地追逐最新、最炫的东西——尽管这很诱人。所以必须要回顾总结,从过去艰难获胜的经验中学习,看是否可以将其应用到今天的场景以及挑战中。我认为开发人员开发的那些非常有用的工具中所包含的领域驱动设计(domain-driven design,DDD)、函数式编程(FP)以及响应式原则,都可以帮助我们管理复杂事务的某个方面。
y 领域复杂性:领域驱动设计帮助我们挖掘并理解领域的不同特性与语义。通过跟利益相关方用他们的语言进行沟通,DDD 可以更容易地创建可扩展的领域模型来映射真实世界,同时允许持续的变化。
y 解决方案复杂性:函数式编程可以帮助我们保持合理性及可组合性。通过可重用的纯函数并使用稳定(不可变)值,函数式编程提供了一个伟大的工具集,通过不会“撒谎”的代码来得出运行时间、并发性以及抽象过程。
系统复杂性:正如在The Reactive Manifesto(http://www.reactivemanifesto.org)中所定义的,响应式原则能帮助我们管理日益复杂的世界,包括多核处理器、云计算、移动设备以及物联网。在这里,所有新系统本质上都是分布式系统。要运作这个世界是非常困难而且很有挑战的,但同样,也拥有很多有趣的新的机会。这种变化迫使我们的行业去反思过去一些围绕系统架构以及设计方面的最佳实践。
我非常喜欢阅读这本书,它完全体现了我在过去十几年的自身经历。我从OO实习生开始——白天埋头于C++ 和Java,而晚上阅读经典的Gang of Four1。2006 年我开始阅读Eric Evan 关于领域驱动建模的书2,它对我或多或少有所启发。然后我就变成一个DDD 狂热爱好者,在所有可能的地方去应用它。多年后,我又开始使用Erlang3,然后是Scala4,它们都让我再次感受到了函数式编程的魅力并深深地爱上了它。我在大学期间学过函数式编程,但当时并没有真正意识到它的威力。在这段时间里,我开始对Java 在并发性、适应性以及可伸缩性方面的“最佳实践”逐渐失去信仰。在Erlang方式,特别是actor模型(5 我认为这是一个更好的做事方式)的指引下,我开始了Akka 项目,我相信这会有助于将响应式原则带入主流。这本书之所以能吸引我是因为它设立了一个更加宏大的目标,将3 个完全不同的工具(领域驱动设计、函数式编程以及响应式原则)用可实践的方式整合到了一起。它教会你诸如边界上下文、领域事件、函数、monad、applicative、future、actor、流以及CQRS6 等内容是如何使复杂性保持可控的。如果内心不够强大,那么这本书将不适合你,阅读它很费劲。但如果花上数小时,你就会收获一些基础概念。亲爱的读者,幸运的你已经迈出了第一步,接下来所需要做的就是继续读下去。
JONAS BONéR
Lightbend 创始人兼CFO
Akka 创始人
序
在2014 年夏天,Manning 出版社希望出版DSLs in Action(https://www.manning.com/books/dsls-in-action)的升级版本,因为DSL 的所有新特性都围绕编程语言的设计和实现。巧合的是正好在那个时间,我用函数模式对一个复杂的领域模型成功地进行了重构。
跟一群刚毕业进入Scala 函数式编程世界的软件工程师们一起,我将域行为建模为纯粹的函数,将域对象设计为代数数据类型,并开始意识到代数API 设计的价值。团队的每个成员人手一本Paul Chiusano 和Rúnar Bjarnason 刚完成的FunctionalProgramming in Scala(中文版为《Scalo 函数式编程》,由电子出版社出版)。我们的域模型非常复杂,实现严格遵守Eric Evans 在他的著作Domain-DrivenDesign: Tackling Complexity in the Heart of Software(Addison-Wesley,2003 年)中所阐述的领域驱动设计(DDD)的原则。不过我们没有用面向对象的方式,而是决定采用函数式编程。一切的开始都像是一个实验,但在最后证明这是一次非常成功并且令人满意的经历。现在当我回头看时,发现DDD 的内容与软件工程的通用规则非常协调一致。因此也不用担心函数式、领域驱动设计会显得像是领域建模的典型范例。
这本书是我们成功运用函数式编程进行领域模型开发的证据。我决定跟读者分享我们遵守的实践、采用的原则,以及在实现中所使用的Scala 风格。Manning 出版社完全同意这个想法并决定继续该项目。
不管你的领域模型是什么样的,定义实现成功的一个关键标准是应用的响应能力。没有一个用户喜欢盯着屏幕上的等待光标,根据我们的经验来看,这通常是因为架构师非必要地阻塞了主线程的执行。需要花费时间执行的昂贵的操作应该用异步的方式来执行,把主线程空出来给其他用户行为。The Reactive Manifesto(www.reactivemanifesto.org)中定义了建模所需要使用的特性,以便保证应用程序是非阻塞、响应及时的,并避免巨大延迟带来的恶劣影响。这也是我要在书中写的另一个方面。在经过与Manning 团队多次友好的商讨后,我们决定在这本书中将函数与响应式编程结合起来。
于是本书就诞生了。通过这个项目,我收获了巨大的乐趣,也希望读者能有类似的体验。我收到了无数读者、评审者、良好祝愿者们的留言,他们陪着我一起提升了这本书的质量。我也非常感谢来自Manning 出版社经验丰富的编辑以及评审者团队的巨大支持。
致谢
我要感谢很多人,他们直接或间接地参与了这本书的创作。
首先,我要感谢Martin Odersky,Scala 编程语言的创建者,我用Scala 完成了所有函数响应式领域建模的案例。同时也非常感谢你建立了Scalaz,这个有趣的库使我们在用Scala 语言进行纯函数编程时充满乐趣。
Twitter 是一个非常酷的沟通方式,承载了各种各样的讨论。我在上面和一些牛人就函数式编程有过很多非常激烈的讨论。感谢每一位牛人,是你们促使我完成了这本书。
感谢所有的评审者:Barry Alexander、Cosimo Attanasi 函数响应式领域建模 下载 mobi epub pdf txt 电子书 格式
函数响应式领域建模 下载 mobi pdf epub txt 电子书 格式 2024
函数响应式领域建模 下载 mobi epub pdf 电子书“十三五”期间,杭州市楼宇经济构筑的两个主中心,即环西湖主中心板块和钱江新城、钱江世纪城主中心板块,这是杭州市楼宇经济发展的核心板块。
评分非常棒的书,买来好好学习!
评分一不小心误入scala大坑,对ddd了解下~
评分领域建模在函数式编程中的落地,学习中
评分领域建模在函数式编程中的落地,学习中
评分东西挺不错的,值得推荐,很好的学习,赞。不错。
评分东西挺不错的,值得推荐,很好的学习,赞。不错。
评分非常棒的书,买来好好学习!
评分由纯函数构成的领域模型是以一种更加自然的方式来反映一个响应式系统内的处理流程,同时它也直接映射到了相应的技术和模式
函数响应式领域建模 mobi epub pdf txt 电子书 格式下载 2024