策略Strategy
实体可以使用 ID 标识,但是值对象是用属性标识,任何属性的变化都视为新的值对象。比如一个银行账户,可以由 ID 唯一标识,币种和余额可以被修改但是还是同一个账户;交易单中的金额由币种和数值组成,无论修改哪一个属性,金额都不再是原来的金额。
DDD 是 Domain-Driven Design 的缩写,其主要的思想是,利用确定的业务模型来指导业务与应用的设计和实现。主张开发人员与业务人员持续地沟通和模型的持续迭代式演化,以保证业务模型与代码实现的一致性,从而实现有效管理业务复杂度,优化软件设计的目的。
聚合Aggregate
技术专家是指熟悉技术方案和实现方式的人,能给出可行的技术方案和了解基础设计的限制条件。技术专家需要能对现有的技术做出描述,而未来的技术选型可能是动态的,能有一定预见性最好。技术专家往往是当前团队中最熟悉架构和代码的人。
微服务Micro Service
分层架构Layered Architecture
目标
定时器Timer
聚合根( Aggregate Root)是聚合中最核心的实体,其他的实体和值对象都从属于这个实体。要管理聚合必须使用一个聚合根,然后使用聚合根来实现发现、持久化聚合的作用,完成统一的业务意义。一个聚合中有且只有一个聚合根,聚合也可以只有一个单独的实体。
规格(Specification) 是一些特殊的业务规则。通常表现为用于校验(数据格式,业务逻辑)、搜索条件。在实践中,规格既可以被设计为灵活的查询或校验条件,也可以被抽象出来以便复用。例如,在 JPA、MongoDB、ElastiSearch和一些具有查询能力的 ORM 都大量使用这种设计方式,同样的在应用程序中我们也可以参考这种设计模式,把业务的规则提取出来。
通过
微服务是一种低耦合的分布式应用系统。
分为
领域层,实现具体的业务逻辑、规则,为应用层提供无差别的服务能力。实际处理业务的地方,领域层需要对应用层提供无差别的服务和能力。领域层特点:不关心场景,关心模型完整性和业务规则不关心谁来,不关心场景完整的业务,关心当前上下文的业务完整强一致性事务放到这层领域层做业务规则验证数据权限放到这层,因为数据权限涉及业务规则
领域模型(Model)是业务概念在程序中的一种表达方式。领域模型可以用来设计和理解整个软件结构。面向对象设计中的类概念是领域模型的一种表达方式。与此类似,UML的建模方法也可以应用在对领域模型的表达上。在 DDD 实践中,领域模型应当尽量简洁,能反应业务概念即可。
事件风暴Event Storming
持久化
战略设计也称为战略建模,是指对业务进行高层次的抽象和归类。主要手段包括理清上下文和进行子域的划分。战略设计的产出通常为上下文图,以及模块或微服务划分。
工厂(Factory)是以构建领域模型(实体或值对象)为职责的类或方法。
领域(Domain)是业务相关知识的集合。通俗来说,领域就是业务知识。业务有一些内在规则,存在专业性,比如财务、CRM、OA、电商等不同领域的业务规则不同。计算机只是业务规则的自动化。公司业务是医疗影像领域。
战术设计Tactical Design
领域模型Model
上下文Context
工厂Factory
领域专家是指熟悉业务规则的人,一般是能敲定业务规则的人。需要分清现状(As-IS)和目标(To-Be)业务,现状业务很多人都能说出来,不过真正的领域专家是能对目标业务做出描述的人。
包含
限界上下文是有明确边界的上下文。在 DDD 实践中领域模型会被限定在限界上下文当中。限界上下文强调概念的一致性。虽然传统的方法学已经在追求概念的一致性,但是忽略了系统的庞大性,不论系统多庞大,在系统任何位置同一概念通用。DDD 不追求全局的一致性,而是将系统拆成多块,在相同的上下文中实现概念一致性。识别上下文可以从概念的二义性着手,比如商品的概念在物流、交易、支付含义完全不一样,但具有不同内涵和外延,实际上他们处在不同上下文。限界上下文可以用于微服务划分、避免模型的不正确复用带来的问题。
模型是对对象、人或系统的信息表示。它通过较为简单的信息结构来代表我们需要理解的复杂事物或系统。
定时器是执行者的一种,通常是定时任务。比如xxl-job
解空间Solution Space
模型驱动设计Model Driven Design
不同的上下文是识别模型边界的手段。
表达领域概念
一种工作方法
事件风暴是一种以工作坊的形式,使用 DDD 建模的方式。事件风暴通过工作坊的方式将领域专家和技术专家拉到一起,进行建模。事件风暴是一种捕获行为需求的方法,类似传统软件的开发用例分析。所有人员(领域专家和技术专家) 对业务行为进行一次发散,并最终收敛达到业务的统一。
参与人只是一种角色,而非具体的一个人,可以是多个自然人做群体参与,也可以一人分饰不同的角色。(应区别于执行者)参与人需要满足一些条件:参与人需要对解决的问题和产出目标达成共识参与人需要 DDD 的基本知识或接受过基本培训领域专家、技术专家需要全程参加
属于
软件设计从软件需求出发,对软件系统的整体结构、模块做出划分和规划,以便于具体代码的顺利编写。
简化
支撑域Support Domain
协作共创是指领域专家和业务专家共同建模。
是一种特殊的
划分范式
领域驱动设计DDD
业务规则policy
获得
命令Command
指导
聚合(Aggregate)是一组生命周期强一致,修改规则强关联的实体和值对象的集合,表达统一的业务意义。聚合的意义在于让业务统一、一致,在面向对象中有非常重要价值。比如,订单中有多个订单项,订单的总价是根据订单项目计算而来的。如果没有经验的开发者直接对订单项做出修改,而不是由订单统一处理业务逻辑,会造成业务的一致性问题。聚合需要在相同的上下文中,不能跨上下文。
接入层Interface Layer
导出
分布式应用系统Distributed
初始化
用户是执行者的一种,是指使用软件或服务的人。用户可以有不同的角色,通常我们会把不同角色的相似行为作为不同的命令来处理,有可能得到同样的事件。比如系统出现了商品已添加的事件,有可能有多个触发的场景: 1. 系统管理员在后台添加 2. 商户在自己的管理平台添加;是用户的行为,不过是不同的角色。
模块Module
执行者actor
模型Model
聚合根Aggregate Root
协作共创Collaboration
本系统System
仓储(Repository)是以持久化领域模型为职责的类。
事件是系统状态发生的某种客观现象,领域事件是和领域有关的事件。领域事件(Domain Event),是在业务上真实发生的客观事实,这些事实对系统会产生关键影响,是观察业务系统变化的关键点。领域事件一般是领域专家关心的。事件的评价方式是系统状态是否发生变化。系统状态变化意味着领域模型被业务规则操作,这是观察系统业务的好方法。识别领域事件的线索有:是否产生了某种数据系统状态是否发生变化,无论这种状态存放到数据库还是内存是否对外发送了某些消息
模块(Module)是一组类或者对象组成的集合。在 DDD 实践中推荐使用限界上下文和聚合来指导模块划分。
分层架构是指在软件设计过程中按照既定的原则将不同的功能实现拆分到不同的层级进行实现的一种设计方式。每个层级有独立的职责,多个层次协同以提供完整功能。按照 DDD 的分层模型,通常可以划分为:接入层、应用层、领域层、基础设施层。
领域模型中的
通用域是另一种特殊的子域,对应的是业界已经有成熟方案的业务。通用域可以看做一种特殊的支撑域,可以使用标准部件来实现,短信通知、邮件等领域问题。
问题空间是待解决的业务问题的集合。
应用层,组织业务场景,编排业务,隔离场景对领域层的差异。应用层遵循面向对象核心思想中的 “关注点分离” 理念。应用层的关注点在于业务场景的处理。应用层特点:关心处理完一个完整的业务该层只负责业务编排,对象转换,而具体的业务逻辑由领域层实现虽不关心请求从何处来,但关心谁来、做什么、有没有权限做利用不同的领域服务来解决问题对最终一致性有要求的业务和事务处理需要放到应用层来处理功能权限放到这层
主持人Facilitator
基础设施层,提供具体的技术实现,比如存储,基础设施对业务保持透明。对于基础设施层来说,基础设施层并不是指 MySQL、Redis 等外部组件,而是外部组件的适配器,Hibernate、Mybatis、Redis Template 等,因此在 DDD 中适配器模式被多次提到,基础设施层往往不能单独存在,还是要依附于领域层。技术设施层的适配器还包括了外部系统的适配。技术设施层特点:关心存储、通知、第三方系统等外部设施(防腐层隔离)基础设施的权限由配置到应用的凭证控制,例如数据库、对象存储的凭证,技术设施层不涉及用户的权限
技术专家Tech Expert
作为 ... 的代表
遵守
仓储Repository
持续建模Continuous
在面向对象程序设计中,工厂是一种设计模式。在广义的工厂模式中,工厂可以根据不同的规则的业务需求构造不同的对象。
策略(Strategy)是业务规则的实现方式。例如通知业务,可以使用不同的渠道来实现,不同渠道的实现逻辑可以认为是不同的策略。 在面向对象程序设计中,策略模式也是一种设计模式,是多态的一种实现模式。策略通常会搭配着接口来设计。如果说接口是一种契约,那策略就是契约的履约方式。
把逻辑架构和部署架构区分开可以很好的理解软件设计上和部署上的不同,对于应用构架来说,逻辑上的设计不一定对应部署结构。DDD 在不同场景中的使用方式不同,避免生搬硬套。当 DDD 的分层结构在单体应用中使用时,每层可能使用包、模块来表达,在微服务中使用的时候,每层可能由不同角色的微服务来完成。
基础设施层Infrastructure Layer
支撑域是一种特殊的子域,是指为了实现核心业务而不得不开发的业务所对应的相关知识的集合。
设计层次
本系统是执行者的一种,指系统本身。
业务操作
外部系统是执行者的一种,系统开放 API 的调用发起者。有一些系统会提供对外的 API 给外部系统,这时候外部系统也会发出命令让系统产生事件,这里的外部系统特指作为执行者的外部系统。
实体Entity
单体Monomer
问题空间Problem Space
服务(Service)是领域模型的操作者,负责领域内的业务规则的实现。
领域专家Domain Expert
限界上下文Bounded Context
核心域就是最关键的业务逻辑,聚焦核心域决定了软件的定位和重心。
值对象是一种特殊的领域模型,不可变,通过值判断同一性。
解空间在 DDD 的上下文中,指的是所有可能的解决方案的集合。解空间是相对问题空间存在的,认识到解空间存在的好处是解空间可以通过一些方法从问题空间导出,而不是通过猜测得出的。
执行者是指使用系统的主体,是导致系统状态变化的触发源。执行者有点像 UML 的涉众,不过区别是执行者不仅是用户,还包括外部系统和本系统。 在事件风暴中,执行者可以是:用户、外部系统、本系统、定时器。
解决的问题
参考
业务规则是指对业务逻辑的定义和约束。不同的业务规则往往意味着不同的领域事件被触发,未来在技术实现时可能是一些分支条件,对应 DDD 实现中可能通过领域服务、规格、策略等方式实现。业务规则的识别是为了将数据和算法分开。
通用语言(Ubiquitous language)是指在软件设计中,业务人员和开发人员需要使用无歧义的统一语言来对话。这些语言包括对概念的统一理解和定义,以及业务人员参与到软件建模中,否则业务的变化会造成软件巨大的变化。
聚焦核心域Focus
应用层Application Layer
参与人Participants
建模是构建模型的过程。在软件设计过程中,通过分析业务,将业务需求使用合适的模型表示出来,是建模的任务。模型可以作为业务分析的产出,并作为软件设计的重要理论基础。
为了更好的践行 DDD,需要遵守
事件Event
软件设计Software Design
是一种
通用语言Ubiquitous
领域层Domain Layer
关注在
值对象Value Object
Model-Driven Design,面向模型的分析设计方法,优先通过识别模型来简化业务设计。
主持人是流程的推动者,以及 DDD 方法论的守护者,推动工作进行。
建模Modeling
分析模型的建立
接入层负责的是系统的输入和输出。接入层只关心沟通协议,不关心业务相关的数据校验。 接入层的实现是与业务应用强相关的,不同的业务应用有不同的实现方式。例如,对于普通的 Web 应用,基于 HTTP 协议的 API 是一种接入层实现方式;对于IoT传感器的数据上传业务,接入层的实现可能需要基于 websocket 或 MQTT 协议。接入层特点:接入层对应用数据透明,只关心数据格式而不关心数据的内容在大部分单体系统中接入层通常被框架实现。例如,在 Spring Boot 框架中,HTTP 协议的 API 设计不需要关注 HTTP 协议本身。在分布式系统中接入层通常被网关实现。
原则Principle
子域是领域的一部分。为了降低业务理解复杂度,DDD 实践中通常将领域划分为多个子域,通过分而治之的方法分析问题。
规格Specfication
子域Sub Domain
使用
通用域General Domain
战略设计Strategic Design
一种具体的方法
持续建模是指模型需要随业务变化而被及时更新。
命令是执行者发起的操作,构成要素是执行者和行为。命令可以类比于 UML 分析中的业务用例,是某个场景中领域事件的触发动作。
外部系统Out System
核心域是指领域中最核心的部分,通常对应企业的核心业务
可划分为
包括
实体是在相同限界上下文中具有唯一标识的领域模型,可变,通过标识判断同一性。
核心域Core Domain
用户User
软件Software
部署架构Deployment Architecture
服务Service
领域Domain
战术设计也称为战术建模,是指对特定上下文下的模型进行详细设计。战术设计的产出可以是用 UML 表达的类图,需要细化到具体的属性,同时确保在代码级别可实现。