3. 领域与子域:核心域、支撑域、通用域的定义与识别

在 DDD 战略设计中,领域(Domain)是组织要解决的业务问题空间。一个大型软件系统通常包含多个业务关注点,将这些关注点按业务价值与通用性拆分为更小的子域(Subdomain),是架构师的首要任务。本章将定义三种子域类型,并给出识别与划分的实操策略。

3.1 三种子域的定义与对比

根据业务的重要程度与通用性,子域分为三类:

类型 定义 业务价值 通用性 典型示例(电商)
核心域 系统最关键的、提供核心竞争力的业务逻辑 极高,直接决定产品差异 低,通常为自研 订单履约、定价引擎、推荐算法
支撑域 为核心域提供必要支持,但本身不构成核心竞争力 中等,缺少则无法运转 中,可自研或外包 库存管理、物流调度、客服工单
通用域 行业通用、无业务差异化的能力 低,不产生竞争优势 高,可直接采购或使用开源 用户认证、支付网关、邮件通知
识别口诀:“核心域决定生死,支撑域保障运转,通用域避免重复造轮子。”

3.2 核心域的识别方法

核心域是架构投资的重点,识别时需回答以下问题:

  • 业务差异点:如果没有这个模块,产品与竞品是否完全一样?
  • 利润贡献:该模块是否直接驱动收入或用户留存?
  • 变更频率:业务策略调整时,是否最常改动这里?
  • 团队投入:最优秀的工程师是否集中在此?
案例:某外卖平台的核心域是“智能调度与预计送达时间”,而非“商家管理”或“支付”。调度算法直接决定配送效率和用户体验,是平台的核心资产。

3.3 支撑域与通用域的边界

支撑域与通用域容易混淆,区分标准是“是否需要定制化”:

  • 支撑域:业务有特殊规则,无法直接使用现成方案。例如“库存锁定策略”因促销活动而异,需要自研。
  • 通用域:行业标准实现,直接集成即可。例如“短信验证码”使用第三方 SDK,无需自研。

3.4 子域划分策略

子域划分不是一次性的,而是迭代演进的过程。推荐以下四步策略:

  1. 事件风暴(Event Storming):与业务专家一起,用领域事件串联业务流程,识别出聚合与限界上下文。
  2. 业务价值排序:对每个候选子域按“核心→支撑→通用”打分,标记优先级。
  3. 依赖关系分析:绘制子域间的依赖箭头,避免循环依赖;核心域应尽量少依赖其他子域。
  4. 限界上下文映射:为每个子域分配独立的限界上下文,确定上下文间的通信方式(RPC、事件、共享内核等)。
常见陷阱:不要将“技术分层”当作子域划分。例如“数据访问层”不是子域,“用户管理”才是。子域必须反映业务概念,而非技术组件。

3.5 子域关系与架构映射

下图展示了一个典型电商系统的子域划分与依赖关系:

电商系统子域划分与依赖关系 核心域 订单履约 定价引擎 推荐算法 (自研,高投入) 支撑域 库存管理 物流调度 客服工单 (自研/外包) 通用域 用户认证 支付网关 邮件通知 (第三方集成) 依赖 依赖 依赖 说明: 核心域只依赖通用域,不直接依赖支撑域;支撑域可依赖通用域。依赖方向应保持单向,避免循环。 每个子域对应一个独立的限界上下文,团队可独立演进。

3.6 子域划分的 Go 实践建议

在 Go 项目中,子域划分直接影响模块(module)与包(package)的组织:

  • 每个子域一个 Go Module:例如 github.com/company/order、github.com/company/inventory,独立版本管理。
  • 核心域模块使用内部包(internal):防止外部直接依赖核心实现细节。
  • 通用域模块尽量薄:只做适配层,调用第三方 SDK,不包含业务逻辑。
  • 支撑域模块可复用:如果多个核心域需要相同支撑能力,通过接口依赖倒置解耦。
Go 代码结构示例:
myapp/
├── order/               # 核心域:订单
│   ├── internal/
│   │   ├── domain/      # 实体、值对象、聚合
│   │   └── service/     # 领域服务
│   ├── api/             # 对外接口
│   └── go.mod
├── inventory/           # 支撑域:库存
│   ├── internal/
│   ├── api/
│   └── go.mod
├── auth/                # 通用域:认证
│   ├── api/
│   └── go.mod
└── go.work              # 工作区统一管理

3.7 识别与划分的常见误区

误区 错误表现 正确做法
技术分层当作子域 将“数据访问层”或“缓存层”划为子域 子域必须对应业务概念,如“用户管理”
所有子域同等对待 核心域与通用域投入相同资源 核心域投入 60% 以上资源,通用域尽量复用
子域划分一次完成 项目启动时强行划分所有子域 通过事件风暴迭代演进,逐步细化
忽略子域间通信 子域之间直接调用数据库 通过 API 或事件总线解耦

3.8 子域演进的持续验证

子域划分不是静态的,随着业务发展,支撑域可能升级为核心域,通用域也可能需要定制化。建议每季度进行一次子域健康度评审:

  • 核心域的变更响应速度是否达标?
  • 支撑域是否出现重复实现?
  • 通用域是否有更好的开源替代?
总结:核心域是架构的心脏,支撑域是骨架,通用域是血液。清晰的子域划分让 Go 团队能够并行开发、独立部署,真正实现“高内聚、低耦合”的架构目标。