领域驱动设计(DDD:Domain-Driven Design)
Eric Evans的“Domain-Driven Design领域驱动设计”简称DDD,Evans DDD是一套综合软件系统分析和设计的面向对象建模方法,本站Jdon.com是国内公开最早讨论DDD网站之一,可订阅DDD专题。过去系统分析和系统设计都是分离的,这种割裂导致:对需求分析设计的结果无法直接落地为代码,而能够运行的代码却无法完整实现业务功能,同时,软件Bug频出,维护升级重写难度大。
DDD则打破了这种隔阂,提出了领域模型概念,统一了分析和设计编程,使得软件能够更灵活快速跟随需求变化。见下面DDD与传统CRUD或过程脚本或者面向数据表等在开发效率上比较:
DDD革命性在于:领域模型准确反映了业务领域语言,领域语言是每个行业的行话,正如科学需要数学语言;算法需要编程语言;法律需要法律术语;绘画音乐建筑等也有自己的艺术语言,专业领域都有领域语言。
DDD最大好处是:接触到需求第一步是首先理解其领域语言,提炼出领域模型。DDD让你首先考虑的是领域语言(在特定上下文中的含义),落地的代码能直观映射到领域模型。
DDD难点在于Bounded Context(BC:有界上下文/限界上下文),关键是在于"Context":
- Context:Context is King已经成为现代认知最基本的共识之一
- Context在中文里或指: 上下文、语境、情况、环境、情境、场景、境地、范围、阶段、局限、背景、周期、顺势、作用域、范式、来龙去脉、路径、道、假设、前提、预设、第一性原理、原因...
中文没有专门Context单词,导致人们忽视其通用广泛存在;另外,认知缺乏边界感也是阻碍之一。
识别上下文是界定问题在哪里,在界定的上下文边界内进行符号推理是解决问题。什么是Context上下文?
DDD是解决复杂中大型业务系统的一套行之有效方式,DDD认为很多原因都会造成软件的复杂性,我们不可能避免所有复杂性,一个好的领域模型是控制复杂性的关键。领域模型的价值在于提供一种通用的语言,使得领域专家、产品经理和软件技术人员联系在一起,沟通无歧义。
DDD 的优势:
- 对齐:正如桥梁连接两边一样,领域设计驱动确保软件开发与业务领域无缝连接。
- 灵活性:通过清晰的领域模型,设计驱动发展(DDD)提供了一个基础,可以更好地适应变化,与不断发展的业务需求保持一致。
- 改进协作:通过建立共享语言,可确保开发人员和领域专家之间的清晰度和统一性。
DDD 有许多组成部分和概念,以下是其中的一些概念:
- 领域通用语言UL:领域本体语言,业务行话术语,自成逻辑体系的语系,UL是技术和业务沟通的桥梁。
- BC有界上下文:受专业术语一致限制的形式边界,术语内容含义取决于其语境和上下文。
- 聚合体:领域模型(实体和价值对象)的对象群,作为一个单一的单元来处理和交易。
banq个人观点:
- 事件=点、上下文=线、子域=面
- 线由点组成,建议从事件活动点开始,从下而上涌现中发现上下文。
- 子域的面由很多上下文的线组成。
- 由下而上设计流程:点->线->面;而不是由上而下设计:面->线->点
- DDD建模是一个探索发现过程,无法从顶层设计开始
- 由上而下是一种科学还原论方法,认为事物由分子组成,分子由原子组成,只要找到所有原子就能组装成任何一个物体,其实很多物体现象是由原子之间相互作用才有的涌现属性,如果拆分成单个原子反而找不到这些属性,1+1>2,大于2的属性不属于俩个1,而是两个1组合在一起才有的。
- 事物由下而上涌现产生,如果你颠倒次序,由上而下学习复制,你以为这样的复制还是原来的那个事物吗?上下颠倒制造复制一个就是原来的那个吗?这是在做模具吗?不是,世界不是用机械模具复制出来的。
DDD落地架构有:Clean架构、六边形架构、 CQRS、Event Source几大大相关领域。下图是传统以数据库为中心的架构与使用DDD实现以领域为中心架构的区别。
服务器后端架构发展两个阶段:
- UI+Service+DataBase的多层SOA架构(上图左),这种服务+数据表模型的架构易使服务变得囊肿,难于维护拓展,伸缩性能差,见这里讨论或Spring Web 应用的最大败笔
- DDD+ 模块化单体或微服务:DDD作为数据建模的升级,主要贡献在于领域界线的划分,界定界限以后,通过两种架构实现领域模型代表的业务功能:模块化单体或微服务架构。
DDD专门为解决复杂性而诞生,因此解决思路完全不同于传统的CRUD,但是DDD本身掌握起来并不会感觉复杂,从程序员角度看,DDD其实是研究将包含业务逻辑的ifelse语句放在哪里的学问,包括业务流程、业务规则、规则引擎、术语字典、DSL或正则表达式、商业智能和数据分析等都属于业务逻辑的范畴领域。
DDD推进过程主要难点是领域发现和领域建模,万事开头难,目前用于领域发现的方法有:事件风暴、业务能力建模、领域讲故事、业务模型画布、示例映射、影响映射、Wardley Maps等,全球DDD社区为此做出主要贡献的人员名单(按Twitter名称排列):
@ericevans0 创建了DDD
@ziobrando 发明了事件风暴建模方法。
@ntcoding 发明使用画布canvas 映射有界上下文方法。
@swardley 发明WardleyMapping方法进行战略规划。
@mathiasverraes 提出了事件溯源具体设计策略,提出复杂系统的仿真建模。
@gregyoung 提出CQRS模式来分离模型。
教程与文章
板桥大话DDD
用大白话简单谈谈DDD的一些基础特点,只是扫盲!数据库SQL强人慎入Vladik Khononov:如何学习领域驱动设计? DDD基础新书
《复杂软件设计之道:领域驱动设计全面解析与实战》
博主banq的DDD深入全面书籍板桥:为什么DDD的Bounded Context翻译为"有界上下文"?
面向对象建模与数据库建模两种分析设计方法的比较
数据库驱动设计与对象建模是决定软件不同命运的两大派别,谁可以让软件更具有生命,维护拓展更方便?伸缩性更强?面向对象与领域建模
据调查,目前有70%左右程序员是在使用OO语言编写传统过程化软件,缺乏完整的面向对象思维方法的教育和培训是基本根源,本文对软件开发中几个常见问题提出了独立的见解及尖锐的观点Evans DDD 领域建模
如何提炼模型,而不是数据表,进而精化模型对象,使其能够反映领域概念基本本质是一个复杂过程,Evans DDD是2004年提出的具备革命性影响的软件思想。实战DDD(Evans DDD:Domain-Driven Design领域驱动设计)
领域建模是一种艺术的技术,不是数学的技术,它是用来解决复杂软件快速应付变化的解决之道。如何从职责和协作中发现丰富的充血对象?
失血模型贫血模型是DDD最大敌人,如何根据SOLID原则和GRASP原则设计业务行为?本文给出了DDD具体实践中一些具体细节,是和DDD配合一起进行面向对象分析设计的好方法。DDD CQRS和Event Sourcing的案例:足球比赛
DDD + CQRS + Event Sourcing实现案例,结合代码与理论讲解。集装箱车队系统的DDD案例
为上海某大型港口公司的运输系统实施的一个领域驱动设计DDD的实战咨询案例。使用DDD聚合发现隐藏的业务规则的案例分析:数据库事务的业务实现
向领域驱动设计前进: 如何使用DDD实现从单体到微服务迁移打造业务平台或中台?
DDD+微服务大型案例:Uber如何从复杂的RPC微服务转向面向业务领域的微服务架构DOMA?