mirror of
https://github.com/zhwei820/learn.lianglianglee.com.git
synced 2025-09-17 08:46:40 +08:00
1093 lines
50 KiB
HTML
1093 lines
50 KiB
HTML
<!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>059 四色建模法.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 class="current-tab" href="/专栏/领域驱动设计实践(完)/059 四色建模法.md.html">059 四色建模法.md.html</a>
|
||
|
||
|
||
</li>
|
||
|
||
<li>
|
||
|
||
|
||
<a 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>059 四色建模法</h1>
|
||
|
||
<p>或许正是认识到彩色 UML 在建模过程的不足之处,ThoughtWorks 的徐昊才在彩色 UML 基础之上提出了自己的“四色建模法”。可考的四色建模法资料仅见于徐昊在 InfoQ 上发表的文章<a href="https://www.infoq.cn/article/xh-four-color-modeling">运用四色建模法进行领域分析</a>。在这篇文章中,徐昊回答了建模活动的一个关键问题:怎么才能保证建模的正确性?徐昊认为:</p>
|
||
|
||
<blockquote>
|
||
|
||
<p>首先我们需要明白建模的目的是什么?如果仅仅是为了描画问题,那么并没有什么对错之分——仅仅是立场和角度的差别;而如果是为了企业业务系统而进行建模,那么这个问题应该变为:如何保证模型能够支撑企业的运营?</p>
|
||
|
||
</blockquote>
|
||
|
||
<p>不要小看这个问题的改变,它实际上是对建模视角的调整与切换。<strong>从企业运营(注意,这里写到的是运营而不是运维,一字之差,天壤之别)的角度思考与识别模型</strong>,才是四色建模法的核心和精髓。这是我在请教了徐昊之后,再次阅读这篇文章后的一个体会。</p>
|
||
|
||
<h3>如何理解四色建模法</h3>
|
||
|
||
<p>徐昊认为,建立企业业务系统的关键目的是满足企业管理者和决策者的诉求。这个诉求就是满足对企业运营的需要。因此,针对企业业务系统建立的模型也需要满足这一诉求。用徐昊的话说,四色建模法并不是对领域建模,而是对企业的运营建模。企业的运营比领域更重要,也更加的稳定。</p>
|
||
|
||
<p>因此,理解四色建模法可以从小处说,就是从管理和运营的角度,抓住运营管理人员最为关注的基础和核心,即企业运营的基础:财务和会计。无论是法律上的诉求,还是财务管理的要求,核心的模型就是<strong>凭证</strong>。在四色建模过程中,我们识别出来的时标型对象,其实就是为此目的提供的一个个凭证。这些凭证以某种数据的形式留下足迹,并按照时间顺序排列起来,可以帮助我们追溯业务的运营或对财务的审计。</p>
|
||
|
||
<p>从大处说,就是从企业系统的“步速”策略来分析核心领域,即遵循 Gatner 提出的 Pace-Layered Application Strategy。这是 Gatner 在 2016 年提出的一份报告,它按照“步速”将企业的应用系统划分为三个层次:SoR(Systems of Record)、SoD(Systems of Differentiation)和 SoI(Systems of Innovation)。处于不同 Pace-Layered 的系统,构建目标并不相同,支持运营和管理的关注点也不相同,故而变化的速率也不相同,需要为其制定不同的企业架构策略,采用不同的技术架构、管理流程乃至于投资策略。这三个层次及其特征如下图所示:</p>
|
||
|
||
<p><img src="assets/1f934160-b6b9-11e9-bada-434c712b2f35" alt="38067624.png" /></p>
|
||
|
||
<p>(图片来自 Gartner)</p>
|
||
|
||
<p><strong>说明:</strong></p>
|
||
|
||
<p>Gartner 认为 SoR 的变化速率非常缓慢,系统运行的生命周期达到十年以上,充分体现了运营模式的不变性。这正是四色建模法善于解决的领域,也是它关注的核心。</p>
|
||
|
||
<p>当然,领域驱动设计也提倡对领域进行划分,将那些业务复杂且对系统成功具有关键意义的内容归入核心领域(Core Domain),作为系统最有价值的部分。Eric Evans 建议:“为了使领域模型成为有价值的资产,必须整齐地梳理出模型的真正核心,并完全根据这个核心来创建应用程序的功能。……让最有才能的人来开发核心领域。”</p>
|
||
|
||
<p>但是,四色建模法与领域驱动设计对核心领域的判断标准并不相同。领域驱动设计是从<strong>价值</strong>的角度来划分核心领域和子领域,Eric 甚至认为:“如果某个设计部分需要保密以便保持竞争优势,那么它就是你的核心领域。”这是一种对领域的纵向切分。四色建模法则不然,它是从<strong>企业运营和管理</strong>的角度进行划分,可以认为是对领域的横向切分。因为企业运营贯穿业务流程的始终,只要业务动作产生的结果影响到企业的运营,都将作为一种财务的凭证而被记录下来,作为时标型对象加入到四色建模法获得的模型中。这种横向切分的方式,正好与 Pace-Layered 的分层原则契合。本质上,四色建模法获得的并非领域模型,而是<strong>企业运营模型</strong>。当然,我们也可以将企业的运营视为一种领域,那么企业运营模型也可视为是领域模型的一部分了。</p>
|
||
|
||
<h3>四色建模法的演化</h3>
|
||
|
||
<p>四色建模法基本继承了彩色 UML 架构型的划分,但它对于各个架构型却有自己独到的理解。整体来看,它特别强调了时标型对象的重要性,理清了角色架构型与描述架构型的模糊定义,让这两个架构型变得更为简单,容易识别。至于 PPT 架构型,在四色建模法中被命名为实体(Entity)。由于实体这一词语在软件行业中被广泛运用,在领域驱动设计中也有自己特殊的含义,为了避免混淆,也为了更容易理解,我仍然保留彩色 UML 的架构型定义。因此,四色建模法代表的领域对象类型分别为:</p>
|
||
|
||
<ul>
|
||
|
||
<li>时标型(Moment-Interval)对象:具有可追溯性的记录运营或管理数据的时刻或时段对象,用粉红色表示</li>
|
||
|
||
<li>PPT(Party/Place/Thing)对象:代表参与到流程中的参与方/地点/物,用绿色表示</li>
|
||
|
||
<li>角色(Role)对象:在时标型对象与 PPT 对象(通常是参与方)之间参与的角色,用黄色表示</li>
|
||
|
||
<li>描述(Description)对象:对 PPT 对象的一种补充描述,用蓝色表示</li>
|
||
|
||
</ul>
|
||
|
||
<p>四色建模法将时标型对象视为建模的起点,自然亦是搭建整个领域分析模型的骨架。这就像八股文的破题,要是题意理解偏了,纵使整篇文章起承转合一气呵成,文字写得花团锦簇,最终也只能是名落孙山的下场。寻找时标型对象,就是破题。那么,什么才是时标型对象呢?</p>
|
||
|
||
<h4>时标型对象</h4>
|
||
|
||
<p>仍然在《<a href="https://www.infoq.cn/article/xh-four-color-modeling">运用四色建模法进行领域分析</a>》这篇文章,徐昊谈到了自己对时标型对象的理解:</p>
|
||
|
||
<blockquote>
|
||
|
||
<p>任何业务事件都会以某种数据的形式留下足迹。我们对于事件的追溯可以通过对数据的追溯来完成。……(我们虽然)无法回到从前去看看到底发生了什么,但是却可以在单据的基础上,一定程度地还原当时事情发生的场景。当我们把这些数据的足迹按照时间顺序排列起来,我们几乎可以清晰地推测出这个在过往的一段时间内到底发生了那些事情。</p>
|
||
|
||
</blockquote>
|
||
|
||
<p>为什么在企业业务系统中需要记录这些业务事件呢?为什么我们需要对这些事件进行追溯呢?目的就是要支撑企业的管理和运营,这事实上也是我们开发企业业务系统主要解决的问题域。这就给了我们以启发,那就是在进行领域分析建模时,要<strong>从运营管理的角度去建模</strong>,从而建立一个能够支撑企业运营和管理的模型,而时标型对象就是模型中的关键概念。因此,我们需要抓住时标型对象的特征:</p>
|
||
|
||
<ul>
|
||
|
||
<li>时标型对象是支撑运营体系关键流程的执行结果;</li>
|
||
|
||
<li>时标型对象是过去某个时刻或时段发生的事实(Fact);</li>
|
||
|
||
<li>时标型对象记录的数据是决策者和管理者关注的信息,满足对责任的可追溯性;</li>
|
||
|
||
<li>时标型对象记录的数据是为了满足财务和法律的需求,倘若缺失,会影响到参与方的权益和义务。</li>
|
||
|
||
</ul>
|
||
|
||
<p>虽然四色建模法以时标型对象为建模的起点,但并非说明时标型对象最容易发现和识别;恰恰相反,比诸于 PPT 对象或角色对象,这些时标型对象往往隐藏领域逻辑中,不易被人发现。之所以要以时标型对象作为建模的起点,是因为它们恰好构成了整个领域分析模型的骨干,属于领域分析模型中的核心概念,不可缺失。</p>
|
||
|
||
<p>在寻找和识别时标型对象时,我们需要理解什么是“对管理与运营产生影响”。以乘坐公交汽车为例。从前乘坐公交汽车时,是有售票员售票的。乘客掏钱买票,售票员就需要把车票撕下来给乘客,同时留下票根。这个票根会作为财务结账与审计的重要凭证。记得在有些公交汽车上还贴有“售票员收钱不撕票属于贪污行为”的标语。这个时候的公交车票就属于时标型对象。当公交汽车渐渐普及为无人售票后,乘客买票的行为为刷卡所代替,没有乘车卡的乘客则以自动投币作为乘车的支付行为。为了减轻运营成本,公交公司以刷卡交易记录和投币箱中的币值金额作为结账和审计的凭证,公交车票仅仅作为乘客的报销凭证,由乘客自行决定是否需要。此时,公交车票就不再属于时标型对象了。原因就在于它对公交公司的管理与运营没有影响。</p>
|
||
|
||
<p>当然,我们也不要忘记时标型对象的特征属性,那就是时刻与时段。因此,在寻找时标型对象时,可以首先建立一条时间轴。任何一个业务流程,都会随着时间的推移连续产生不同的事件。根据运营或法律的需求,我们需要记录下这些事件的足迹,形成可追溯的记录。倘若这些记录是决策者和管理者关注的信息,缺失它们会影响到对责任的追溯,就可以将其识别为时标型对象。</p>
|
||
|
||
<p>例如,6 月 7 日,咨询师肖然接受了一个工作任务安排,要求在次日从成都出差到北京。于是,肖然需要预订去程的机票。以下是按照时间线记录下来的肖然在某旅行网站上留下的足迹:</p>
|
||
|
||
<ul>
|
||
|
||
<li>6 月 7 日 16 时 30 分,他使用自己的账户名登录到一家旅行网站:发起登录请求,输入密码后登录成功。登录请求与企业运营和管理无关,不需要识别为时标型对象。</li>
|
||
|
||
<li>6 月 7 日 16 时 32 分,他查询了 6 月 8 日从成都到北京的航班:发起航班查询请求,获得航班查询结果。航班查询结果与企业运营和管理无关,不需要识别为时标型对象。</li>
|
||
|
||
<li>6 月 7 日 16 时 40 分,他选定查询结果中的一个航班为去程,在输入乘客信息后并确认订单信息后,发起支付:<strong>提交</strong>机票预订订单,产生订单支付凭证,旅行网站向航空公司发起航班预订。订单、支付凭证影响到企业的财务和账目,航班预订影响到乘客的权益,直接或间接影响到了企业的运营和管理,识别时标型对象 Order、Payment 和 FlightSubscription。</li>
|
||
|
||
<li>6 月 7 日 17 时,旅行网站通知旅客订票成功:发送订票成功的通知信息,旅行网站完成订票支付交易。订票成功的通知信息与企业运营和管理无关,但机票会影响到乘客的权益,支付交易会影响到企业的财务账目,直接或间接影响到企业的运营和管理,识别时标型对象 AirTicket 和 Transaction。</li>
|
||
|
||
<li>6 月 7 日 18 时 20 分,因为行程有变,他取消了航班:取消订单并发起退款请求。订单状态变更影响到乘客和航空公司的权益,退款请求影响到企业的交易账目,直接或间接影响到企业的运营和管理,识别时标型对象 Order 和 RefundRequest。</li>
|
||
|
||
<li>6 月 7 日 18 时 22 分,旅行网管理员审核退票请求,审核通过并发起退款:取消订单的审核记录和退款记录影响到企业的审计与财务账目,直接或间接影响到了企业的运营和管理,识别时标型对象 Approvement 和 Refund。</li>
|
||
|
||
<li>6 月 7 日 18 时 23 分,订单取消成功:订单的状态变更影响到乘客和航空公司的权益,间接影响到企业的运营和管理,识别时标型对象 Order。</li>
|
||
|
||
<li>6 月 7 日 18 时 30 分,退款成功:退款操作为旅行网站与支付中介之间的一次交易,影响到乘客和企业的权益与财务账目,直接影响到企业的运营和管理,识别时标型对象 Transaction。</li>
|
||
|
||
</ul>
|
||
|
||
<p>整条时间轴需要记录的数据如下所示:</p>
|
||
|
||
<p><img src="assets/9bcf4d50-b6b9-11e9-96e0-d90b4d8f55a3" alt="58194234.png" /></p>
|
||
|
||
<p>通过时间轴识别时标型对象的关键有两点:</p>
|
||
|
||
<ul>
|
||
|
||
<li>根据某个时刻产生的业务动作,去寻找与该业务动作具有<strong>因果关系</strong>的领域对象。例如,在“确认订单并支付”这个业务动作中,订单的确认动作会导致订单对象 Order 的产生,而支付行为又会产生 Payment 对象。虽然是订票,但由于旅行网站并不真正具备航班票务购买的能力,仅仅是一个订票中介,因而需要发起对该航班的预定信息,从而识别出 FlightSubscription 对象。既然旅行网站并不能确定订票是否能够购买成功,因而在乘客发起支付时,并没有发起与银行或第三方交易机构的交易,故而 Transaction 对象是在订票成功之后才产生的。</li>
|
||
|
||
<li>判断该领域对象是否直接或间接影响到企业的运营和管理,从而确定是否为时标型对象。例如,登录和查询航班的行为虽然会产生登录信息和航班查询结果,但由于这些信息并不会影响到企业的运营和管理,因此不被识别为时标型对象。注意,搜索请求 SearchRequest 与退款请求 RefundRequest 之间的区别。缺失后者可能导致退款失败,就会影响到乘客的合法权益,丧失了责任追溯的能力。再次强调,我们要区分运营和运维的区别,前者面向的是管理者和决策者,后者面向的是 IT 系统的运维人员。这实际上也是可追溯事实和日志的差别,前者是运营角度需要记录的信息,后者是运维角度需要记录的信息,二者不可等同视之。</li>
|
||
|
||
</ul>
|
||
|
||
<p>虽然时刻和时段是时标型对象的特征属性,但是在四色建模法中,不能因为一个对象具有时间属性,就想当然地认为它是时标型对象。例如,航班 Flight 虽然具有计划起飞时间和计划降落时间、实际起飞时间和实际降落时间这两个时间段,但该时段属性与订票的业务活动并没有任何因果关系,并不会对企业的运营和管理产生影响,因而不属于时标型对象。实际上,它是与时标型对象相关联的 PPT 对象。</p>
|
||
|
||
<h4>四色建模法的建模过程</h4>
|
||
|
||
<p>四色建模法不仅进一步明确和简化了彩色 UML 提出的四种架构型对象,还总结了清晰的建模过程。在领域分析建模过程中,不是胡子眉毛一把抓,将所有类型的领域概念一股脑儿呈现出来,而是草蛇灰线,沿着一条若隐若现的建模路径由简至繁逐步显现模型的全貌。这条建模路径就是四色建模法的建模过程,它分为如下步骤:</p>
|
||
|
||
<ul>
|
||
|
||
<li>首先以满足管理和运营的需要为前提,寻找需要<strong>追溯的事件</strong>。</li>
|
||
|
||
<li>根据这些需要追溯,寻找足迹以及相应的<strong>时标型对象</strong>。</li>
|
||
|
||
<li>寻找时标对象周围的<strong>参与方/地点/物品</strong>。</li>
|
||
|
||
<li>从中抽象<strong>角色</strong>。</li>
|
||
|
||
<li>把一些信息用<strong>描述对象</strong>补足。</li>
|
||
|
||
</ul>
|
||
|
||
<p>四色建模法需要寻找追溯的事件,这与事件风暴的分析过程接近。事实上,二者在领域分析建模的活动中可以有机地融合。当然,由于时标型对象是支撑运营体系<strong>关键流程</strong>的执行结果,我们也可以事先确定系统的业务流程,然后寻找那些支撑运营体系的关键业务步骤。如下图所示的业务流程图,其中被标记为灰色的业务步骤就是我们识别时标型对象的关注点。针对这些业务步骤,从管理者或决策者的角度分别对它们提出以下问题:</p>
|
||
|
||
<ul>
|
||
|
||
<li>该业务步骤是否核心步骤?</li>
|
||
|
||
<li>业务步骤是否产生值得记录的可追溯结果?</li>
|
||
|
||
<li>倘若缺失该结果,会影响运营或管理吗?</li>
|
||
|
||
</ul>
|
||
|
||
<p><img src="assets/cc86c4a0-b6b9-11e9-9502-4d2d1c5bfcd4" alt="64352868.png" /></p>
|
||
|
||
<p>一旦确定该业务步骤产生的结果,且判定该结果会影响运营和管理,就说明该结果就是我们希望寻找到的隐藏在业务逻辑背后的重要领域概念。我们需要为这个概念命名,名称必须符合统一语言。倘若统一语言并未包含该概念(大多数时候,正是如此),则它的发现将极大地丰富领域模型与统一语言。</p>
|
||
|
||
<p>寻找时标型对象是四色建模的起点,一旦确定了这些时标型对象,就建立了整个领域分析模型的骨干。时标型对象在模型中往往不是孤立的,会与代表参与方/地点/物品的 PPT 对象建立关联。这个过程是对领域分析模型的一种丰富与补充。例如,时标型对象机票 AirTicket 与 PPT 对象航班 Flight 和旅客 Passenger,倘若机票缺少 Flight 的航班号和 Passenger 的姓名与身份证号,机票就是无效的。由于 PPT 对象明确地表达了人、组织、地点和物品,因此也可以相对容易地在业务需求描述中寻找到这些概念。在确定时标型对象与 PPT 对象之间的关系时,同时也可以帮助我们验证识别的时标型对象是否合理。</p>
|
||
|
||
<p>寻找角色对象,往往从时标型对象与 PPT 对象之间的关系着手。这些角色对象相当于是 PPT 对象参与到业务流程中所戴的帽子。如时标型对象“促销记录”与 PPT 对象“员工”之间存在关联,但做出促销决定的员工其实是“市场人员”,它就是员工在促销流程中所戴的帽子。四色建模法的角色对象与彩色 UML 的角色构造型在概念和职责上完全相同,但四色建模法更加突出它在时标型对象与 PPT 对象之间扮演的作用。在领域模型中,它往往被放到二者的关联线上:</p>
|
||
|
||
<p><img src="assets/fbce0a20-b6b9-11e9-9502-4d2d1c5bfcd4" alt="img" /></p>
|
||
|
||
<p>四色建模法的描述对象被限定为对 PPT 对象的描述。在已经确定了 PPT 对象的前提之下,我们只需要判断这些 PPT 对象是否还需要做进一步的说明。若需要,就引入对应的描述对象。例如 PPT 对象员工仅提供了员工的基本信息,那就由“员工详情”提供更加详细的信息:</p>
|
||
|
||
<p><img src="assets/04807310-b6ba-11e9-9502-4d2d1c5bfcd4" alt="img" /></p>
|
||
|
||
<p>在运用四色建模法时,固然时标型对象是建模的起点乃至核心,但在识别过程中,却不必纠结识别出来的概念究竟是否为时标型对象。若为此花费了太多建模时间,就有些得不偿失了。毕竟在领域分析建模过程中,进行分析建模的“初心”并非要识别出时标型对象,而是识别能够完整表达领域知识的领域概念!换言之,四色建模法是方法和过程,获得的领域分析模型才是我们的目标与结果。这与前述彩色 UML 的建模思路是一样的。</p>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<div>
|
||
|
||
<div style="float: left">
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/058 彩色 UML 与彩色建模.md.html">上一页</a>
|
||
|
||
</div>
|
||
|
||
<div style="float: right">
|
||
|
||
<a href="/专栏/领域驱动设计实践(完)/060 案例 订单核心流程的四色建模.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":"70997e7f6c013cfa","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>
|
||
|