news 2026/7/12 7:48:10

DDD 系列:领域、子域和限界上下文

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
DDD 系列:领域、子域和限界上下文

上一篇文章中,我们学习了贫血模型和充血模型,解决了“业务规则应该放在哪里”的问题。

但一个系统里还有订单、商品、库存、支付等很多业务。哪些对象应该放在一起,边界在哪里,光靠充血模型回答不了。

这一篇我们继续学习 DDD 战略设计中三个基础概念:领域、子域和限界上下文。

一、为什么要划分业务边界

我们平时最熟悉的是技术分层:

controller service mapper entity

这种分法解决的是代码放在哪里,却没有告诉我们业务应该怎么拆。

以电商系统为例,商品、订单、库存和物流都可能用到“商品”,但关注点完全不同:

  • 商品中心关心标题、类目和上下架状态;
  • 库存关心 SKU、可用库存和仓库;
  • 订单关心下单时的名称、成交价格和数量;
  • 物流关心重量、体积和配送要求。

如果所有模块共用一个Product,它很快就会变成谁都依赖、谁都不敢改的万能对象。

DDD 会先划分业务问题和模型的适用范围,再考虑代码、数据库和服务怎么落地。领域、子域和限界上下文,就是用来说明这些边界的。

二、领域与子域

领域对应Domain,简单来说,就是我们需要理解和解决的一块业务范围。

例如“电商”是一个领域,其中包含商品、订单、库存、支付和物流等业务问题。领域描述的是业务本身,不是 Java 包、数据库或技术框架。

领域的大小是相对的。从电商平台看,支付可能只是其中一部分;但对支付公司来说,支付本身又是一个大领域,还能继续拆成收单、退款、对账和清算。

一个大领域拆出的业务部分叫作子域。以电商领域为例,可以粗略拆成:

  • 商品子域;
  • 订单子域;
  • 库存子域;
  • 支付子域;
  • 物流子域。

每个子域解决一类相对完整的问题。订单负责交易生命周期,库存负责增加、锁定、扣减和释放,物流负责发货和运输跟踪。

子域也可以继续拆,但不要为了套 DDD 概念无限拆分。拆分的目标是让职责更清楚;如果拆完每块只剩一两个增删改查方法,反而会增加协作成本。

三、核心域、支撑域和通用域

不同子域对业务的价值不同。DDD 通常把它们分为三类,用来判断有限的人力应该投入在哪里。

类型说明示例
核心域体现主要业务竞争力,规则通常复杂且持续变化交易平台的订单撮合
支撑域支撑核心业务,并带有企业自己的规则商家结算、售后审核
通用域多数系统都会遇到,通常有成熟方案认证、短信、文件存储

核心域不是固定的模块名单。同样是电商平台,零售平台可能重视交易和营销,物流平台可能重视履约调度,二手平台可能重视验货和担保交易。

判断时可以问三个问题:它是不是主要价值来源,规则是否复杂且经常变化,市面上是否已有成熟通用方案。

这里说“通用”,不代表它不重要。认证和权限同样重要,只是它们通常不能体现当前业务与竞争对手的差异,可以优先使用成熟产品或公共能力。

分类也不是常量。随着公司战略变化,支撑域可能变成核心域,自研能力也可能被公共平台替代。

四、限界上下文与通用语言

子域划分了业务问题,但还需要给模型规定明确的适用范围,这就是限界上下文(Bounded Context)。

在一个限界上下文内,业务术语有明确含义,模型和规则保持一致,并由明确的模块或团队维护。

“限界”限制的是模型生效的范围,不是限制业务沟通。一个上下文中的模型出了边界,不应该被默认复用,其他上下文要按照自己的业务重新表达。

还是以“商品”为例:商品上下文维护标题和上下架状态;库存上下文使用库存项表达 SKU 和库存数量;订单上下文保存下单时的商品快照;物流上下文只关心发货属性。

这意味着我们不需要一个万能Product。订单上下文可以定义自己的OrderItem

publicclassOrderItem{/** 商品 SKU 标识,用于记录本次下单选择的具体规格 */privateLongskuId;/** 下单时的商品名称,商品改名不会影响历史订单 */privateStringproductName;/** 下单时的成交单价,用于保证订单金额可追溯 */privateBigDecimaldealPrice;/** 本次购买数量 */privateIntegerquantity;}

它只保留订单需要的信息,不必带上商品详情、搜索关键词等字段。不同上下文需要协作时,通过接口或消息传递必要数据,而不是直接修改对方的表和对象。

这里还要注意:限界上下文不等于微服务。

限界上下文是业务语义和模型边界,微服务是部署和运行边界。单体项目也能通过模块和接口建立多个限界上下文;两个服务如果共用表、互改数据,业务边界仍然是混乱的。

限界上下文内部还需要通用语言(Ubiquitous Language)。它要求业务、产品、开发和测试对关键术语有一致理解。

例如“取消订单”和“超时关闭”可能是两个动作,前置条件和后续处理也不同,代码就应该直接表达:

order.cancelByUser();order.closeByTimeout();

通用语言最终要落实到需求、类名、方法名、状态枚举、接口、事件和测试用例中,而不只是停留在会议里。

五、子域和限界上下文的关系

这两个概念很容易混淆,可以先记住:

  • 子域是对业务问题空间的划分,回答“有哪些不同的业务问题”;
  • 限界上下文是模型和解决方案生效的边界,回答“用哪套模型解决这些问题”。

理想情况下,一个子域通常对应一个限界上下文。但历史系统里,订单和库存可能还挤在同一个上下文;复杂的订单子域也可能拆成多个上下文。

这种对应关系还会受业务复杂度、团队职责和系统现状影响。划分的目标是得到清楚的业务边界,不是追求形式上的一一对应。

