mirror of
https://github.com/zhwei820/learn.lianglianglee.com.git
synced 2025-09-17 08:46:40 +08:00
282 lines
22 KiB
HTML
282 lines
22 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>02 领域、子域、核心域、通用域和支撑域:傻傻分不清?.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="/专栏/DDD实战课/00 开篇词 学好了DDD,你能做什么?.md.html">00 开篇词 学好了DDD,你能做什么?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/DDD实战课/01 领域驱动设计:微服务设计为什么要选择DDD.md.html">01 领域驱动设计:微服务设计为什么要选择DDD</a>
|
||
</li>
|
||
<li>
|
||
<a class="current-tab" href="/专栏/DDD实战课/02 领域、子域、核心域、通用域和支撑域:傻傻分不清?.md.html">02 领域、子域、核心域、通用域和支撑域:傻傻分不清?</a>
|
||
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/DDD实战课/03 限界上下文:定义领域边界的利器">03 限界上下文:定义领域边界的利器</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/DDD实战课/04 实体和值对象:从领域模型的基础单元看系统设计.md.html">04 实体和值对象:从领域模型的基础单元看系统设计</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/DDD实战课/05 聚合和聚合根:怎样设计聚合?.md.html">05 聚合和聚合根:怎样设计聚合?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/DDD实战课/06 领域事件:解耦微服务的关键.md.html">06 领域事件:解耦微服务的关键</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/DDD实战课/07 DDD分层架构:有效降低层与层之间的依赖.md.html">07 DDD分层架构:有效降低层与层之间的依赖</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/DDD实战课/08 微服务架构模型:几种常见模型的对比和分析.md.html">08 微服务架构模型:几种常见模型的对比和分析</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/DDD实战课/09 中台:数字转型后到底应该共享什么?.md.html">09 中台:数字转型后到底应该共享什么?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/DDD实战课/10 DDD、中台和微服务:它们是如何协作的?.md.html">10 DDD、中台和微服务:它们是如何协作的?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/DDD实战课/11 DDD实践:如何用DDD重构中台业务模型?.md.html">11 DDD实践:如何用DDD重构中台业务模型?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/DDD实战课/12 领域建模:如何用事件风暴构建领域模型?.md.html">12 领域建模:如何用事件风暴构建领域模型?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/DDD实战课/13 代码模型(上):如何使用DDD设计微服务代码模型?.md.html">13 代码模型(上):如何使用DDD设计微服务代码模型?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/DDD实战课/14 代码模型(下):如何保证领域模型与代码模型的一致性?.md.html">14 代码模型(下):如何保证领域模型与代码模型的一致性?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/DDD实战课/15 边界:微服务的各种边界在架构演进中的作用?.md.html">15 边界:微服务的各种边界在架构演进中的作用?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/DDD实战课/16 视图:如何实现服务和数据在微服务各层的协作?.md.html">16 视图:如何实现服务和数据在微服务各层的协作?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/DDD实战课/17 从后端到前端:微服务后,前端如何设计?.md.html">17 从后端到前端:微服务后,前端如何设计?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/DDD实战课/18 知识点串讲:基于DDD的微服务设计实例.md.html">18 知识点串讲:基于DDD的微服务设计实例</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/DDD实战课/19 总结(一):微服务设计和拆分要坚持哪些原则?.md.html">19 总结(一):微服务设计和拆分要坚持哪些原则?</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/DDD实战课/20 总结(二):分布式架构关键设计10问.md.html">20 总结(二):分布式架构关键设计10问</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/DDD实战课/答疑:有关3个典型问题的讲解.md.html">答疑:有关3个典型问题的讲解</a>
|
||
</li>
|
||
<li>
|
||
|
||
<a href="/专栏/DDD实战课/结束语 所谓高手,就是跨过坑和大海.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>02 领域、子域、核心域、通用域和支撑域:傻傻分不清?</h1>
|
||
<p>你好,我是欧创新。</p>
|
||
<p>DDD 的知识体系提出了很多的名词,像:领域、子域、核心域、通用域、支撑域、限界上下文、聚合、聚合根、实体、值对象等等,非常多。这些名词,都是关键概念,但它们实在有些晦涩难懂,可能导致你还没开始实践 DDD 就打起了退堂鼓。因此,在基础篇中,我希望能带着你一起做好实践前的准备工作。</p>
|
||
<p>除此之外,我想说的是,这些名词在你的微服务设计和开发过程中不一定都用得上,但它可以帮你理解 DDD 的核心设计思想和理念。而这些思想和理念,在 IT 战略设计、业务建模和微服务设计中都是可以借鉴的。</p>
|
||
<p>那么,从这讲开始,我就会围绕以上这些 DDD 关键概念进行讲解,帮助你彻底理清它们与微服务的关系,了解它们在微服务设计中的作用。今天我们重点了解 DDD 的领域、子域、核心域、通用域和支撑域等重要概念。</p>
|
||
<h2>如何理解领域和子域?</h2>
|
||
<p>我们先看一下汉语词典中对领域的解释:“领域是从事一种专门活动或事业的<strong>范围</strong>、部类或部门。”百度百科对领域的解释:“领域具体指一种特定的<strong>范围</strong>或区域。”</p>
|
||
<p>两个解释有一个共同点——范围。对了!领域就是用来确定范围的,范围即边界,这也是 DDD 在设计中不断强调边界的原因。</p>
|
||
<p>在研究和解决业务问题时,DDD 会按照一定的规则将业务领域进行细分,当领域细分到一定的程度后,DDD 会将问题范围限定在特定的边界内,在这个边界内建立领域模型,进而用代码实现该领域模型,解决相应的业务问题。简言之,DDD 的领域就是这个边界内要解决的业务问题域。</p>
|
||
<p>既然领域是用来限定业务边界和范围的,那么就会有大小之分,领域越大,业务范围就越大,反之则相反。</p>
|
||
<p>领域可以进一步划分为子领域。我们把划分出来的多个子领域称为子域,每个子域对应一个更小的问题域或更小的业务范围。</p>
|
||
<p>我们知道,DDD 是一种处理高度复杂领域的设计思想,它试图分离技术实现的复杂度。那么面对错综复杂的业务领域,DDD 是如何使业务从复杂变得简单,更容易让人理解,技术实现更容易呢?</p>
|
||
<p>其实很好理解,DDD 的研究方法与自然科学的研究方法类似。当人们在自然科学研究中遇到复杂问题时,通常的做法就是将问题一步一步地细分,再针对细分出来的问题域,逐个深入研究,探索和建立所有子域的知识体系。当所有问题子域完成研究时,我们就建立了全部领域的完整知识体系了。</p>
|
||
<p><img src="assets/1628872456555.png" alt="png" /></p>
|
||
<p>我们来看一下上面这张图。这个例子是在讲如何给桃树建立一个完整的生物学知识体系。初中生物课其实早就告诉我们研究方法了。<strong>它的研究过程是这样的。</strong></p>
|
||
<p>第一步:确定研究对象,即研究领域,这里是一棵桃树。</p>
|
||
<p>第二步:对研究对象进行细分,将桃树细分为器官,器官又分为营养器官和生殖器官两种。其中营养器官包括根、茎和叶,生殖器官包括花、果实和种子。桃树的知识体系是我们已经确定要研究的问题域,对应 DDD 的领域。根、茎、叶、花、果实和种子等器官则是细分后的问题子域。这个过程就是 DDD 将领域细分为多个子域的过程。</p>
|
||
<p>第三步:对器官进行细分,将器官细分为组织。比如,叶子器官可细分为保护组织、营养组织和输导组织等。这个过程就是 DDD 将子域进一步细分为多个子域的过程。</p>
|
||
<p>第四步:对组织进行细分,将组织细分为细胞,细胞成为我们研究的最小单元。细胞之间的细胞壁确定了单元的边界,也确定了研究的最小边界。</p>
|
||
<p>这里先剧透一点聚合、聚合根、实体以及值对象的内容,我还会在 [第 04 讲] 和 [第 05 讲] 中详细讲解。</p>
|
||
<p>我们知道细胞核、线粒体、细胞膜等物质共同构成细胞,这些物质一起协作让细胞具有这类细胞特定的生物功能。在这里你可以把细胞理解为 DDD 的聚合,细胞内的这些物质就可以理解为聚合里面的聚合根、实体以及值对象等,在聚合内这些实体一起协作完成特定的业务功能。这个过程类似 DDD 设计时,确定微服务内功能要素和边界的过程。</p>
|
||
<p>这里总结一下,就是说每一个细分的领域都会有一个知识体系,也就是 DDD 的领域模型。在所有子域的研究完成后,我们就建立了全域的知识体系了,也就建立了全域的领域模型。</p>
|
||
<p>上面我们用自然科学研究的方法,说明了领域可以通过细分为子域的方法,来降低研究的复杂度。现在我们把这个话题再切换到业务领域,对比验证下,二者的细分过程是否是一致的。这里以我从事的保险行业为例。</p>
|
||
<p>保险是个比较大的领域,很早以前的保险核心系统把所有的功能都放在一个系统里来实现,这个系统就是我们常说的单体系统。后来单体系统开始无法适应保险业务的发展,因此保险公司开始了中台转型,引入分布式微服务架构来替换原来的单体系统。而分布式微服务架构就需要划分业务领域边界,建立领域模型,并实现微服务落地了。</p>
|
||
<p>为实现保险领域建模和微服务建设,我们可以根据业务关联度以及流程边界将保险领域细分为:承保、收付、再保以及理赔等子域,而承保子域还可以继续细分为投保、保全(寿险)、批改(财险)等子子域。</p>
|
||
<p>在投保这个限界上下文内可以建立投保的领域模型,投保的领域模型最后映射到系统就是投保微服务。这就是一个保险领域的细分和微服务的建设过程。</p>
|
||
<p>那么你可能会说,我不是保险行业的人,我怎么理解这个过程呢?我认为,不同行业的业务模型可能会不一样,但领域建模和微服务建设的过程和方法基本类似,其核心思想就是将问题域逐步分解,降低业务理解和系统实现的复杂度。</p>
|
||
<h2>如何理解核心域、通用域和支撑域?</h2>
|
||
<p>在领域不断划分的过程中,领域会细分为不同的子域,子域可以根据自身重要性和功能属性划分为三类子域,它们分别是:核心域、通用域和支撑域。</p>
|
||
<p>决定产品和公司核心竞争力的子域是核心域,它是业务成功的主要因素和公司的核心竞争力。没有太多个性化的诉求,同时被多个子域使用的通用功能子域是通用域。还有一种功能子域是必需的,但既不包含决定产品和公司核心竞争力的功能,也不包含通用功能的子域,它就是支撑域。</p>
|
||
<p>这三类子域相较之下,核心域是最重要的,我们下面讲目的的时候还会以核心域为例详细介绍。通用域和支撑域如果对应到企业系统,举例来说的话,通用域则是你需要用到的通用系统,比如认证、权限等等,这类应用很容易买到,没有企业特点限制,不需要做太多的定制化。而支撑域则具有企业特性,但不具有通用性,例如数据代码类的数据字典等系统。</p>
|
||
<p><strong>那为什么要划分核心域、通用域和支撑域,主要目的是什么呢?</strong></p>
|
||
<p>还是拿上图的桃树来说吧。我们将桃树细分为了根、茎、叶、花、果实和种子等六个子域,那桃树是否有核心域?有的话,到底哪个是核心域呢?</p>
|
||
<p>不同的人对桃树的理解是不同的。如果这棵桃树生长在公园里,在园丁的眼里,他喜欢的是“人面桃花相映红”的阳春三月,这时花就是桃树的核心域。但如果这棵桃树生长在果园里,对果农来说,他则是希望在丰收的季节收获硕果累累的桃子,这时果实就是桃树的核心域。</p>
|
||
<p>在不同的场景下,不同的人对桃树核心域的理解是不同的,因此对桃树的处理方式也会不一样。园丁更关注桃树花期的营养,而果农则更关注桃树落果期的营养,有时为了保证果实的营养供给,还会裁剪掉疯长的茎和叶(通用域或支撑域)。</p>
|
||
<p>同样的道理,公司在 IT 系统建设过程中,由于预算和资源有限,对不同类型的子域应有不同的关注度和资源投入策略,记住好钢要用在刀刃上。</p>
|
||
<p>很多公司的业务,表面看上去相似,但商业模式和战略方向是存在很大差异的,因此公司的关注点会不一样,在划分核心域、通用域和支撑域时,其结果也会出现非常大的差异。</p>
|
||
<p>比如同样都是电商平台的淘宝、天猫、京东和苏宁易购,他们的商业模式是不同的。淘宝是 C2C 网站,个人卖家对个人买家,而天猫、京东和苏宁易购则是 B2C 网站,是公司卖家对个人买家。即便是苏宁易购与京东都是 B2C 的模式,他们的商业模式也是不一样的,苏宁易购是典型的传统线下卖场转型成为电商,京东则是直营加部分平台模式。</p>
|
||
<p>商业模式的不同会导致核心域划分结果的不同。有的公司核心域可能在客户服务,有的可能在产品质量,有的可能在物流。在公司领域细分、建立领域模型和系统建设时,我们就要结合公司战略重点和商业模式,找到核心域了,且重点关注核心域。</p>
|
||
<p>如果你的公司刚好有意向转型微服务架构的话,我建议你和你的技术团队要将核心域的建设排在首位,最好是有绝对的掌控能力和自主研发能力,如果资源实在有限的话,可以在支撑域或者通用域上想想办法,暂时采用外购的方式也未尝不可。</p>
|
||
<h2>总结</h2>
|
||
<p>领域的核心思想就是将问题域逐级细分,来降低业务理解和系统实现的复杂度。通过领域细分,逐步缩小微服务需要解决的问题域,构建合适的领域模型,而领域模型映射成系统就是微服务了。</p>
|
||
<p>核心域、支撑域和通用域的主要目标是:通过领域划分,区分不同子域在公司内的不同功能属性和重要性,从而公司可对不同子域采取不同的资源投入和建设策略,其关注度也会不一样。</p>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<div style="float: left">
|
||
<a href="/专栏/DDD实战课/01 领域驱动设计:微服务设计为什么要选择DDD.md.html">上一页</a>
|
||
</div>
|
||
<div style="float: right">
|
||
<a href="/专栏/DDD实战课/03 限界上下文:定义领域边界的利器">下一页</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":"70996eda1c0b3d60","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>
|