DDD 起源
Eric Evans 的书:Domain Driven Design:Tackling the Complexity in the Heart of Software。
提出:通过领域模型,捕获领域知识,使用领域模型,构造更易维护的软件 。
软件开发的核心难度在于:处理隐藏在业务知识中的复杂度。模型,就是对这种复杂度的简化和精炼。处理这种复杂度,需要打破业务和技术双方的知识壁垒(统一语言),从而使知识传递、需求沟通变得更高效。
为什么需要领域模型
模型驱动的思路。程序 = 数据结构 + 算法。 通过数据结构出发构造模型,通过算法来解决问题。
在软件开发的早期,树、图、链表、堆、栈等与领域无关的模型,帮助我们解决了编译器、内存管理、数据库索引等大量问题。无数的成功案例给了我们一种习惯:将问题转化为与领域无关的数据结构,即构造与领域无关的模型。
而如果做的是业务软件,就会引入不具备开发背景的业务方参与进来。这个时候,与领域无关的数据结构及其关联的算法,业务方并不理解,也无法直观地映射为业务上的流程和功能。这种认知的差异,就会造成团队的沟通困难。
显而易见的,解决办法就是,构造与领域相关的模型,将业务上的流程和功能,转化为模型的行为。
怎么构造领域模型
Eric、8x提出及总结:不断循环往复“知识消化(Knowledge Crunching)”的步骤,迭代改进的试错法。
crunching,指的是吃薯片时发出的那种难以忽略的咔嚓声。那 knowledge crunching,就意味着我们捕获领域知识的时候,要大声的、引人注意的去获得反馈,哪怕这个反馈是负面的。
知识消化:两关联一循环。
- 模型和软件实现关联
- 模型和统一语言关联
- 提炼知识的循环
模型和软件实现关联
Eric 在知识消化中,并没有强调模型好坏的重要性,反而非常强调模型和软件实现间的关联。
模型不求一步到位,但求一次比一次好,技术方和业务方以迭代反馈的方式,通过提炼知识的循环,逐步完成对模型的淬炼。比起模型的好坏(总是会改好的),模型和软件实现关联就显得更为重要了。
如果模型和软件实现不关联的话,就会导致分裂出 2 个模型:更接近业务方使用的分析模型,更解决软件实现的设计的模型。此时,分析模型就退化成了纯粹的需求沟通的工具,脱离了实现细节,分析就会天马行空、不着边际。
将模型和软件实现关联,一种做法是开发“充血模型、富含知识的模型(Knowledge Rich Model)”。也就是强调了面向对象技术在表达领域模型上的优势。
贫血模型(Anemic Model) --> 充血模型(Knowledge Rich Model) :
贫血模型:对象仅仅是简单的对数据的封装,关联关系和业务计算都散落在对象的范围之外。
充血模型:对象里,包含了某个概念的行为与逻辑。
比如,极客时间中,用户和他订阅的专栏。可能会有2个逻辑:获取用户所有订阅专栏、计算用户所有订阅专栏的总价。
贫血模型的写法:
record User() {
}
record Subscription() {
}
class