描述
开 本: 16开纸 张: 胶版纸包 装: 平装-胶订是否套装: 否国际标准书号ISBN: 9787121323928
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 总结 ………………………….
开发人员正淹没在各种错综复杂的问题中,需要借助多核处理器以及分布式基
础架构的优势,来应对产生数据越来越多的高要求用户规模的迅猛增长,以确保更
低的延迟以及更高的吞吐率。所以开发人员不得不在消费者日益苛刻的紧张截止时
间前按时交付。
开发人员的工作从来没有轻松过。为了能保持多产的同时又能享受工作,需要
采用合适的工具集——这些工具可以通过优化资源的使用来管理日益增长的复杂性
以及需求。通常,并不是简单地追逐、炫的东西——尽管这很诱人。所以必
须要回顾总结,从过去艰难获胜的经验中学习,看是否可以将其应用到今天的场景
以及挑战中。我认为开发人员开发的那些非常有用的工具中所包含的领域驱动设计
(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 刚完成的Functional
Programming in Scala(中文版为《Scalo 函数式编程》,由电子出版社出版)。
我们的域模型非常复杂,实现严格遵守Eric Evans 在他的著作Domain-Driven
Design: 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、Daniel Garcia、Jan Nonnen、
Jason Goodwin、Jaume Valls、Jean-Fran?ois Morin、John G. Schwitz、Ken Fricklas、
Lukasz Kupka、Michael Hamrah、Othman Doghri、Rintcius Blok、Robert Miller、
Saleem Shafi、Tarek Nabil,以及William E. Wheeler。时间可能是我们拥有的宝贵
的资源,我非常感谢他们愿意在这本书上花费时间,每个评审者都给了我很棒的建
议,极大地提升了这本书的质量。
感谢所有购买了MEAP1 的读者,在作者在线论坛里的定期沟通,一直鼓励着我
完成这本书。特别要感谢Arya Irani,她贡献的一个pull 请求帮助我更新了monad
代码(从基于Scalaz 7.1 到7.2)。同样要特别感谢Thomas Lockney 和Charles Feduke,
他们对每个不同的MEAP 版本做了彻底的技术评审。
我还要感谢Manning 出版社再次信任我。在我写本书的时候,我们有过非
常美好的合作,而再次合作甚至更有乐趣。我要感谢以下Manning 员工的杰出工作。
感谢Michael Stephens和Christina Rudloff促使我启动这个项目。
感谢Jennifer Stout 在10 个章节的漫长过程中不屈不挠地纠正了我所有的错误。
感谢Alain Gouniot在整个过程中提供了深入的技术评审。
感谢Gandace Gilhooley与Ana Romac帮助推动这本书。
感谢Mary Piergies、Kevin Sullivan、Maureen Spencer,以及所有幕后工作人员(包括Sharon Wilkey、Alyson Brener、April Milne,以及Dennis Dalinnik),他们帮助我把一个粗糙的草稿变成一本真正的书。
感谢Jonas Bonér 为我的书写序。我很荣幸,我与Jonas 已经相识了很长时间,他也是我很多软件开发项目的重要灵感来源。
后,我要感谢我的妻子、母亲以及我的儿子Aarush,他们给我提供了完美的“生态环境”,在那里,写一本关于函数式编程的书这种创造性任务才有可能完成。
关于本书
本书内容涉及如何使用函数式编程实现领域模型,以及如何通过使用响应式原则(诸如非阻塞计算和异步消息)来确保模型的响应性。领域模型都是针对问题领域的,可以通过很多方式实现一个解决方案框架——
能提供与问题领域模型相同的函数性,通常会使用面向对象技术来设计领域模型。
本书中使用了一种正交方式——用纯函数对领域行为建模,用代数数据类型对领域
实体建模,并将不变性作为设计空间的一个主关注点。作为读者,你能学到基于代
数技术的函数式设计模式,可以将其直接用于实现自己的领域模型。
这本书同样还包括了响应式编程——使用future、promi
评论
还没有评论。