- Published on
领域驱动设计-1
领域驱动设计DDD
敏捷开发宣言:https://agilemanifesto.org/iso/zhchs/manifesto.html
敏捷宣言遵循的原则:https://agilemanifesto.org/iso/zhchs/principles.html
建模和设计就是将 领域和知识转换为代码的过程
挖掘用户故事,建立通用语言,战略设计,战术设计,都是长期的。不是只属于某一阶段。
# 简要概念
**用户故事**:对问题空间的描绘
很多团队在开始做项目的时候,产品经理先出一个无比细致的设计文稿,开发同学也很喜欢用写需求文档不细致这一点来怼产品,就好像是一种政治正确。产品不是按部就班的板砖。 一开始就把产品和功能都定稿,可能是一个没有生命力的产品。 好的产品是所有人不断讨论修改打磨得到的。
敏捷方法提倡在早期使用用户故事对需求进行恰当好处的描述,而不是太过细致。用户故事对认识的描述,而不是解决方案。
**通用语言**:
- 讨论模型和定义模型时,团队使用同一种语言
- 领域知识需要在团队内部高效流转,模型需要描述
- 通用语言要体现在代码里
**战略设计**:共同讨论
- 对问题空间和解决空间进行分解的过程
- 目的是分解模型以控制复杂性
- DDD与传统建模和设计方法的核心区别之一。
**战术设计**:开发过程
- 对各个BC的细节设计过程
- BC内部的模型结构与完整及时方案
- (战术设计是包括编码的)
常用建模方法:
- Domain Storytellig 领域故事陈述法 简单易用。
- Event Storming 事件风暴法 影响力最大,
- 4C 四色建模法
DDD认为现有工作的方式:
产品经理提需求写文档,开发理解进行技术方案设计。
以需求为粒度进行协作。问题点和领域知识重叠,模型重叠。 重复劳动,压力大。归根结底,效率低,职责重叠导致冲突。所以要基于子域进行分工协作。
不同子域交付给不同人负责,不同子域聚焦不同问题。 有经验的架构师直接通过直觉经验进行子域划分。 那么怎么检验划分的结果。
基于用户故事分解的领域划分。 分解过程中仍然需要大量思考和不同的讨论。
1. 用户故事
1.1 什么是用户故事及如何描述
用户故事描述了不同类型的用户需要什么以及为什么需要,它可以帮助我们创建需求的简单描述。
在软件开发和演进过程中,随着产品和开发对产品认识的加深,需求总是在不断变化,所以,过早地进入需求细节以及对细节的描述,是一种时间上的巨大浪费。从这一点来说,用户故事提供了一种恰到好处的粒度,使得产品在需求分析阶段能够极大地节约时间,并且使产品和研发人员始终把注意力集中在关键点,避免他们过早地陷入细节以及被细节所局限,同时给产品功能留出了讨论空间,从而使产品有机会在讨论过程中得到优化。
用户故事的构建一般来说有三个环节:
- 简单描述用户需求;
- 围绕简单描述进行讨论;
- 明确如何验证。
分别对应用户故事的三个元素,也就是3C:Card(卡片)、Conversation(谈话)、Confirmation(验证)。
1.1.1 Card(卡片)
“卡片”就是指对用户故事的简述(传统上人们通过便利贴在白板上构建用户故事),一个好的用户故事卡片包括三个要素:
-
谁:谁需要这个功能;
-
需要什么:想通过系统完成什么事情;
-
为什么:为什么需要这个功能,这个功能带来什么样的价值。
1.1.2 Conversation(谈话)
谈话是指用户、领域专家、产品经理、研发之间围绕用户故事进行的讨论,谈话是明确需求细节的必要环节。可以用文字对谈话进行简要记录,此外,也可以基于图形或其他工具进行讨论。稍后我们会介绍相关工具可以对用户故事进行挖掘和细化([使用Domain Storytelling挖掘用户故事](# 2. 使用Domain Storytelling挖掘用户故事))。
1.1.3 Confirmation(验证)
验证代表了验收测试,描述了客户或者产品owner怎样确定用户故事已经被实现,且能够满足需求。一般可以用如下模板写Confirmation:
假设我是<角色>,在xxx情况下,
当我<操作>,
那么<结果>。
2. 使用Domain Storytelling分析用户故事
学会一种语言的最好方式是听别人说这种语言,尝试重复他们所说的并留意他们的反馈。
2.1 什么是domain storytelling?
Domain Storytelling是一种领域分析建模方法,通过这种方法,产品和研发人员可以利用语言学习的相同原理建立或者学习一个领域的通用语言,并且建立领域模型。
2.2 domain storytelling图和相关工具
在storytelling过程中,一方(通常是架构师)聆听另一方(通常是产品经理或者领域专家)以主谓宾的句型(谁做了什么)讲述用户故事的流程,进行问答和讨论,并以图形的方式快速复述出来。直观理解为步骤图,或者流程图,行为图。
使用在线工具domain-story-modeler,可以在线实践domain storytelling。
3. 建立通用语言
我们对用户故事进行storytelling,其实就是建立领域通用语言的过程,storytelling的输出结果(上述的storytelling图)也就包含了领域通用语言的完整语句,对象、角色、活动、以及体现它们相互作用的完整语句,在图中都可以一览无余。这里我们可以更进一步,将通用语言中的词汇提炼出来,将其中英文都列在通用语言词汇表中,这些词汇将会贯穿整个建模和设计过程,最终也会体现在代码中,因此团队中所有成员,都需要明确理解其含义,并且在相关讨论、模型、以及代码中使用它们。这个表格的样例如下所示,完整表格较长
其实就是一个业务相关名词的字典。
| 类型 | 中文 | 英文 | 上下文 | | ---- | -------------------------- | ----------------------- | -------------------------- | | 对象 | 商品 | commodity | 用户选择商品 | | 对象 | 支付 | payment | 用户完成支付 | | 对象 | 货道售卖机 | slot vending machine | 货道售卖机展示支付二维码 | | 对象 | 支付二维码 | payment QR code | 货道售卖机展示支付二维码 | | 系统 | 手机支付平台 | mobile payment platform | 用户在手机支付平台完成支付 | | 对象 | 柜门机(无人货柜、货柜机) | cabinet vending machine | 柜门机解锁柜门 | | 对象 | 柜门机二维码 | cabinet QR code | 用户扫描柜门机二维码 | | .... | .... | .... | .... |
4. 领域划分
领域划分是对问题空间的划分,原则是分离关注点,目的是将系统的建模和设计工作分而治之,进行简化,并为寻找限界上下文提供依据,打下基础。
用户故事是从用户的角度对需求的描述,也就是领域问题的描述,是与实现方案无关的。我们可以借助用户故事进行领域划分。顶层用户故事能够让我们对系统有一个全局性的认识,但是并不包含太多细节,其中的每个活动,可能较复杂,也可能包含了多个子领域的信息。如果我们要深入利用用户故事进行战略和战术设计,需要将它分解成子用户故事,将用户故事中模糊的部分逐层分解,直至清晰和聚焦。
4.1 分解用户故事
4.2 基于用户故事进行领域划分
对于分解之后的用户故事,我们可以按照分离关注点的原则将其进行分类,将关注同一细分领域的用户故事分为一组,将这些用户故事形成的小组命名,即可得到各个子领域,同时根据用例之间的层次关系,也能得到各个子领域之间的关系。
5. 限界上下文的识别和上下文映射
5.1 寻找限界上下文
通过分别从各子领域的用户故事中提取关键概念,审视它们之间的关系,以及它们与外部系统之间的关系,我们可以梳理出系统中的限界上下文。
融合了领域划分和限界上下文的全局系统概览如下图所示:
5.2 上下文映射
确定上下文之间的关系,绘制上下文映射图,是战略设计中非常重要的一步。
5.2.1 SmartRM上下文映射
通过明确SmartRM之间的关系,决定应用到上下文之间的协作模式,并且在必要的地方引入防腐层(ACL)。我们得到下面的上下文映射图: