| name | domain-modeling |
| description | 领域建模技能——当需要从需求中提取领域模型、定义实体和边界、建立通用语言时使用。在架构设计之前执行领域建模。 |
领域建模
概述
在动手架构设计之前,先把问题域的核心概念、实体关系、业务规则理清楚。受 Matt Pocock domain-modeling 启发,侧重可落地的领域模型而非 UML 图。
核心理念: 代码是领域模型的映射。模型不清楚,架构就不可能清楚。
何时使用
- 新功能的需求分析完成后、架构设计之前
- 需求中有大量业务术语需要统一理解
- 多个模块之间有复杂的业务关系
- 用户说"理一下业务逻辑"、"建模"、"领域模型"
- 团队对某个功能的理解不一致
工作流位置
brainstorming(需求分析)
↓
domain-modeling(领域建模) ← 新加
│ 输出:领域模型文档 + 通用术语表
↓
wf-architect(架构设计)
│ 输入领域模型,输出系统设计
↓
arch-review(架构评审)
建模流程
步骤 1:提取核心概念
通读需求/规格,识别所有业务概念。不要技术名词(数据库、API、接口),只关注业务语言。
需求原文:"用户可以创建播放列表,添加视频,分享给好友"
提取的概念:
- 用户(User)— 系统的使用者
- 播放列表(Playlist)— 视频的集合
- 视频(Video)— 可播放的媒体内容
- 分享(Share)— 将播放列表访问权授予好友
- 好友(Friend)— 其他用户
步骤 2:定义实体和关系
用简单的文本描述实体之间的关系,不用画图:
实体关系:
用户 1---* 播放列表 (一个用户可以有多个播放列表)
播放列表 *---* 视频 (一个播放列表可包含多个视频,一个视频可属于多个列表)
用户 *---* 用户 (好友关系,双向)
播放列表 *---* 用户 (分享:一个播放列表可分享给多个用户)
关系类型:
1---1 — 一对一(一个用户只有一个资料)
1---* — 一对多(一个用户有多个播放列表)
*---* — 多对多(视频和播放列表)
步骤 3:建立通用语言
把概念和术语统一,消除歧义:
## 通用语言
| 术语 | 定义 | 别称(禁用) |
|------|------|-------------|
| 用户 | 系统的注册使用者 | 客户、会员 |
| 播放列表 | 视频的有序集合,有标题和描述 | 歌单、收藏夹 |
| 共享 | 将播放列表设为其他用户可见 | 分享、公开 |
| 视频 | 可播放的媒体文件,含标题、时长、封面 | 影片、素材 |
步骤 4:识别业务规则
把隐含的约束显式写出来:
## 业务规则
1. 非公开播放列表对其他用户不可见
2. 一个播放列表最多包含 500 个视频
3. 只有播放列表的创建者可以删除它
4. 用户不能将播放列表分享给自己
5. 好友关系是双向的——A 是 B 的好友,则 B 也是 A 的好友
步骤 5:识别限界上下文
把大系统拆成有清晰边界的子域:
## 限界上下文
┌─ 用户上下文 ──────────────────┐
│ 注册、登录、个人资料、好友管理 │
└──────────────────────────────┘
┌─ 内容上下文 ──────────────────┐
│ 视频上传、转码、存储、元数据 │
└──────────────────────────────┘
┌─ 播放列表上下文 ──────────────┐
│ 创建列表、增删视频、排序、分享 │
└──────────────────────────────┘
┌─ 社交上下文 ──────────────────┐
│ 好友搜索、分享通知、时间线 │
└──────────────────────────────┘
输出模板
# 领域模型:[功能名称]
## 核心概念
- [概念1]:[定义]
- [概念2]:[定义]
## 实体关系
[文本描述各实体之间的关系]
## 通用语言
[术语表:术语 → 定义 → 禁用别称]
## 业务规则
1. [规则1]
2. [规则2]
## 限界上下文
- [上下文1]:[职责]
- [上下文2]:[职责]
## 影响的范围
[涉及哪些现有模块/文件]
知识沉淀(边做边积累)
借鉴 grill-with-docs 的理念,领域建模过程中产生的知识持续沉淀,不只在最终文档里。
通用语言 → 实时写入 CONTEXT.md
在建模过程中,每发现或确认一个业务术语,立即更新 CONTEXT.md:
CONTEXT.md 变化过程:
第 1 轮对话:用户说"一个播放列表可以包含多个视频"
→ 立即追加:
## 通用语言
- 播放列表(Playlist):视频的有序集合,有标题和描述
- 视频(Video):可播放的媒体文件
第 2 轮对话:发现"共享"和"分享"是同一个概念
→ 追加:
- 共享(Share):将播放列表设为其他用户可见
- 禁止使用"分享"(与"共享"同义,统一用"共享")
CONTEXT.md 的通用语言部分由 domain-modeling 和 brainstorming 共同维护。任何对话中只要有术语澄清,就更新它。
关键决策 → 实时写 ADR
当做出以下类型的决策时,创建架构决策记录(ADR):
什么情况下写 ADR:
✅ 技术选型(用 A 库还是 B 库)
✅ 方案取舍(方案二是我们选的,为什么放弃方案一)
✅ 约束条件(必须用某个框架、必须兼容某个版本)
❌ 不要写:业务逻辑细节、实现步骤、临时决定
ADR 格式(存到 docs/adr/):
# ADR-0001:使用 exceljs 而非 xlsx 库
## 背景
需要导出 Excel 文件,社区主流有 xlsx 和 exceljs 两个库。
## 决策
选用 exceljs
## 理由
- 支持流式写入,大数据量不 OOM(xlsx 全量加载)
- 活跃维护(上次 commit 在 1 周内)
- 支持样式定制(xlsx 不支持)
## 后果
- 学习成本:团队需熟悉 exceljs API
- xlsx 的相关代码需迁移
持续更新原则
- 不要等到文档写完才记——想到就写,说到就记
- CONTEXT.md 是活的——每次 domain-modeling 都追加新术语
- ADR 是轻量的——3-5 句话,不要长篇大论
- findings.md 也同步——关键的术语歧义和决策理由也记录到 findings.md
输出位置
- 领域模型文档:
docs/superpowers/domain-models/YYYY-MM-DD-<feature>-domain.md
- 通用语言追加到 CONTEXT.md(如果存在)
自检
配合已有技能
| 阶段 | 技能 | 作用 |
|---|
| 需求分析 | brainstorming | 理解需求、输出规格 |
| 领域建模 | domain-modeling(本技能) | 提炼领域模型 + 通用语言 |
| 架构设计 | wf-architect | 基于领域模型做系统设计 |
| 架构评审 | arch-review | 评审架构是否准确映射领域 |
| 编码 | wf-developer | 代码结构与领域模型对齐 |