(1)领域驱动设计里程碑之作,资深技术专家兼技术管理者二十年工作经验结晶
(2)深度解读DDD思想,揭示使用 DSL实现DDD快速落地的方法与技巧,缓解复杂软件开发之痛
本书是拥有二十年商业软件开发经验及十年技术管理经验的资深技术专家呕心沥血之作,也是目前市场上少有的阐述如何通过使用领域专用语言(DSL)实现领域驱动设计(DDD)的图书。
书中首先带领读者重温DDD在战术设计层面及战略设计层面上的部分重要概念,并简要介绍了自DDD社区兴起的一些软件架构模式。然后阐述如何设计一门DDD原生的DSL,包括这个DSL的规范支持哪些特性、如何帮助团队描述领域模型的方方面面、这些特性的选择基于何种考量等。
然后在此基础上详细讲解了如何使用技术工具将描述领域模型的DSL文档直接转化为可以工作的软件代码,在这个过程中结合诸多来自商业软件开发工作中的真实案例,展示并分析了大量的关键代码,让读者可以深入地了解制造那些基于DSL的DDD技术工具的秘密。
之后讲述了一些建模案例,并探讨了一些与DDD相关的其他话题,对读者开拓技术思维、更深刻地理解DDD有所助益。
【第一部分 概念】
第1章 DDD 的关键概念 2
1.1 自顶而下、逐步求精 3
1.1.1 DDD开创全新分析流派 3
1.1.2 什么是软件的核心复杂性 4
1.2 什么是领域模型 4
1.3 战术层面的关键概念 6
1.3.1 实体 6
1.3.2 值对象 6
1.3.3 聚合与聚合根、聚合内部实体 7
1.3.4 聚合的整体与局部 9
1.3.5 聚合是数据修改的单元 9
1.3.6 聚合分析是“拆分”的基础 10
1.3.7 服务 12
1.4 战略层面的关键概念 13
1.4.1 限界上下文 13
1.4.2 限界上下文与微服务 14
1.4.3 防腐层 15
1.4.4 统一语言 18
1.5 ER 模型、OO模型和关系模型 19
1.6 概念建模与模型范式 21
第2章 其他DDD相关概念 22
2.1 领域 ID 22
2.1.1 自然键与代理键 23
2.1.2 DDD 实体的 ID 需要被最终用户看到 23
2.1.3 什么时候使用代理键 24
2.2 ID、Local ID 与 Global ID 26
2.3 命令、事件与状态 27
第3章 CQRS 与 Event Sourcing 29
3.1 命令查询职责分离 29
3.2 事件溯源 32
3.3 From-Thru 模式 33
3.3.1 示例:ProductPrice 33
3.3.2 示例:PartyRelationship 35
3.4 CQRS、ES 与流处理 36
【第二部分 设计】
第4章 DDD 的 DSL是什么 40
4.1 为什么 DDD 需要 DSL 41
4.1.1 为什么实现 DDD 那么难 41
4.1.2 搞定 DDD 的“锤子”在哪里 42
4.2 需要什么样的 DSL 43
4.2.1 在“信仰”上保持中立 44
4.2.2 DDD 原生 45
4.2.3 在复杂和简单中平衡 46
4.2.4 通过 DSL 重塑软件开发过程 48
4.3 DDDML——DDD 的 DSL 48
4.3.1 DDDML 的词汇表 49
4.3.2 DDDML 的 Schema 51
4.4 DDDML 示例:Car 52
4.4.1 “对象”的名称在哪里 55
4.4.2 使用两种命名风格:camelCase 与 PascalCase 55
4.4.3 为何引入关键字 itemType 56
第5章 限界上下文 57
5.1 DDDML 文档的根结点下有什么 57
5.2 限界上下文的配置 59
5.3 名称空间 62
5.3.1 再谈 PascalCase 命名风格 62
5.3.2 注意两个字母的首字母缩写词 63
5.4 关于模块 64
第6章 值对象 67
6.1 领域基础类型 68
6.1.1 例子:从 OFBiz 借鉴过来的类型系统 70
6.1.2 例子:任务的触发器 73
6.2 数据值对象 75
6.3 枚举对象 76
第7章 聚合与实体 79
7.1 用同一个结点描述聚合及聚合根 79
7.2 实体之间只有一种基本关系 82
7.3 关于实体的 ID 85
7.4 不变的实体 89
7.5 动态对象 90
7.6 继承与多态 92
7.6.1 使用关键字 inheritedFrom 94
7.6.2 超对象 95
7.7 引用 97
7.7.1 定义实体的引用 97
7.7.2 属性的类型与引用类型 101
7.8 基本属性与派生属性 102
7.8.1 类型为实体集合的派生属性 103
7.8.2 类型为值对象的派生属性 106
7.9 约束 107
7.9.1 在实体层面的约束 107
7.9.2 在属性层面的约束 109
7.10 提供扩展点 110
第8章 超越数据模型 112
8.1 实体的方法 112
8.1.1 聚合根的方法 115
8.1.2 非聚合根实体的方法 116
8.1.3 属性的命令 117
8.1.4 命令 ID 与请求者 ID 119
8.2 记录业务逻辑 119
8.2.1 关于 accountingQuantityTypes 120
8.2.2 关于 derivationLogic 120
8.2.3 关于 filter 121
8.2.4 使用关键字referenceFilter 121
8.2.5 业务逻辑代码中的变量 122
8.2.6 说说区块链 123
8.3 领域服务 123
8.4 在方法定义中使用关键字 inheritedFrom 125
8.5 方法的安全性 126
第9章 模式 128
9.1 账务模式 128
9.2 状态机模式 132
9.3 树结构模式 137
9.3.1 简单的树 137
9.3.2 使用关键字structureType 138
9.3.3 使用关键字structureTypeFilter 139
【第三部分 实践】
第10章 处理限界上下文与值对象 142
10.1 项目文件 143
10.2 处理值对象 144
10.2.1 一个需要处理的数据值对象示例 145
10.2.2 使用 Hibernate 存储数据值对象 146
10.2.3 处理值对象的集合 149
10.2.4 在 URL 中使用数据值对象 151
10.2.5 处理领域基础类型 153
第11章 处理聚合与实体 161
11.1 生成聚合的代码 162
11.1.1 接口 163
11.1.2 代码中的命名问题 178
11.1.3 接口的实现 179
11.1.4 事件存储与持久化 207
11.1.5 使用 Validation 框架 218
11.1.6 保证静态方法与模型同步更新 220
11.1.7 不使用事件溯源 222
11.2 Override 聚合对象的方法 223
11.3 处理继承 225
11.3.1 TPCH 226
11.3.2 TPCC 227
11.3.3 TPS 228
11.4 处理模式 229
11.4.1 处理账务模式 229
11.4.2 处理状态机模式 234
第12章 处理领域服务 238
12.1 处理数据的一致性 239
12.1.1 使用数据库事务实现一致性 240
12.1.2 使用 Saga 实现最终一致性 241
12.2 发布与处理领域事件 243
12.2.1 编写 DDDML 文档 243
12.2.2 生成的事件发布代码 245
12.2.3 编写生产端聚合的业务逻辑 253
12.2.4 实现消费端领域事件的处理 254
12.3 支持基于编制的 Saga 255
12.3.1 编写 DDDML 文档 255
12.3.2 生成的 Saga 命令处理代码 261
12.3.3 需要我们编写的 Saga 代码 268
12.3.4 需要我们实现的实体方法 273
第13章 RESTful API 276
13.1 RESTful API 的最佳实践 276
13.1.1 没有必要绞尽脑汁地寻找名词 277
13.1.2 尽可能使用 HTTP作为封包 277
13.1.3 异常处理 279
13.2 聚合的 RESTful API 280
13.2.1 GET 280
13.2.2 PUT 291
13.2.3 PATCH 293
13.2.4 DELETE 295
13.2.5 POST 295
13.2.6 事件溯源 API 296
13.2.7 树的查询接口 297
13.3 服务的 RESTful API 297
13.4 身份与访问管理 299
13.4.1 获取 OAuth 2.0 Bearer Token 299
13.4.2 在资源服务器上处理授权 301
13.5 生成 Client SDK 302
13.5.1 创建聚合实例 303
13.5.2 更新聚合实例 304
13.5.3 使用 Retrofit2 306
第14章 直达 UI 308
14.1 两条路线的斗争 309
14.1.1 前端“知道”领域模型 309
14.1.2 前端“只知道”RESTful API 312
14.2 生成 Admin UI 312
14.2.1 使用 referenceFilter 313
14.2.2 展示派生的实体集合属性 315
14.2.3 使用属性层面的约束 316
14.2.4 使用 UI 层元数据 317
14.2.5 构建更实时的应用 318
【第四部分 建模漫谈与 DDD 随想】
第15章 找回敏捷的软件设计 322
15.1 重构不是万能灵药 323
15.2 数据建模示例:订单的装运与支付 324
15.2.1 订单与订单行项 325
15.2.2 订单与订单装运组 327
15.2.3 订单与装运单 328
15.2.4 订单的项目发货 329
15.2.5 订单的支付 330
15.3 中台是一个轮回 332
15.4 实例化需求与行为驱动测试 334
15.4.1 什么是实例化需求 334
15.4.2 BDD 工具 335
15.4.3 BDD 工具应与 DDD 相得益彰 336
15.4.4 不要在验收测试中使用固件数据 336
15.4.5 制造“制造数据”的工具 337
15.5 要领域模型驱动,不要 UI 驱动 345
15.6 不要用“我”的视角设计核心模型 346
15.6.1 让 User 消失 347
15.6.2 认识一下 Party 348
15.7 我们想要的敏捷设计 350
第16章 说说 SaaS 351
16.1 何为 SaaS 351
16.2 多租户技术 352
16.3 构建成功的 SaaS 有何难 353
16.3.1 多租户系统的构建成本 353
16.3.2 难以满足的定制化需求 353
16.3.3 负重前行的传统软件公司 355
16.4 SaaS 需要 DDD 355
第17章 更好的“锤子” 356
17.1 我们制作的一个 DDDML GUI 工具 357
17.1.1 给领域建模提供起点 357
17.1.2 创建新的限界上下文 358
17.1.3 从 OFBiz 中“借鉴”数据模型 359
17.1.4 构建项目并运行应用 361
17.1.5 使用 HTTP PUT 方法创建实体 362
17.1.6 给聚合增加方法 363
17.1.7 生成限界上下文的Demo Admin UI 368
17.1.8 让不同层级的开发人员各尽其能 369
17.2 以统一语言建模 370
附录 DDDML 示例与缩写表 373
温馨提示:请使用泸西县图书馆的读者帐号和密码进行登录
开发软件困难的部分其实是建立对软件所服务的领域的认知,即“领域建模”。那么应该构建何种风格的领域模型以及如何描述所构造的模型呢?杨捷锋向我们强烈推荐DDD以及DSL——以“领域驱动设计”的方法构造 DDD 风格的领域模型,并以DSL来描述它们。作者以近20年的编码经验练就的深厚功力,在书中写下DDD实践的思考及建议,十分精彩,令人击节。
—— 郝培强(Tinyfool) 英语轻松读创始人
技术的本质是为了业务创新或者解决业务中的各种问题。领域驱动设计(DDD)是架构设计中的经典思想,经典不会过时。杨捷锋的DSL实践给我们带来了DDD领域的更多经验与思考。
—— 杨卫华(Tim Yang) Westar区块链实验室创始人、中国计算机学会TF架构SIG主席
传统企业的数字化不仅需要推动互联网发展的高并发、大数据等新技术,更需要构建领域模型,以支持复杂的企业业务的持续演进。如何才能实现?良方是DDD。但是,技术人员没有一定的经验,运用DDD时很容易犯错误。本书从道、术、工具等多个层次阐述DDD。需要举例说明时,作者不满足于使用简单的例子,而是拿出工作中碰到的经典案例来讲解,更有结合DDD对软件SaaS化及PaaS化的思考。本书值得借鉴与研读。
—— 刘建 蓝图移动首席架构师、前蓝信技术合伙人
为了避免业务突变而燃尽利润,我们需要构建对领域的深度认知模型。但模型描述标准化、代码生成等难题多年来横亘在DDD前进的道路上。Eric Evans早就说过,DSL会是DDD的下一大步,现在我们终于有了DDDML!基于DDDML的解决方案已经在电商行业实践,现在更剑指构建云端FaaS平台的“小目标”——具有业务价值的代码应该用简单的函数来写。诸多细分领域的DSL(如BPMN 2.0)已然大获成功,相信DDDML亦当如此。
—— 胡天成 原PFU(富士通集团)技术顾问
领域驱动设计是个美妙的愿景。长期以来,虽有不少技术管理者对各种先进的概念和方法论充满激情,但像作者这样多年在工作中坚持实践领域驱动设计的,并不多见。作者早年主要为海尔、宝洁、沈飞、朗讯等传统企业提供技术服务,近几年又投身于互联网行业,经验丰富。本书不囿于管理者的视角,更从工程师的角度直指领域驱动设计落地的关键,书中充满操作性极强的建议,直至代码级的剖析讲解,值得拥有。
—— 杨彬 海贝易通董事长、前朗讯研发总监