
你在和 AI 编程助手讨论代码结构的时候,有没有遇到过这种情况——你说“这个模块的接口可以简化一下”,AI 回你“好的,我来优化 API”;你说“这里需要一个适配层”,AI 开始给你写一堆抽象的工厂类。你们说的似乎是同一件事,但又不完全一样。“模块”和“组件”有什么区别?“接口”到底是指类型签名还是包括错误处理和性能特征?“边界”和“接缝”是一回事吗?
这些词在日常开发中经常被混用,但当你要和 AI 助手一起做代码设计的时候,词语的模糊会直接导致设计的模糊。codebase-design 这个技能就是为了解决这个问题而出现的。
它由 Matt Pocock 开发,是 GitHub 上 skills 仓库中的核心技能之一。截至 2026 年 8 月,这个技能在 Claude Code 平台上的安装量已超过 16 万次。它不生成代码,不提供模板,不帮你写文档——它只做一件事:给 AI 编程助手一套精确的词汇,用来讨论和设计代码结构。
这个技能能做什么
codebase-design 的核心思想来自 John Ousterhout 在《A Philosophy of Software Design》中提出的“深度模块”概念。深度模块的特点是:小接口,大实现——调用者只需要学习很少的东西,就能获得很多功能。
但 codebase-design 不是简单地复述这个概念。它把“深度”从“代码行数比例”重新定义为“杠杆效应”(leverage)——调用者每学一个单位的接口,能获得多少行为能力。这个衡量标准更贴近实际使用场景:一个接口好不好,不在于它背后有多少行代码,而在于调用者用起来有多顺手。
为了实现这个目标,技能提供了一套严格的术语表。这套术语表规定了在讨论代码设计时必须使用的精确词汇,并明确禁止使用那些含义模糊的替代词。
Module(模块) :任何有接口和实现的东西。这个词是故意设计成“规模无关”的——可以是一个函数、一个类、一个包,也可以是一个跨层的切片。技能特别强调:不要说“组件”(component)、“单元”(unit)或“服务”(service)。这些词要么太窄,要么在不同语境下含义不同,容易引起误解。
Interface(接口) :调用者为了正确使用模块需要知道的一切。这不仅仅是指类型签名,还包括不变量(invariants)、顺序约束、错误模式、必需的配置项和性能特征。技能特别指出:不要说“API”或“签名”(signature),因为这两个词太窄了,只覆盖了类型层面的东西。
Seam(接缝) :Michael Feathers 提出的概念——可以在不修改某个地方的情况下改变行为的位置。简单说,就是模块的接口所在的位置。接缝放在哪里,是一个独立的设计决策,和接口背后放什么东西是两回事。技能特别指出:不要说“边界”(boundary),因为这个词在 DDD(领域驱动设计)中已经被“限界上下文”占用了,容易混淆。
Adapter(适配器) :在接缝处满足某个接口的具体实现。适配器描述的是“角色”(这个位置填了什么),而不是“实质”(里面装了什么)。一个适配器可以是小适配器+大实现(比如一个 PostgreSQL 仓储),也可以是大适配器+小实现(比如一个内存中的 fake)。
Depth(深度) :接口的杠杆效应——调用者(或测试)每学一个单位的接口,能驱动多少行为。深度模块 = 小接口 + 大量实现;浅层模块 = 大接口 + 少量实现(要避免)。
Leverage(杠杆效应) :调用者从深度中获得的东西——每学一个单位的接口,获得更多的能力。一个实现可以在 N 个调用点和 M 个测试中反复产生回报。
Locality(局部性) :维护者从深度中获得的东西——修改、缺陷、知识和验证都集中在一个地方,而不是分散到所有调用者中。改一处,全部生效。
除了这套术语,技能还提供了一个实用的判断工具——删除测试(deletion test)。想象一下:如果把这个模块删掉,它的复杂度是会彻底消失,还是只是扩散到了所有调用者那里?如果复杂度只是扩散了,说明这个模块没有提供足够的价值,它的接口可能太浅了。
技能还包含 design-it-twice 模式——在确定最终方案之前,用两种不同的方式设计同一个接口,然后比较哪个更好。这个模式可以帮你避免“第一个想到的方案就是最好的方案”这种思维陷阱。
安装方法
codebase-design 是 Matt Pocock 的 skills 仓库的一部分,支持 Claude Code、Cursor、Windsurf、Codex、Goose、GitHub Copilot、Zed 等多种 AI 编程助手。
通过 npx skills 安装(推荐) :
在项目根目录打开终端,执行以下命令:
npx skills add mattpocock/skills --skill codebase-design
为特定 Agent 安装:
如果只想为某个特定的 AI 助手安装,可以用 --agent 参数指定:
npx -y skills add mattpocock/skills --skill codebase-design --agent claude-code
这条命令会把技能安装到当前项目的 .claude/skills/ 目录下。
通过 skillsauth 全局安装:
npx skillsauth add mattpocock/skills codebase-design通过 Claude Plugin Hub 安装:
npx claudepluginhub filippolmt/skills --plugin codebase-design前置条件:
Node.js 环境(版本 ≥ 18)
一个支持 skills 的 AI 编程助手(Claude Code、Cursor、Windsurf 等)
安装完成后,技能会自动配置到你的 AI 编程环境中。你可以通过 /codebase-design 命令调用它。
什么时候该用它
应该使用的情况:
你想设计或改进一个模块的接口
你在寻找“加深”的机会——让接口更小、实现更丰富
你在决定接缝应该放在哪里
你想让代码更容易测试
你想让代码对 AI 更友好(AI-navigable)——AI 助手能更容易地理解代码结构
其他技能需要用到“深度模块”的词汇体系
不应该使用的情况:
你只是在写代码,没有涉及结构设计
你只是在查资料,不需要讨论设计决策
任务本身不需要任何架构层面的思考
使用案例
案例一:设计一个新模块的接口
你正在开发一个支付处理模块。你告诉 AI 助手:“我要设计一个支付模块的接口。”
没有 codebase-design 的时候,AI 可能会直接给你写一堆代码——一个 PaymentService 类,里面有 process()、refund()、validate() 等方法,然后问你“这样可以吗”。
有了 codebase-design,AI 会先用这套词汇和你讨论:这个模块的接口应该包含什么?调用者需要知道哪些不变量?错误模式是什么?配置项有哪些?接缝应该放在哪里?你们先把接口的形状讨论清楚,再开始写实现。结果是:接口更小、更清晰,调用者用起来更顺手。
案例二:重构一个越来越难维护的模块
你有一个模块,一开始很简单,但经过几轮迭代之后,接口上挂了十几个方法,参数越来越复杂,调用者越来越困惑。你告诉 AI 助手:“这个模块越来越难用了,帮我看看怎么改进。”
codebase-design 会引导你用“深度”的视角来分析问题:这个模块的接口有多大?实现有多丰富?接口和实现的比例是否合理?如果删除这个模块,复杂度是会消失还是扩散?这些问题的答案会帮你找到重构的方向——可能是把接口拆小,可能是把部分逻辑移到模块内部,可能是重新设计接缝的位置。
案例三:让代码更容易测试
你的代码很难写单元测试——每次测试都要准备一大堆依赖,mock 一大堆东西。你告诉 AI 助手:“这段代码太难测了,帮我想想办法。”
codebase-design 会引导你关注“接缝”的位置:测试是通过什么接口来驱动这个模块的?如果接缝放在这里,测试需要准备多少东西?如果把接缝移到另一个位置,测试会不会变得更简单?这些讨论会帮你找到一个更测试友好的设计。
案例四:让代码对 AI 更友好
你的项目越来越大,AI 编程助手越来越难理解代码的结构——每次让它改一个地方,它都要读一大堆文件才能搞清楚上下文。你告诉 AI 助手:“帮我优化一下代码结构,让你自己更容易理解。”
codebase-design 会引导你设计“深度模块”——每个模块都有一个小接口和大量实现。对 AI 来说,理解一个小接口比理解一个大接口容易得多。模块越深,AI 需要学习的接口就越小,理解代码的速度就越快。
几个值得注意的细节
这套词汇是强制性的,不是建议性的:技能文档明确要求“Use these terms exactly — don't substitute”——使用这些精确的术语,不要用其他词替代。“一致的语言是全部意义所在”。这不是在吹毛求疵——当你在和 AI 讨论代码结构的时候,词语的精确性直接决定了设计的质量。
“深度”不看代码行数,看杠杆效应:codebase-design 对“深度”的定义和 Ousterhout 的原始定义有一个关键差异——它用“杠杆效应”代替了“代码行数比例”。一个接口好不好,不在于它背后有多少行代码,而在于调用者每学一个单位的接口能获得多少能力。
适配器和实现是两回事:一个 Postgres 仓储可以有很小的适配层(几行代码)和很大的实现(整个 SQL 层);一个内存 fake 可以有很大的适配层(模拟所有行为)和很小的实现(几个字典)。技能要求你区分“适配器”和“实现”——当你讨论接缝的时候用“适配器”,其他时候用“实现”。
删除测试是一个强大的判断工具:下次你不确定一个模块是否有存在的价值,试试删除测试——想象把它删掉,看看复杂度是会消失还是扩散。如果复杂度只是扩散到了所有调用者那里,这个模块可能太浅了,需要加深。


◯ 评论 0