| name | ubiquitous-language |
| description | 从当前对话中提炼出一份 DDD 风格的通用语言(ubiquitous language)术语表,标记歧义并提出规范术语。保存到 UBIQUITOUS_LANGUAGE.md。当用户想定义领域术语、构建术语表、固化用词、创建通用语言,或提到 "domain model" 或 "DDD" 时使用。 |
| disable-model-invocation | true |
通用语言(Ubiquitous Language)
从当前对话中提取领域术语并将其规范化为一份一致的术语表,保存到本地文件。
流程
- 扫描对话,寻找与领域相关的名词、动词和概念
- 识别问题:
- 同一个词用于不同概念(歧义)
- 不同的词用于同一个概念(同义词)
- 含糊或被过度负载的术语
- 提出一份规范化的术语表,并对术语选择持有明确立场
- 写入工作目录下的
UBIQUITOUS_LANGUAGE.md,使用下面的格式
- 在对话中内联输出一份摘要
输出格式
写一个 UBIQUITOUS_LANGUAGE.md 文件,结构如下:
# 通用语言
## 订单生命周期
| 术语 | 定义 | 应避免的别名 |
| ----------- | ------------------------------------------------- | --------------------- |
| **Order** | 客户购买一个或多个商品的请求 | Purchase, transaction |
| **Invoice** | 交付后发送给客户的付款请求 | Bill, payment request |
## 人员
| 术语 | 定义 | 应避免的别名 |
| ------------ | ------------------------------------------- | ---------------------- |
| **Customer** | 下订单的个人或组织 | Client, buyer, account |
| **User** | 系统中的一个认证身份 | Login, account |
## 关系
- 一个 **Invoice** 恰好属于一个 **Customer**
- 一个 **Order** 产生一个或多个 **Invoice**
## 示例对话
> **开发者:** "当一个 **Customer** 下了一个 **Order**,我们会立即创建 **Invoice** 吗?"
> **领域专家:** "不会——只有在 **Fulfillment** 被确认后才会生成 **Invoice**。如果商品分开在不同的 **Shipment** 中发货,单个 **Order** 可以产生多个 **Invoice**。"
> **开发者:** "那如果一个 **Shipment** 在发货前被取消,就不会为它生成 **Invoice**?"
> **领域专家:** "正是如此。**Invoice** 的生命周期绑定在 **Fulfillment** 上,而不是 **Order** 上。"
## 标记出的歧义
- "account" 被用来同时表示 **Customer** 和 **User**——这是两个不同的概念:**Customer** 下订单,而 **User** 是一个认证身份,它可能代表也可能不代表一个 **Customer**。
规则
- 要有明确立场。 当同一概念存在多个词时,挑出最好的那个,把其余的列为应避免的别名。
- 明确标记冲突。 如果某个术语在对话中被歧义地使用,在"标记出的歧义"一节中点明,并给出清晰的建议。
- 只纳入对领域专家有意义的术语。 跳过模块名或类名,除非它们在领域语言中有意义。
- 保持定义紧凑。 最多一句话。定义它"是什么",而非它"做什么"。
- 展示关系。 使用加粗的术语名,并在显而易见处表达基数(cardinality)。
- 只纳入领域术语。 跳过通用编程概念(array、function、endpoint),除非它们具有领域特定的含义。
- 当出现自然的聚类时,把术语分成多个表格(例如按子域、生命周期或参与者)。每个分组拥有自己的标题和表格。如果所有术语都属于单一、内聚的领域,一个表格也可以——不要强行分组。
- 写一段示例对话。 一段开发者与领域专家之间的简短对话(3-5 轮),展示这些术语如何自然地相互作用。对话应当厘清相关概念之间的边界,并展示术语被精确使用。
示例对话
开发者: "我怎么在没有 Docker 的情况下测试 sync service?"
领域专家: "改为提供 filesystem layer,而不是 Docker layer。它实现了相同的 Sandbox service 接口,但使用一个本地目录作为 sandbox。"
开发者: "那 sync-in 仍然会创建一个 bundle 并解包它?"
领域专家: "正是。sync service 并不知道它在和哪一层对话。它调用 exec 和 copyIn——filesystem layer 只是把这些当作本地 shell 命令来运行。"
再次运行
当在同一对话中再次被调用时:
- 读取现有的
UBIQUITOUS_LANGUAGE.md
- 纳入后续讨论中出现的任何新术语
- 如果理解有所演进,更新定义
- 重新标记任何新的歧义
- 重写示例对话以纳入新术语