learn.lianglianglee.com/专栏/领域驱动设计实践(完)/060 案例 订单核心流程的四色建模.md.html
2022-05-11 19:04:14 +08:00

1021 lines
45 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<!-- saved from url=(0046)https://kaiiiz.github.io/hexo-theme-book-demo/ -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
<link rel="icon" href="/static/favicon.png">
<title>060 案例 订单核心流程的四色建模.md.html</title>
<!-- Spectre.css framework -->
<link rel="stylesheet" href="/static/index.css">
<!-- theme css & js -->
<meta name="generator" content="Hexo 4.2.0">
</head>
<body>
<div class="book-container">
<div class="book-sidebar">
<div class="book-brand">
<a href="/">
<img src="/static/favicon.png">
<span>技术文章摘抄</span>
</a>
</div>
<div class="book-menu uncollapsible">
<ul class="uncollapsible">
<li><a href="/" class="current-tab">首页</a></li>
</ul>
<ul class="uncollapsible">
<li><a href="../">上一级</a></li>
</ul>
<ul class="uncollapsible">
<li>
<a href="/专栏/领域驱动设计实践(完)/001 「战略篇」访谈 DDD 和微服务是什么关系?.md.html">001 「战略篇」访谈 DDD 和微服务是什么关系?.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/002 「战略篇」开篇词:领域驱动设计,重焕青春的设计经典.md.html">002 「战略篇」开篇词:领域驱动设计,重焕青春的设计经典.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/003 领域驱动设计概览.md.html">003 领域驱动设计概览.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/004 深入分析软件的复杂度.md.html">004 深入分析软件的复杂度.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/005 控制软件复杂度的原则.md.html">005 控制软件复杂度的原则.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/006 领域驱动设计对软件复杂度的应对(上).md.html">006 领域驱动设计对软件复杂度的应对(上).md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/007 领域驱动设计对软件复杂度的应对(下).md.html">007 领域驱动设计对软件复杂度的应对(下).md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/008 软件开发团队的沟通与协作.md.html">008 软件开发团队的沟通与协作.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/009 运用领域场景分析提炼领域知识(上).md.html">009 运用领域场景分析提炼领域知识(上).md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/010 运用领域场景分析提炼领域知识(下).md.html">010 运用领域场景分析提炼领域知识(下).md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/011 建立统一语言.md.html">011 建立统一语言.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/012 理解限界上下文.md.html">012 理解限界上下文.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/013 限界上下文的控制力(上).md.html">013 限界上下文的控制力(上).md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/014 限界上下文的控制力(下).md.html">014 限界上下文的控制力(下).md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/015 识别限界上下文(上).md.html">015 识别限界上下文(上).md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/016 识别限界上下文(下).md.html">016 识别限界上下文(下).md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/017 理解上下文映射.md.html">017 理解上下文映射.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/018 上下文映射的团队协作模式.md.html">018 上下文映射的团队协作模式.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/019 上下文映射的通信集成模式.md.html">019 上下文映射的通信集成模式.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/020 辨别限界上下文的协作关系(上).md.html">020 辨别限界上下文的协作关系(上).md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/021 辨别限界上下文的协作关系(下).md.html">021 辨别限界上下文的协作关系(下).md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/022 认识分层架构.md.html">022 认识分层架构.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/023 分层架构的演化.md.html">023 分层架构的演化.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/024 领域驱动架构的演进.md.html">024 领域驱动架构的演进.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/025 案例 层次的职责与协作关系(图文篇).md.html">025 案例 层次的职责与协作关系(图文篇).md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/026 限界上下文与架构.md.html">026 限界上下文与架构.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/027 限界上下文对架构的影响.md.html">027 限界上下文对架构的影响.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/028 领域驱动设计的代码模型.md.html">028 领域驱动设计的代码模型.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/029 代码模型的架构决策.md.html">029 代码模型的架构决策.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/030 实践 先启阶段的需求分析.md.html">030 实践 先启阶段的需求分析.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/031 实践 先启阶段的领域场景分析(上).md.html">031 实践 先启阶段的领域场景分析(上).md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/032 实践 先启阶段的领域场景分析(下).md.html">032 实践 先启阶段的领域场景分析(下).md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/033 实践 识别限界上下文.md.html">033 实践 识别限界上下文.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/034 实践 确定限界上下文的协作关系.md.html">034 实践 确定限界上下文的协作关系.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/035 实践 EAS 的整体架构.md.html">035 实践 EAS 的整体架构.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/036 「战术篇」访谈DDD 能帮开发团队提高设计水平吗?.md.html">036 「战术篇」访谈DDD 能帮开发团队提高设计水平吗?.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/037 「战术篇」开篇词:领域驱动设计的不确定性.md.html">037 「战术篇」开篇词:领域驱动设计的不确定性.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/038 什么是模型.md.html">038 什么是模型.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/039 数据分析模型.md.html">039 数据分析模型.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/040 数据设计模型.md.html">040 数据设计模型.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/041 数据模型与对象模型.md.html">041 数据模型与对象模型.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/042 数据实现模型.md.html">042 数据实现模型.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/043 案例 培训管理系统.md.html">043 案例 培训管理系统.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/044 服务资源模型.md.html">044 服务资源模型.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/045 服务行为模型.md.html">045 服务行为模型.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/046 服务设计模型.md.html">046 服务设计模型.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/047 领域模型驱动设计.md.html">047 领域模型驱动设计.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/048 领域实现模型.md.html">048 领域实现模型.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/049 理解领域模型.md.html">049 理解领域模型.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/050 领域模型与结构范式.md.html">050 领域模型与结构范式.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/051 领域模型与对象范式(上).md.html">051 领域模型与对象范式(上).md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/052 领域模型与对象范式(中).md.html">052 领域模型与对象范式(中).md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/053 领域模型与对象范式(下).md.html">053 领域模型与对象范式(下).md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/054 领域模型与函数范式.md.html">054 领域模型与函数范式.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/055 领域驱动分层架构与对象模型.md.html">055 领域驱动分层架构与对象模型.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/056 统一语言与领域分析模型.md.html">056 统一语言与领域分析模型.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/057 精炼领域分析模型.md.html">057 精炼领域分析模型.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/058 彩色 UML 与彩色建模.md.html">058 彩色 UML 与彩色建模.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/059 四色建模法.md.html">059 四色建模法.md.html</a>
</li>
<li>
<a class="current-tab" href="/专栏/领域驱动设计实践(完)/060 案例 订单核心流程的四色建模.md.html">060 案例 订单核心流程的四色建模.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/061 事件风暴与业务全景探索.md.html">061 事件风暴与业务全景探索.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/062 事件风暴与领域分析建模.md.html">062 事件风暴与领域分析建模.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/063 案例 订单核心流程的事件风暴.md.html">063 案例 订单核心流程的事件风暴.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/064 表达领域设计模型.md.html">064 表达领域设计模型.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/065 实体.md.html">065 实体.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/066 值对象.md.html">066 值对象.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/067 对象图与聚合.md.html">067 对象图与聚合.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/068 聚合设计原则.md.html">068 聚合设计原则.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/069 聚合之间的关系.md.html">069 聚合之间的关系.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/070 聚合的设计过程.md.html">070 聚合的设计过程.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/071 案例 培训领域模型的聚合设计.md.html">071 案例 培训领域模型的聚合设计.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/072 领域模型对象的生命周期-工厂.md.html">072 领域模型对象的生命周期-工厂.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/073 领域模型对象的生命周期-资源库.md.html">073 领域模型对象的生命周期-资源库.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/074 领域服务.md.html">074 领域服务.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/075 案例 领域设计模型的价值.md.html">075 案例 领域设计模型的价值.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/076 应用服务.md.html">076 应用服务.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/077 场景的设计驱动力.md.html">077 场景的设计驱动力.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/078 案例 薪资管理系统的场景驱动设计.md.html">078 案例 薪资管理系统的场景驱动设计.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/079 场景驱动设计与 DCI 模式.md.html">079 场景驱动设计与 DCI 模式.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/080 领域事件.md.html">080 领域事件.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/081 发布者—订阅者模式.md.html">081 发布者—订阅者模式.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/082 事件溯源模式.md.html">082 事件溯源模式.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/083 测试优先的领域实现建模.md.html">083 测试优先的领域实现建模.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/084 深入理解简单设计.md.html">084 深入理解简单设计.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/085 案例 薪资管理系统的测试驱动开发(上).md.html">085 案例 薪资管理系统的测试驱动开发(上).md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/086 案例 薪资管理系统的测试驱动开发(下).md.html">086 案例 薪资管理系统的测试驱动开发(下).md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/087 对象关系映射(上).md.html">087 对象关系映射(上).md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/088 对象关系映射(下).md.html">088 对象关系映射(下).md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/089 领域模型与数据模型.md.html">089 领域模型与数据模型.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/090 领域驱动设计对持久化的影响.md.html">090 领域驱动设计对持久化的影响.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/091 领域驱动设计体系.md.html">091 领域驱动设计体系.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/092 子领域与限界上下文.md.html">092 子领域与限界上下文.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/093 限界上下文的边界与协作.md.html">093 限界上下文的边界与协作.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/094 限界上下文之间的分布式通信.md.html">094 限界上下文之间的分布式通信.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/095 命令查询职责分离.md.html">095 命令查询职责分离.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/096 分布式柔性事务.md.html">096 分布式柔性事务.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/097 设计概念的统一语言.md.html">097 设计概念的统一语言.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/098 模型对象.md.html">098 模型对象.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/099 领域驱动设计参考过程模型.md.html">099 领域驱动设计参考过程模型.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/100 领域驱动设计的精髓.md.html">100 领域驱动设计的精髓.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/101 实践 员工上下文的领域建模.md.html">101 实践 员工上下文的领域建模.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/102 实践 考勤上下文的领域建模.md.html">102 实践 考勤上下文的领域建模.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/103 实践 项目上下文的领域建模.md.html">103 实践 项目上下文的领域建模.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/104 实践 培训上下文的业务需求.md.html">104 实践 培训上下文的业务需求.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/105 实践 培训上下文的领域分析建模.md.html">105 实践 培训上下文的领域分析建模.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/106 实践 培训上下文的领域设计建模.md.html">106 实践 培训上下文的领域设计建模.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/107 实践 培训上下文的领域实现建模.md.html">107 实践 培训上下文的领域实现建模.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/108 实践 EAS 系统的代码模型.md.html">108 实践 EAS 系统的代码模型.md.html</a>
</li>
<li>
<a href="/专栏/领域驱动设计实践(完)/109 后记:如何学习领域驱动设计.md.html">109 后记:如何学习领域驱动设计.md.html</a>
</li>
</ul>
</div>
</div>
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
<div class="sidebar-toggle-inner"></div>
</div>
<script>
function add_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.add('show')
}
function remove_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.remove('show')
}
function sidebar_toggle() {
let sidebar_toggle = document.querySelector('.sidebar-toggle')
let sidebar = document.querySelector('.book-sidebar')
let content = document.querySelector('.off-canvas-content')
if (sidebar_toggle.classList.contains('extend')) { // show
sidebar_toggle.classList.remove('extend')
sidebar.classList.remove('hide')
content.classList.remove('extend')
} else { // hide
sidebar_toggle.classList.add('extend')
sidebar.classList.add('hide')
content.classList.add('extend')
}
}
function open_sidebar() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.add('show')
overlay.classList.add('show')
}
function hide_canvas() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.remove('show')
overlay.classList.remove('show')
}
</script>
<div class="off-canvas-content">
<div class="columns">
<div class="column col-12 col-lg-12">
<div class="book-navbar">
<!-- For Responsive Layout -->
<header class="navbar">
<section class="navbar-section">
<a onclick="open_sidebar()">
<i class="icon icon-menu"></i>
</a>
</section>
</header>
</div>
<div class="book-content" style="max-width: 960px; margin: 0 auto;
overflow-x: auto;
overflow-y: hidden;">
<div class="book-post">
<p id="tip" align="center"></p>
<div><h1>060 案例 订单核心流程的四色建模</h1>
<p>我们以电商系统的订单流程为例演练一下通过四色建模法帮助我们获得领域分析模型的过程。基于前面对四色建模法的介绍要识别时标型对象需要先梳理出业务流程尤其是核心的业务流程。电商系统的订单流程描述了从订单产生到交易结束的整个过程覆盖了电子商城E-Mall、仓库管理WMS与物流管理系统TMS等多个系统之间的业务流转。订单流程通常分为正向流程与逆向流程。从生成订单开始由买家发起购物付款—仓库发货不针对虚拟商品—用户收货为正向流程若买家对所购商品不满意则由买家发起退货申请—仓库收货—退款处理流程为逆向流程。为简便起见本案例仅考虑正向订单流程如下图所示</p>
<p><img src="assets/eb1121f0-b6c2-11e9-bada-434c712b2f35" alt="51764615.png" /></p>
<p>遵循四色建模法对业务流程进行梳理时,重要的不仅仅是保证业务流程的完整性,同时还需要站在运营者和管理者的角度,判断哪些流程步骤会<strong>影响到运营与管理</strong>。对于电商系统来说,订单自身的每次状态变化都与买家的用户体验息息相关,如果缺少订单,就会对商城的运营管理产生直接影响。支付行为与账务有关,如果缺少支付信息,就无法完成账目的对账,对商城的财务审计与财务收支统计产生影响。在追踪订单状态的过程中,因为缺货引起的订单拆分,订单打包与商品配送等过程,与买家消费状况、库存管理和物流跟踪有着直接联系,直接影响买家购物。这正是图中一部分步骤被标记为灰色的核心步骤的缘由。</p>
<p>我一再强调,领域分析建模工作需得团队与领域专家进行充分交流。倘若建模分析师无法准确地识别这些核心步骤,就说明他缺乏管理和运营的视角,不具备模型分析必须的领域知识,这正是领域专家乃至企业管理者介入建模环节的时机。领域分析建模的建模原则之一,就是一定要<strong>与理解业务的领域专家共同建模</strong></p>
<p>一旦识别出业务流程的核心步骤,接下来就应该寻找:这些核心步骤会留下值得记录的“足迹”吗?倘若缺乏该记录,是否会对运营与管理产生影响?结合时标型对象的特征,我们要去发现那些隐藏在业务流程背后的领域概念,它们具有:</p>
<ul>
<li>“事实”的不可变更性:它是过去某个时刻或时段发生的事实</li>
<li>“责任”的可追溯性:它记录的数据是决策者和管理者关注的信息</li>
</ul>
<p>在四色建模过程中,我们遵循时标型对象的特征来不断发起和领域专家之间的问答,当然也可以是设计者自己的自问自答。提问的模式遵循:</p>
<ul>
<li>针对核心步骤 <code>&lt;S&gt;</code>,是否需要记录该步骤行为的结果 <code>&lt;R&gt;</code></li>
<li>如果缺少了结果 <code>&lt;R&gt;</code>,会否对运营与管理产生影响?</li>
</ul>
<p>第一个问题是正向的,带我们思考,以<strong>驱动</strong>出可能隐藏在业务流程背后的关键概念;第二个问题是反向的,用以<strong>验证</strong>挖掘出来的这个业务概念,是否真的属于领域分析模型中的核心概念?这一正反两个方向的分析驱动力如下图所示:</p>
<p><img src="assets/039f24b0-b6c3-11e9-bada-434c712b2f35" alt="img" /></p>
<p>以“支付”业务步骤为例,当买家对订单进行支付时,需要记录支付的结果吗?显然需要!那么这个结果应该用什么领域概念来描述它?是“支付记录”、“网银记录”、“交易记录”还是“支付凭证”?如果不能确定概念的名称,就需要结合领域知识来梳理和辨别,然后将其作为<strong>统一语言的候选</strong>。假设我们确定为“支付凭证”,然后再反过来思考,如果没有支付凭证,会影响到电商业务的运营与管理吗?答案是肯定的。例如考虑买家退货场景:如果缺少支付凭证,将无法判断该买家是否为订单成功进行了支付,也不知道支付发生的时间,金额以及支付方式。不知道这些信息,就无法满足退货退款的需求。当电商需要与卖家进行结算,又或者需要统计每日或每月的营收情况时,缺少支付凭证记录的信息,这些运营管理行为也将无法完成。</p>
<p>经过这样的双重判断,既帮助我们挖掘出隐藏的领域分析模型概念,又能够对该概念进行正确性验证,使得我们的领域分析模型在变得越来越丰富的同时,还能保证模型的正确性。而概念名称的确认,也是维护统一语言的良机。通过这样的分析与思考过程,我们由前述流程可获得如下标记为粉红色的时标型对象:</p>
<p><img src="assets/100a4fe0-b6c3-11e9-9502-4d2d1c5bfcd4" alt="56146079.png" /></p>
<p>在识别时标型对象时针对“下订单”核心步骤可以获得“订单”对象。这个对象是时标型对象吗订单记录的数据与运营管理直接有关它也确实是关键行为在确定时间产生的结果订单与代表物的商品、代表人的客户具有关联关系这些都是时标型对象的特征。唯一不同之处在于订单并非不可变更的“事实”随着一些关键行为的产生订单状态会随之发生变更例如随着“订单配送”行为的发生同一个订单的状态就从“Granted”变更为“Shipped”。</p>
<p>如果要绝对地追求时标型对象的不可变性,或许订单不应该归入到时标型对象中。但我认为,在识别出订单对象后,继续纠结于它是时标型对象还是 PPT 对象并无意义。正如我在前面所说:“在领域分析建模过程中,进行分析建模的“初心”并非要识别出时标型对象,而是识别能够完整表达领域知识的领域概念!”因此,在运用四色建模法时,时刻谨记我们建模的目标是<strong>寻找正确的领域对象</strong>不要受到领域对象类型的干扰。当建模过程从分析活动进入到设计活动四色建模法的这四种对象类型都将标记为领域驱动设计中的设计要素即确定这些对象到底是实体Entity还是值对象Value Object</p>
<p>当然,理解时标型对象的特征是非常有必要的,掌握这些知识有助于建模人员发现时标型对象。还是以订单为例,虽然订单状态会发生变化,但它的的确确是过去某个时间产生的对管理和运营产生影响的数据记录。若将其视为时标型对象,则说明对“责任的追溯”要高于“事实的不可变更”。此外,在理解所谓的“不变性”时,也不能太狭隘,而应理解为时标型对象关键属性的不可变。所谓“关键属性”,其实就是影响到管理与运营的属性,如订单的订单项、总金额、配送地址等。许多电商网站都不允许买家在提交订单之后,对订单进行修改。若需修改订单,只能是在取消订单之后,再次提交另一份订单。</p>
<p>在识别出时标型对象之后,还需要尽可能确定它们彼此之间的关系。在下图所示的时标型对象中,延期交货单、包裹存单与订单之间存在关联关系,这是因为管理者需要了解这些时标型对象来自于哪一个订单,以便于追溯;而配送单与订单却没有直接关联,虽然它仍然需要获得订单信息来满足追溯的需求,但这个信息可以直接从包裹存单中获得。事实上,在物流配送领域,确实无需考虑购买环节产生的订单信息。</p>
<p><img src="assets/1f603ef0-b6c3-11e9-bada-434c712b2f35" alt="img" /></p>
<p>一旦确定了时标型对象就可以识别代表“参与方Party/地点Place/物品Thing”的 PPT 对象来丰富这个骨干的基本模型。如前所述,时标型对象不可能是孤立的,也不可能凭空产生,一定会与 PPT 对象产生关系。当时标型对象需要满足运营和管理的需要而被追溯时,可能就需要 PPT 对象提供信息。寻找 PPT 对象可以参考业务需求描述中的名词概念,也可以看看产生时标型对象的行为究竟会与什么对象有关。</p>
<p>如果 PPT 对象作为参与方,意味着该对象是业务流程中核心步骤的参与方,只要该参与方的信息将用于追溯时标型对象,就需要建立该对象与时标型对象之间的关系。例如,当客户下订单时,会有账户作为参与方执行支付,则支付凭证就会与账户存在关联关系;员工作为参与者执行审核订单、退款和订单打包行为,因此退款记录、审核结果和包裹存单都将与“员工”实体存在关联。</p>
<p>对于代表地点的 PPT 对象,相对比较特殊,只有那些明确需要地点信息的时标型对象才需要它,例如配送单就需要“配送地址”对象,否则就无法知道配送的目的地。当然,不要将地点与地址混为一谈。例如销售领域中的销售渠道、区域,物流领域中的路线、站点都是代表地点的 PPT 对象。</p>
<p>代表“物品”的 PPT 对象往往会作为业务流程中核心步骤的被操作对象,并为时标型对象提供必要的信息,以利于信息的追溯。例如订单需要“商品”信息,否则无法说明买家到底<strong>购买</strong>了哪些商品;延期交货单需要“商品”信息,这样才能标记哪些商品<strong>缺货</strong>;包裹存单需要“商品”信息,可以为<strong>库存</strong>打包提供正确的商品参考信息;配送单也需要“商品”信息,只有这样才能对整个<strong>配送</strong>过程进行监管。同时配送单还需要“承运商”的信息以便于对配送单进行跟踪明确配送的责任方。PPT 对象在四色建模法中用绿色标签来表示,因而可以得到如下的订单分析模型:</p>
<p><img src="assets/3782fcc0-b6c3-11e9-96e0-d90b4d8f55a3" alt="82497284.png" /></p>
<p>在确定 PPT 对象与时标型对象之间的关系时,可能出现同一个 PPT 对象与多个时标型对象之间存在关联的情况。这恰好是角色Role对象出现的时机。例如上述模型就反复出现了多个“商品”对象。我们可否将这些“商品”概念合并为一个呢仔细分析这些商品对象虽然名称相同但对于不同的时标型对象却体现了不同的业务关系实际代表不同的领域概念。例如订单关联的商品代表了一种购买关系此时的商品其实是已购商品延期交货单中的商品表示目前缺货代表缺货商品包裹存单的商品属于库存配送单的商品其实是物流运输过程中的货物。</p>
<p>当时标型对象与代表人或组织的 PPT 对象存在关联关系时,引入角色对象更为常见。事实上,这个角色对象才是触发业务行为产生时标型对象的真正发起人。例如,当员工与审核结果产生关系时,需要由“审核人”这个角色来执行审核订单操作;当员工与包裹存单产生关系时,由“配货人”完成订单打包操作。</p>
<p>角色对象用黄色标签表示,于是模型演进为:</p>
<p><img src="assets/4a8af750-b6c3-11e9-bada-434c712b2f35" alt="82537966.png" /></p>
<p>角色对象其实体现了相同的 PPT 对象在不同上下文中代表的不同业务含义,因此可以结合战略设计的限界上下文来理解。例如已购商品属于购买上下文,库存商品属于库存上下文,货物属于物流上下文。这也正是限界上下文的价值,即用于维护上下文边界内的模型统一。</p>
<p>在建模过程中,我们可以将战略设计和战术设计融合起来。如果在先启阶段已经初步识别了限界上下文,那么在针对领域进行建模时,可以将限界上下文引入到模型中,作为领域模型的边界;当我们在建模时,倘若发现存在领域概念混乱或重复的情况,例如订单建模过程中针对员工和商品引入的角色对象,又可以反过来帮助我们检测之前的限界上下文识别是否存在问题,并及时进行改进,从而形成我在《领域驱动设计实践(战略篇)》第 01 课《领域驱动设计概览》中提到的“演进的领域驱动设计过程”,即:</p>
<blockquote>
<p>战略设计会控制和分解战术设计的边界与粒度,战术设计则以实证角度验证领域模型的有效性、完整性与一致性,进而以演进的方式对之前的战略设计阶段进行迭代,从而形成一种螺旋式上升的迭代设计过程。</p>
</blockquote>
<p>最后是描述对象。如前所述,描述对象是对 PPT 对象的描述。在 PPT 对象已经被识别出来的前提下,判断这些 PPT 对象是否还需要做进一步的说明。显然,如果要吸引顾客购买商品,需要对商品信息做进一步补充和说明;同理,顾客和承运商也需要添加描述:</p>
<p><img src="assets/5ea217f0-b6c3-11e9-bada-434c712b2f35" alt="82620980.png" /></p>
<p>四色建模法的核心是时标型对象,它们也是领域分析模型中最有价值的领域概念。在四色建模过程中,时刻牢记时标型对象的特征,从运营和管理角度去理解是其根本。通俗地说,四色建模法就是要围绕着“<strong></strong>”进行模型识别。时标型对象会直接或间接影响到企业的收入和支出。正如徐昊所说,四色建模法源自“财务是业务通用语言”的领域风暴。每个时标型对象本质上都是<strong>凭证</strong>,包括原始凭证和应收凭证等,这些都是财务的业务语言。</p>
<p>不管领域怎么变化,企业的运营模式和对凭证(或者说票据)的关注基本上是不变的。若能抓住时标型对象的这些特征,就可以让领域建模不再跟着感觉走,而是基于运营角度建立领域分析模型的骨架,剩下的就是逐渐填充和丰富的过程。显然,这是一种相对可以落地的领域分析建模方法。</p>
<h3>分享交流</h3>
<p>我们为本课程付费读者创建了微信交流群,以方便更有针对性地讨论课程相关问题。入群方式请到第 6-1 课末尾添加小编的微信号并注明「DDD」。</p>
<p>阅读文章过程中有任何疑问随时可以跟其他小伙伴讨论,或者直接向作者提问(作者看到后抽空回复)。你的分享不仅帮助他人,更会提升自己。</p>
</div>
</div>
<div>
<div style="float: left">
<a href="/专栏/领域驱动设计实践(完)/059 四色建模法.md.html">上一页</a>
</div>
<div style="float: right">
<a href="/专栏/领域驱动设计实践(完)/061 事件风暴与业务全景探索.md.html">下一页</a>
</div>
</div>
</div>
</div>
</div>
</div>
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
</div>
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"70997e82093f3cfa","version":"2021.12.0","r":1,"token":"1f5d475227ce4f0089a7cff1ab17c0f5","si":100}' crossorigin="anonymous"></script>
</body>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NPSEEVD756"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'G-NPSEEVD756');
var path = window.location.pathname
var cookie = getCookie("lastPath");
console.log(path)
if (path.replace("/", "") === "") {
if (cookie.replace("/", "") !== "") {
console.log(cookie)
document.getElementById("tip").innerHTML = "<a href='" + cookie + "'>跳转到上次进度</a>"
}
} else {
setCookie("lastPath", path)
}
function setCookie(cname, cvalue) {
var d = new Date();
d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
var expires = "expires=" + d.toGMTString();
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
}
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i].trim();
if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
}
return "";
}
</script>
</html>