领域建模
它的作用¶
domain-modeling 在你设计时构建并打磨项目的统一语言。它会质疑与术语表冲突的术语,在你使用模糊词时要求一个精确的词,并用具体场景测试某个关系,直到边界完全清晰。
它是主动的实践,而不是被动的实践。任何技能都可以读取 GLOSSARY.md 来借用其中的词汇。这个技能用于你正在更改模型的时候,因此它会打断你。它会在你敲定术语的那一刻,在对话中途将术语写入 GLOSSARY.md,而不是在最后生成一份整齐的术语表。最后写出的术语表是对一次会话的总结;内联版本则是该会话的输出。
何时使用它¶
输入 /domain-modeling,或者当任务匹配时,代理会自动使用它。实际上,自动调用是这个技能最薄弱的部分。当 grill-with-docs 或 wayfinder 说需要加载它时,模型 常常加载 grilling 而跳过这个技能。如果一次质询会话运行后,GLOSSARY.md 最后没有变化,那就是发生了这种情况。请与其他技能一起按名称调用它。
当词语本身是问题时,使用它:
| 情境 | 应对 |
|---|---|
| 两个人对“取消”的含义理解不同 | domain-modeling:选择规范术语,将另一个列在 _Avoid_ 下 |
| “账户”在三个文件中承担三种职责 | domain-modeling:将其拆分为客户和用户 |
| 你刚刚做了一个难以逆转的架构选择 | domain-modeling:如果该选择达到标准,它会提供一个 ADR |
| 模块的形状是问题:接缝在哪里,接口有多深 | codebase-design |
| 你想在构建前对整个计划进行质询 | grill-with-docs,它在底层驱动这个技能 |
| 你想查询一个术语,而不是更改它 | 什么都不做。读取 GLOSSARY.md。它是一个文件。 |
前提条件¶
无需预先准备。该技能会写入两个位置,并延迟创建它们:
GLOSSARY.md位于仓库根目录。当你敲定第一个术语时,技能会创建它。如果仓库根目录有GLOSSARY-MAP.md,术语会写入该映射所指向的按上下文划分的GLOSSARY.md。docs/adr/。当第一个达到标准的 ADR 出现时,技能会创建它。
开始之前无需任何内容存在,技能也不会提前创建任何东西。
两种产物,两条标准¶
术语表和 ADR 有不同的标准。这个技能的大部分麻烦来自把两者混为一谈。
GLOSSARY.md |
docs/adr/NNNN-slug.md |
|
|---|---|---|
| 保存内容 | 术语。一个事物是什么,用一两句话说明,被拒绝的同义词列在 _Avoid_ 下 |
一个决策,用一到三句话说明:上下文、选择、原因 |
| 写入标准 | 一个模糊术语变成了规范术语 | 三者全部满足:难以逆转、没有上下文时会令人意外、是真实权衡的结果 |
| 写入方式 | 内联,在术语敲定的那一刻 | 提供,而不是假定 |
| 绝不保存 | 实现细节、规范、草稿本、通用编程概念 | 本次会话中每个决策的日记 |
如果 ADR 的三项测试中有任何一项不满足,就没有 ADR。一个容易逆转的决策最终会被逆转;一个不令人意外的决策不是任何人的问题;一个没有真实替代方案的决策只是记录了你做了显而易见的事。
GLOSSARY.md 规则最重要,因为它是实践中最容易出问题的地方。它只是术语表,别无其他。 如果不加约束,模型会把“写入 GLOSSARY.md”当作可以持久化你给出的每个答案的许可,文件就会变成一份持续更新的规范。这是该技能被报告最多的问题,跨越多个模型。
交叉引用,以及它的边界¶
当你说明某事物如何工作时,技能会检查代码并指出任何矛盾。你的代码取消整个订单,但你刚才说部分取消是可能的,哪个是对的? 技能会在更改任何一方之前,让语言和代码大声达成一致。
它交叉引用代码以及已提交的 GLOSSARY.md 和 ADR,除此之外没有别的。它不会搜索你的问题跟踪器。如果你的团队几个月前就一个命名冲突争论过,并在一个已关闭的问题中敲定了它,技能会再次把它当作新问题提出。有一个未解决的请求要修复这个问题。在此之前,变通方法是将说明放入你自己的 docs/agents/domain.md,技能已经会读取它。
常见问题¶
我的 GLOSSARY.md 有 500 行。1,000 行。3,000 行。我该怎么办?
大小是症状。原因是文件吸收了实现细节和那些本就不属于术语表的决策。解决方法是一条直接指令:/grill-with-docs make my GLOSSARY.md more concise and remove any implementation details from it。对一个臃肿的文件运行它,大部分内容会消失。只有当文件已经精简,但仍然覆盖两个读者不想同时掌握的领域时,才用 GLOSSARY-MAP.md 拆分它。拆分一个臃肿的文件只会得到几个臃肿的文件。该技能在这里的指导还不够强,无法一开始就阻止这种增长,而跟踪该问题的 issue 仍然开放。
为什么它是 GLOSSARY.md 而不是 GLOSSARY.md?
这是整个技能集中争论最多的命名问题,而且没有定论。反对当前名称的理由是充分的:如果它是“一个术语表,别无其他”,GLOSSARY.md 就说明了这一点;正如一位读者所说,“有了 AI 代理,一切都是上下文”。支持它的理由是映射:GLOSSARY-MAP.md 指向多个 GLOSSARY.md 文件,读起来自然,而 GLOSSARY-MAP.md 并不自然;并且 context 是 DDD 中用于模型有界区域的固定术语。至少有人维护一个本地 fork,纯粹为了重命名该文件。你也可以这样做,但技能集中的其他每个技能都会查找 GLOSSARY.md,因此重命名意味着要修补所有技能。
/ubiquitous-language 去哪了?
它被移除了,而且不是被弃用。它的职责转移到了 domain-modeling,后者持续维护整个模型,而不是从一次对话中倾倒出一份术语表。现在词汇约束更加重要,而不是更不重要。它在 grilling、triage 和 mapping 之下运行,而不是作为一个你必须记住的独立步骤。
如何为一个没有术语表的代码库获得术语表?
明确请求它,而不是等待它逐渐积累。/grill-with-docs help me scaffold my existing repo with a GLOSSARY.md 是文档中给出的路径。请预期一次长时间拷问。有用户报告在文件成形之前被问了 50 多个问题。在 brownfield 仓库中,顺带使用构建术语表的速度太慢。
我能否保留领域模型并使用自己的 ADR 格式? 目前不能干净地做到。术语表部分和 ADR 部分打包在同一个技能中,因此一个已有既定 ADR 约定(不同模板、不同位置、不同命名)的团队会收到与其内部风格冲突的指令。当前选项是本地复制该技能并编辑它,或者在仓库自己的 agent 文档中覆盖 ADR 约定。将两者拆分是一个开放请求。
术语表真的物有所值吗?它又多了一个需要审查的产物,而且可能会过时。 有时它并不物有所值。DDD 越靠近实现,就越不实用。收益在上游,在于命名和概念对齐,而不是聚合和分层仪式。同义词控制对命名边界很重要:模块名、表名、状态枚举、issue 标题、CLI 命令。在普通文字中,它的重要性要低得多。还有一种反对意见认为,领域术语压缩了已经共享这些术语的人类之间的沟通,而且 agent 对普通英语描述的响应方式相同。按这种理解,术语表的价值在于让你和你的审查者与 agent 正在做的事情保持一致,而不是让 agent 变得更好。对于一天就能完成的构建,跳过它。未经审查、由 agent 编写的术语表比没有更糟:它会充满自信的断言,而后续会话会将其视为真实。
它能把我的模糊 prompt 转成领域语言吗? 不能,也没有计划做一个会这样做的技能。你自己都不理解的领域语言,一旦写下来就没有意义。这个技能在你已经理解之后强制精确性;它不会发明你没有的词汇。相关的陷阱是在没有进行建模的情况下使用领域词。在错误概念之上使用正确的名词,会产生读起来正确但实际不正确的输出。
如果它正在起作用¶
- 它会在你说到一半时停下来,问你指的是两件事中的哪一个,而不是选一个然后继续。
GLOSSARY.md在对话期间发生变化,而不是在结尾一次性爆发。- 它拒绝为明天就能撤销的事情写 ADR,并说明三项测试中哪一项失败了。
- 新条目用一两句话定义某事物是什么,并在
_Avoid_下列出你放弃使用的词。 - 当你的代码和你的句子不一致时,它会把你的代码引用回给你。
GLOSSARY.md变短和变长一样频繁。
它在哪里适用¶
domain-modeling 是一个模型调用的参考,它运行在其他技能之下的频率比单独运行更高。grill-with-docs 通过一次 grilling 会话驱动它,wayfinder 在绘制地图时加载它,triage 使用它让 工单 保持项目自己的措辞,improve-codebase-architecture 在决策确定时调用它。它最接近的兄弟是 codebase-design。它们共同构成其他一切之下的词汇层,这一个用于领域,那一个用于模块的形状。它也可以直接访问,当你想要这种纪律,而不想被通常加载它的技能的那些步骤绑定时。当你不确定哪个技能合适时,ask-matt 会为你路由。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 skills13/skills