所以不能机械套用“一个子域等于一个限界上下文,更等于一个微服务”。真正需要检查的是:模型语义是否一致,规则是否有明确归属,边界之间是否通过清楚的契约协作。

六、从电商案例看边界如何落地

假设用户下单后,系统要锁定库存、处理支付并通知仓库发货。可以先按业务能力得到下面几个上下文:

限界上下文主要模型主要职责
商品上下文商品、类目、SKU维护展示和销售属性
订单上下文订单、订单项创建交易并维护订单生命周期
库存上下文库存项、锁定记录管理可用、锁定、扣减和释放
支付上下文支付单、退款单处理支付和退款状态
物流上下文发货单、物流轨迹管理发货和运输过程

下单时,订单上下文获取必要的商品信息,库存上下文判断并锁定库存,订单保存成交快照,支付上下文处理支付,支付结果再推动订单和履约流程。

这里的重点不是一定要使用接口还是消息,而是每个上下文只维护自己的规则和数据。

对于已经运行多年的 MVC 项目,可以先做四件事:

  1. 查找同名但含义不同的业务词,例如各种status和“完成”;
  2. 核实哪些表被多个模块直接修改,并结合调用链、SQL 和日志确认真实用途;
  3. 找出经常一起变化的代码,判断它们是否属于同一业务边界;
  4. 先明确模块职责和跨边界接口,再决定是否拆库、拆服务。

老系统里可能存在补偿任务和历史兼容逻辑,不能看到跨模块更新就直接删除。先核实现状,再逐步收紧边界更稳妥。

业务边界也不能只由开发人员根据代码目录决定。产品、业务、开发和测试需要一起确认流程和术语,否则技术上看着整齐,模型却可能与真实业务不符。

七、常见误区和验证方法

划分边界时,常见误区主要有这些:

  • 按数据库表划分子域;
  • 把一个实体当成一个限界上下文;
  • 用微服务数量证明业务边界合理;
  • 为了减少字段重复,让所有模块共用一套 Entity;
  • 只让开发人员根据代码目录划分业务边界。

边界划完后,可以检查:

  • 每个子域解决的问题能否用一句话说清楚;
  • 同一上下文内的关键术语是否只有一种含义;
  • 每条核心规则是否有明确归属;
  • 不同上下文是否直接修改对方数据;
  • 跨边界传递的是明确契约,还是内部对象;
  • 一个上下文变化时,是否经常要求其他上下文同步修改。

如果职责、术语和规则仍然说不清,边界就需要继续调整。领域知识本来就是逐步积累的,不必追求一次划到完美。

最后简单总结一下:

  • 领域是一块需要理解和解决的业务范围,子域是对它的继续拆分;
  • 核心域、支撑域和通用域体现不同的业务价值和投入优先级;
  • 限界上下文规定业务语言和模型生效的范围;
  • 子域属于问题空间,限界上下文属于模型和解决方案边界;
  • 划分边界要看真实业务、数据归属和调用关系,不能直接套数据库表或微服务。

到这里,我们已经从“业务规则放在哪里”,走到了“哪些业务应该放在一起”。下一篇继续学习战略设计,看看这些边界怎么进一步指导系统拆分。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/12 7:47:33

STM32F031C6与TLA2518构建高性价比多通道数据采集系统

1. 项目背景与核心需求解析在工业自动化、医疗设备和消费电子等领域,模拟信号到数字信号的可靠转换一直是嵌入式系统设计的关键环节。TLA2518作为德州仪器推出的一款12位精度、1MSPS采样率的8通道ADC芯片,配合STM32F031C6这款基于ARM Cortex-M0内核的微控…

作者头像 李华
网站建设 2026/7/12 7:47:24

C++集成Bartender实现自动化标签打印:COM接口调用与实战指南

1. 项目概述:当C遇上Bartender,自动化标签打印的“最后一公里”在工业制造、物流仓储、零售门店这些领域,标签打印是再日常不过的操作。从产品外箱的条码到仓库货架的标识,一张小小的标签背后,是数据流与物理世界的关键…

作者头像 李华
网站建设 2026/7/12 7:44:28

Unity Timeline自定义轨道开发指南:从原理到实战

1. 项目概述:为什么你需要关注Timeline自定义轨道? 如果你还在Unity项目里,把Timeline当成一个只能拖拽Animation Clip的“高级动画播放器”,那可能错过了它至少80%的威力。我见过太多项目,Timeline的用法停留在最基础…

作者头像 李华
网站建设 2026/7/12 7:44:03

BEV感知中MoE架构的模块化设计与落地实践

1. 项目概述:当BEV感知遇上MoE,清华团队把“分工协作”刻进了自动驾驶的神经网络里最近刷到“CBDES MoE”这个关键词的朋友,大概率是在自动驾驶技术社区、CV论文讨论组,或者高校实验室的晨会纪要里看到的。它不是某个新出的开源工…

作者头像 李华
网站建设 2026/7/12 7:43:24

真空低温烘干设备的深度解析及2026市场前景展望

真空低温烘干设备的基本原理与优势 工作原理解析 真空低温烘干设备的核心在于利用真空环境降低水分蒸发的温度。这种设备通过抽走空气中的压力,使水分在较低温度下迅速 evaporate,从而减少热量对产品的损伤。相比于常规技术,这种烘干方式能…

作者头像 李华
网站建设 2026/7/12 7:42:05

规模大的墙板工厂怎么选

说白了,这篇就是针对‘杭州桐庐墙板工厂哪家规模大’这个问题,把公开能查到的资料整理了一下,从位置、产品、服务范围这些角度列出来,不评价谁好谁坏,也不推荐买哪家。 桐庐川亿基材有限公司 这家公司就在桐庐本地&am…

作者头像 李华