领域驱动设计是一种设计方法, 试图解决的问题是软件的难以理解, 难以演化. 采用的方法是围绕业务概念来构建模型.
不过你也可以从两个角度来理解领域驱动设计: 作为设计结果的DDD和作为开发方法的DDD, 即 What and How.
作为结果的领域驱动设计是这样一种设计(What): 它建立了一个模型, 这个模型具有以下一些特征:
它是用Ubiquitous Language描述的, 可以用于未必懂编程的业务专家和开发团队之间的交流, 以及开发团队内部的交流, 以及代码中类和方法的名字.
它包含了业务领域中一些基本的概念, 以及概念之间的关系, 它们如何彼此合作, 完成业务领域的各种日常工作. 这些概念是与软件无关的, 无论你有没有用软件来建模它们, 它们每天都出现在从业人员的头脑中, 交谈中, 公司的账本中. 换句话说, 它反映了这个领域的知识. 任何理解了这个模型的人, 就理解了这个领域是如何运转的.
它很少是一个大而全的模型, 因为同一件事物, 在不同的业务场景中有不同的概念, 术语, 角色. 同一份数据, 在不同的场景中也有不同的含义和解读. 因此, 模型里的概念按照应用场景自然的分组, 它们与另外场景中的概念的关联则通过一种内在的映射来保持.
它是一种说明性的模型, 没有实现细节, 因为它将软件本身的技术复杂性分离出去, 而主要致力于描述业务领域. 这样模型的复杂性就只由业务领域的复杂性来决定. 而通常的结果是这会使它更简单.
这样的模型很容易随着业务的变化而变化, 至少不应该比业务本身的变化更困难, 更剧烈. 保守一点讲, 业务领域的变化比技术领域的变化缓慢的多, 模型反映业务, 因此也稳定的多. 当业务渐变时, 模型只需跟随做简单的调整. 业务其实并不复杂, 无论有没有软件支持, 每个领域每天都实际发生着数以亿计的从财务的角度可以追溯的,从从业人员的角度可以理解的, 从管理者的角度可以掌控的业务. 软件却难以正确表达的原因不在于业务本身多复杂, 而在于我们用的工具, 用的方法. DDD试图分离实现(solution domain)的复杂性, 还原业务(problem domain)的简单性, 并提供了相应的工具和方法支持.
这个模型描绘的前景是激动人心的, 但是如何实现 (How)? 我们需要实现技术的支持和开发过程实践的支持
书里描述了一些通用的构造块(Building Block), 即实现技术的支持:
Entity, Value Object and Aggregate
Repository and Factory
Layered Architecture, Module and Service etc.
Side-effect-free-function
Intention-revealing-interface, Specification and Assertion etc.
...
当然这些构造块并不是全部, 新的模式会不断被开发出来 弥合分析与设计及实现之间的Gap. 这些构造块也不是必需的. 虽然Eric在书里说设计必须考虑实现, 但实现并不非得就是书里提供的构造块, 比如 Entity, Value Object, Repository. 反过来说也可以: 用了Entity, Value Object, Repository等并不一定意味着你就是在进行DDD. 事实上, 类似Entity和Value Object这样的基本概念上的区别, Side effect free function这样的常识, 是任何一种设计, 任何一种设计方法都应该考虑的.
而更重要的是, 开发过程中哪些实践可以支持DDD的实现? 事实上这一部分是DDD的核心, 甚至你可以把它理解为What而不是How. 因此描述可以反过来: 我们无法保证最终能得出一个完美的领域模型, 我们只能在开发过程中尽力去改进我们手头的模型, 然后顺其自然. 因此如何改进模型才是关键, DDD提供了一些基本的方法来促成这种改进.
开发团队与领域专家的合作: 头脑风暴, 草图, 持续学习, 知识消化...
模型作为统一语言: 捕捉语言的不一致性; 通过对话改进模型.
绑定模型与设计实现: 消除分析和设计之间的Gap; 建模人员同时负责实现
把隐含概念转变为显式概念: 倾听表达用语, 检查不协调之处, 研究矛盾之处, 查阅书籍, 不断尝试重构
借力分析模式
借力设计模式, 尤其是类似策略模式这样偏重于模型概念而不是实现的模式.
更深层次的重构: 组建探索团队, 抓住每个模型与现实不匹配的时机, 将危机视为机会.
...
然而我们通常面临更多的现实约束, 比如我们不是每次都是从头开始建造一个新的系统, 我们不得不与遗留系统进行集成; 也不是只有我们一个开发团队, 我们需要与其他团队合作. Eric将解决这部分问题的方法叫做战略性设计(Strategic Design)
系统涉及面广, 规模庞大: Bounded Context, Context Map, System Metaphor, Responsibility Layers, Knowledge Level
多个团队并行开发, 彼此需要交互: Shared Kernel, Customer/Supplier Team, Conformist, Anticorruption Layer
有另外的系统(通常是遗留的)需要集成: Anticorruption Layer, 各走各路, Open Host Service, Published Language
有限的资源,无限的问题: 好钢用在刀刃上, Distill Core Domain
这确实是最困难的一部分, 如果在战略上选择了不合适的方向, 则前面的构造块, 领域模型只能算是局部优化. TaoWen说DDD这本书只看第四部分就可以了, 这也是一种Distill Core Domain吧.