改进代码库架构
把架构上的摩擦摆到明面上,并提出加深机会:那些把浅模块变成深模块的重构。目标是可测试性与适合 AI 导航。
这条命令以项目的领域模型为_依据_,并建立在一套共享的设计词汇之上:
- 调用 Skill 工具,传入「codebase-design」,取得架构词汇(模块、接口、深度、接缝、适配器、杠杆、局部性)及其原则(删除测试、「接口就是测试面」、「一个适配器 = 假想的接缝,两个 = 真实的接缝」)。每一条建议里都严格使用这些词,不要滑向「组件」「服务」「API」或「边界」。
GLOSSARY.md里的领域语言为好的接缝提供名字;docs/adr/里的 ADR 记录着这条命令不该重新翻案的决策。
过程
1. 探查
先定范围,再扫描:YAGNI。 加深一个模块的回报,在于让它日后的改动更容易,所以要把额外的权重压在代码库最近改动过的部分上。先决定往哪儿看,然后再看:
- 如果用户点名了某个方向(某个模块、某个子系统、某个痛点),就照它来,跳过下面的推断。
- 否则,往回翻相当长一段提交历史(
git log --oneline),找出代码库的热点,也就是反复出现的文件和区域,让这些路径先把你的注意力吸引过去。如果改动很分散、没有明显热点,就把网撒得更大一些。
先读项目的领域词汇表(GLOSSARY.md),以及你正要触碰的那片区域里的任何 ADR。
然后起一个子代理走一遍代码库。不要照搬死板的启发式规则;顺着代码的实际情况自然探查,并记下你在什么地方感到了摩擦:
- 哪里理解一个概念需要在许多小模块之间来回跳?
- 哪里的模块很浅,接口几乎和实现一样复杂?
- 哪里纯粹为了可测试性抽出了纯函数,而真正的缺陷藏在它们的调用方式里(没有局部性)?
- 哪里紧耦合的模块越过自己的接缝往外漏?
- 代码库的哪些部分没有测试,或者按现在的接口很难测?
对任何你怀疑是浅的东西套用删除测试:删掉它,会让复杂度集中起来,还是只是把它挪个地方?「会集中起来」就是你想要的信号。
2. 把候选方案做成 HTML 报告呈上
写一个自包含的 HTML 文件到操作系统的临时目录,免得有任何东西落进仓库。临时目录从 $TMPDIR 取,取不到就退到 /tmp(Windows 上是 %TEMP%),写到 <tmpdir>/architecture-review-<timestamp>.html,这样每次运行都会得到一个全新的文件。为用户打开它(Linux 上用 xdg-open <path>,macOS 上用 open <path>,Windows 上用 start <path>),并把绝对路径告诉他。
报告用通过 CDN 引入的 Tailwind 做布局和样式,用通过 CDN 引入的 Mermaid 画那些用图/流程/时序能可靠传达结构的示意图。把 Mermaid 和手写的 CSS/SVG 视觉混着用:关系呈图状时(调用图、依赖、时序)用 Mermaid;想要更有编排感的东西时(体量图、剖面图、折叠动画)用手搭的 div/SVG。每个候选方案都要有一幅前后对比可视化。要善用视觉表达。
每个候选方案渲染成一张卡片,包含:
- 文件:涉及哪些文件/模块
- 问题:当前架构为什么造成摩擦
- 方案:用平实的话描述会改什么
- 收益:用局部性和杠杆来解释,并说明测试会怎么变好
- 前/后示意图:并排、手绘,展示浅在哪里、加深在哪里
- 推荐强度:
Strong、Worth exploring、Speculative之一,渲染成徽标
报告结尾放一节首选推荐:你会先动哪个候选方案,以及为什么。
领域部分用 GLOSSARY.md 的词汇,架构部分用 /codebase-design 的词汇。 如果 GLOSSARY.md 定义了「Order」,就说「Order 录入模块」,而不是「FooBarHandler」,也不是「Order 服务」。
与 ADR 的冲突:如果某个候选方案与既有的 ADR 相抵触,只有摩擦大到值得重新审视这条 ADR 时才把它摆出来。在卡片里把它标清楚(例如一个警告框:「与 ADR-0007 相抵触,但值得重新打开,因为……」)。不要把 ADR 禁止的每一种理论上的重构都列一遍。
完整的 HTML 骨架、示意图模式和样式指引见 HTML-REPORT.md。
先不要提接口方案。文件写好之后,问用户:「这些里面你想深入探讨哪一个?」
3. 盘问循环
用户选定一个候选方案后,调用 Skill 工具,传入「grilling」,和用户一起走一遍决策树:约束、依赖、加深后的模块是什么形状、接缝后面放着什么、哪些测试能存活下来。
副作用在决策成形的当下就地发生;调用 Skill 工具,传入「domain-modeling」,让领域模型随时保持最新:
- 给加深后的模块起的名字用了
GLOSSARY.md里没有的概念? 把这个词加进GLOSSARY.md。文件不存在就按需创建。 - 在对话中打磨了一个含糊的词? 就当场更新
GLOSSARY.md。 - 用户以一条有分量的理由否掉了候选方案? 提议写一条 ADR,措辞如:「要不要我把这条记成 ADR,好让以后的架构评审不再重复提它?」 只有当未来的探查者确实需要这条理由才能避免重复建议同一件事时才提议;临时性的理由(「现在不值得做」)和不言自明的理由都跳过。
- 想为加深后的模块探索备选接口? 调用 Skill 工具,传入「codebase-design」,用它那套「设计两遍」的并行子代理做法。


