领域驱动设计学习笔记一
bounded context:
- 代表一个系统/应用程序/一种业务服务
- 开发、领域专家讨论对话,基于同一种语言/同一个共享的领域模型
ubiquitous language:
- 包含类和主要操作的名称,有些讨论模型中已经明确的规则;
- ubiquitous language的更改就是对模型的更改
domain:
- 代表公司运作的一切
- 和公司组织架构所承担的指责有关
Service:
- 与领域相关的操作不是entity/value object的一个自然组成部分
- 接口是根据领域模型的其他元素定义的
- 操作是无状态的
Entity:
- 有标识符
- 有生命周期
ValueObject:
- 没有唯一标识符
- equals方法,可以用包含的属性来实现
- 他是不可变的
AGGREGATE
- 包含对象之前密不可分的关联
- 可以包含多个entity和value object
- 也被称为根实体,持久化的基本单位
- 在一个aggregate中引用另外一个aggregate是不鼓励的,提倡通过ID引用
实施DDD的关键
- ubiquitous language
- 建模
- 战略建模: 宏观拆分,划分 bounded context,形成俯瞰视角的 Context Map
- 战术建模: 在战略建模划分出得 bounded context中进行 aggregate、entity、value object建模,并按模块分组
领域驱动设计:
- 要求模型不仅能够指导早期的分析工作
- 还应该成为设计的基础
- 要求有一种不同的建模方法
- 要有概念:缺乏概念的后果-只实现有用的功能却无法解释操作的原因
Model-Driven-Design
- service: 表示模型
- entity: 表示模型
- 通过Repository访问
- 通过aggregate维护完整性,entity是aggregate的基础
- 通过factory来封装
- value object: 表示模型
- 通过aggregate封装
- 通过factory封装
- layered architecture: 通过分层隔离领域
- smart ui: 互相排斥的选择
Layered architecture
大多数成功的架构使用的是下面这个4个概念层的变体:
- 表示层
- 向用户显示信息
- 解释用户指令
- 应用层
- 指责:
- 软件要完成的任务
- 指挥表达领域概念的对象来解决问题
- 对业务意义重大,也是与其他系统应用层进行交互的必要渠道
- 实施原则
- 尽量简单,不包含业务规则或者知识
- 为下一层的领域对象协调任务,分配工作,使他们互相协作
- 指责:
- 领域/模型层
- 负责表达业务概念,业务状态信息以及业务规则,验证和计算
- 尽管persist业务状态的技术细节是基础设施实现,反映业务情况状态是本层控制的,本层是业务软件的核心
- 基础设置层(相当于maven的 common module)
- 为以上各层提供能力
- 为应用层传递消息
- 电子邮件
- 传真
- 短信
- 为领域层提供持久化机制
- 为表示层提供展示层组件
- 为应用层传递消息
- 还能通过架构框架支持4个层次间的交互模式
- 为以上各层提供能力
各层调用关系
- 基础设施层不会发起对领域层的操作
- 应用层和领域层可以调用基础设施层所提供的service
aggregate
- 外部对象不能引用除根entity以外的任何对象
CODING GUIDE
- 尽量复用核心模型
- 减少多余的DTO
- Repository-还是保持贫血模型
PROJECT MANAGE GUIDE
- 提炼core domain,交给能够胜任
- 确保实现系统蓝图的深层模型和柔性设计
DOMAIN DESIGN GUIDE
一 指导性原则
- domain vision statement
只是指明了一个方向,比较宽泛的说明,具体核心模型元素留给开发/业务自己去解释和猜测,除非团队沟通极其充分,否则单靠vision statement很难产生效果
- 是想通过什么样的方式/流程达到业务目的
- 不是实现标准/实现要求
- highlighted core
- 精炼文档 描述core domain以及core元素之间的主要交互过程
- 标明Core 在一堆材料当中,筛选出coredomain,最小化可行产品(Minimum Viable Product, MVP)
二 内聚(衔接)机制
core domain或者 generic subdomain的模型描述的是事实、规则或者问题, 而cohesive mechanism满足规则或者用来完成模型指定的计算。 做什么、怎么做要分离。
generic domain 与 cohesive mechanism区别
generic domain 与 cohesive mechanism动机相同的,都为core domain减负的。区别在于职责不同:
- generic domain以描述性的模型为基础,表示出团队会如何看待领域的某个方面。这一点和core domain没什么不同,只是重要性和专门程度较低而已
- cohesive mechanism并不表示领域,目的解决描述性模型提出来的一些复杂的计算问题 一句话来总结,模型提出问题, cohesive mechanism解决问题。
通过精炼得到声明式风格
·
在微服务架构实践中,人们大量地使用了DDD中的概念和技术:
- 微服务中应该首先建立UL,然后再讨论领域模型。
- 一个微服务最大不要超过一个BC(Bounded Context),否则微服务内会存在有歧义的领域概念。
- 一个微服务最小不要小于一个聚合,否则会引入分布式事务的复杂度。
- 微服务的划分过程类似于BC的划分过程,每个微服务都有一个领域模型。
- 微服务间的集成可以通过Context Map来完成,比如ACL(Anticorruption Layer,防腐层)。
- 微服务间最好采用Domain Event(领域事件)来进行交互,使得微服务可以保持松耦合。
不同的Bounded Context 如何需要发生交互,需要通过Context Map实现。 Context Map 可以使用translator(转换层)来实现。 根据是否为紧密集成产品,团队服务用户群,团队协调能力等因素,实现模式有三种
- shared kernal 共享内核。紧密相关应用程序。
- customer/supplier development team 上下游。 有约束的上下游
- conformist 跟随者。 上下游约束松散,但下游强依赖上游
转换层责任:防止边界渗透泄漏,防卫BC,相当于一个隔离层(防腐层) Facade、Adapter
Adapter:把消息转换为语义上等价的。 Facade:基于子系统的模型封装对外(第三方)提供服务。
运用四色建模法进行领域分析
-
时刻-时间段原型(Moment-Interval Archetype) 表示在某个时刻或某一段时间内发生的某个活动。使用粉红色表示,简写为MI。
-
参与方-地点-物品原型(Part-Place-Thing Archetype) 表示参与某个活动的人或物,地点则是活动的发生地。使用绿色表示。简写为PPT。
-
描述原型(Description Archetype) 表示对PPT的本质描述。它不是PPT的分类!Description是从PPT抽象出来的不变的共性的属性的集合。使用蓝色表示,简写为DESC。 举个例子,有一个人叫张三,如果某个外星人问你张三是什么?你会怎么说?可能会说,张三是个人,但是外星人不知道“人”是什么。然后你会怎么办?你就会说:张三是个由一个头、两只手、两只脚,以及一个身体组成的客观存在。虽然这时外星人仍然不知道人是什么,但我已经可以借用这个例子向大家说明什么是“Description”了。在这个例子中,张三就是一个PPT,而“由一个头、两只手、两只脚,以及一个身体组成的客观存在”就是对张三的Description,头、手、脚、身体则是人的本质的不变的共性的属性的集合。但我们人类比较聪明,很会抽象总结和命名,已经把这个Description用一个字来代替了,那就是“人”。所以就有所谓的张三是人的说法。
-
角色原型(Role Archetype) 角色就是我们平时所理解的“身份”。使用黄色表示,简写为Role。为什么会有角色这个概念?因为有些活动,只允许具有特定角色(身份)的PPT(参与者)才能参与该活动。比如一个人只有具有教师的角色才能上课(一种活动);一个人只有是一个合法公民才能参与选举和被选举;但是有些活动也是不需要角色的,比如一个人不需要具备任何角色就可以睡觉(一种活动)。当然,其实说人不需要角色就能睡觉也是错误的,错在哪里?因为我们可以这样理解:一个客观存在只要具有“人”的角色就能睡觉,其实这时候,我们已经把DESC当作角色来看待了。所以,其实角色这个概念是非常广的,不能用我们平时所理解的狭义的“身份”来理解,因为“教师”、“合法公民”、“人”都可以被作为角色来看待。因此,应该这样说:任何一个活动,都需要具有一定角色的参与者才能参与。
用一句话来概括四色原型就是:一个什么什么样的人或组织或物品以某种角色在某个时刻或某段时间内参与某个活动。 其中“什么什么样的”就是DESC,“人或组织或物品”就是PPT,“角色”就是Role,而”某个时刻或某段时间内的某个活动”就是MI。
PPT 通过 MI来记录追溯事件
PPT 和 MI ,通过(command)来完成事件。
学习四色原型图有一段时间了,磕磕碰碰一路走来,更有理解严重偏差的时候,不过近日总算有所领悟了,把一些想法写在这里,供大家共同讨论。
不过说到四色原型图,大家更愿意一起比较的是“领域驱动设计”,简称 DDD,因此这个讨论也就把 DDD 掺合在一起了。
(关于四色原型图的信息,大家可以自行google,有一个英文版的pdf文件。)
1、Moment-interval
这个图被作为是四色原型图中最重要的一个部分。我想也是最难理解的一个图。原文对它的定义是:某一个时刻,或者某一段时间内发生的业务。这种定义非常非常的抽象,导致我们在使用四色原型图去分析业务的时候,很难确定到底什么是 MI。
那么,到底什么是 MI 呢?去除抽象的定义,以及其他挠头的文字,揭开它的本质,其实它就是业务领域的关键性动词!
例如,销售,报告,结算,确认订单 等等,这样关键性的动词,其实都表示一个 MI。
所以,我们也就知道如何发现一个 MI了,在一堆堆的需求文字中,我们要找到关键性的动词,那么它就是 MI,也就是当前这个业务的核心了。围绕着这个 MI,我们会继续发现 ppt,role,desc 等等。所以 MI 神奇吗?一点都不神奇。深奥吗?一点不深奥。
值得一提的是,虽然第一次找到了几个 MI,再经过分析后,很可能这些 MI 会合并到一起--这根据你的需求来设计。
另外一个网上流传甚广,害人不倦的信息是:很多人都说 MI 相当于 DDD 中的 service。这是绝对的误人子弟!通过上面的分析,我们已经知道 MI 必然包含业务的关键性动作,而这类关键性动作,通常是作为领域模型的一个方法,很少会作为 service 的方法。所以,说 MI 相当于 DDD 中的service是绝对的错误,正确的说来,应该是 MI 可能是 DDD 中的 service,更可能是 DDD 中的领域模型。
2、ppt(Party, Place, Thing) 和 role
对于 ppt ,大家都有一个共识,就是 ppt 一般相当于领域模型,而寻找ppt的方式也无外乎就是归纳名词的方式。不过,之前我们一定会先找到 MI,所以这个 ppt 也是围绕着 MI归纳出来的。
Role 是个迷惑大家的东西。因为一提到 role,大家基本都联想到“人”之类的有生命的东西。可是在四色原型里,Role也可能是没有生命的物体。例如,车是一个 ppt,坏掉的车则是车的一个role,良好的车也是车的一个role。虽然我们通常会认为这是车的两个状态,但是这里我们将它设计为车的两个Role。
3、desc
desc这个图的定义是类似目录的结构,起到描述性的作用。大家的共识是它相当于领域模型的值对象----我的理解也就达到这个程度,我觉得用值对象来类比它非常合适,容易让人理解。
4、四色原型,DDD 到底应该选择哪个?
四色原型其实正如其名字一样,是一种分析模式,而不是设计模式。
所以,分析阶段采用四色原型,而在设计阶段采用 DDD 应该是可以的。
其实四色原型也没有什么特别深奥的地方,面对需求文档,我们先找关键性动词,围绕它去找关键性名词,理清业务的逻辑。这是我们常用的思维方式,不过四色原型将这个过程更加科学化,并且用图的方式让这个过程更加清晰。
打个比方:以前我们分析需求是凭感觉,现在则是遵循一定的步骤做。
所以,需求分析,不用四色原型也ok,但是使用四色原型,会更加顺利和清晰。
以上是我对四色原型的思考,欢迎大家来一起讨论。