Zero-Doc:极简的 Spec Coding 落地指南

在 AI 辅助编程逐渐成为主流的今天,业界已经达成了一个共识:Spec Coding(规格驱动开发)是提升 AI 代码质量的必经之路。

然而,横亘在开发者面前的现实却很骨感。一提到 Spec Coding,大家脑海中浮现的往往是复杂、沉重的文档维护负担。

以近期在 GitHub 上备受关注的开源框架 OpenSpec 为例。尽管它已经极力标榜自己"流式而非僵化 (fluid not rigid)",并试图通过一套 Slash 命令来简化流程,但当你真正使用它时会发现:为了添加一个功能,你依然需要生成并维护一个包含 proposal.mdspecs/design.md tasks.md 四个 Markdown 文件的专属文件夹。

这种"文档驱动"的刻板印象,导致绝大多数开发者依然停留在最原始的阶段------直接把成百上千行的源码扔给 AI,然后祈祷它能像资深同事一样瞬间领悟系统的精髓。

结果显而易见:AI 经常产生幻觉,写出无法运行的代码,或者在复杂的逻辑迷宫中迷失方向。

我们需要打破"Spec Coding = 重型工程"的诅咒。本文将探讨一种极简主义且与众不同的落地方案------我们称之为 Zero-Doc Spec Coding(零文档契约)。它不要求你引入任何额外的工具链,也不强迫你学习一套生硬的"提示词语言"去讨好 AI。它只要求你回归开发者的本能:写好结构化的测试断言。

一、 困境与破局:从"文档驱动"到"极简意图"

1.1 上下文窗口的"信噪比"危机

要理解为什么我们需要 Spec Coding,首先得理解大语言模型 (LLM) 的局限性。LLM 本质上是一个"无状态"的函数,它的输出质量完全取决于输入的质量。

当你把整个项目的源代码一股脑地塞进 AI 的上下文窗口时,你实际上是在制造一场"信息灾难"。生产级的代码库中充满了实现细节 (Implementation Details) :繁琐的数据库连接配置、冗长的错误处理逻辑、各种 Helper 函数的定义......这些对于 AI 理解"你要做什么"来说,绝大部分都是噪声 (Noise)

当噪声淹没了真正的业务逻辑(信号 Signal),AI 的注意力就会被分散。简单地说,把原始代码直接丢给 AI,就像是在嘈杂的菜市场里试图通过喊叫来沟通复杂的数学问题------沟通效率极其低下,且极易出错。

1.2 极简解法:Zero-Doc(零文档)

传统的 Spec Coding 之所以难以落地,正是因为它走入了一个误区:要求开发者在代码之外,再维护一套复杂的文档或模型。像 OpenSpec 这样的方案虽然解决了"从无到有"的对齐问题,但却无法逃避"文档腐化"的宿命。 写文档存在沉重的维护负担,且极易过时。

这正是 Zero-Doc Spec Coding 与众不同的地方:我们不维护任何静态的 Markdown 注释或文档,我们只维护活的断言。 文档是死的,单测可以跟着系统一起迭代,是活的。

将 PRD 直接转化为结构化的测试断言,这就是我们的极简着陆点:

  • 输入:PRD(业务意图)
  • 锚点:结构化测试代码(Human in the loop 的绝对审查领域)
  • 产物:实现代码(可抛弃的衍生品)

二、 核心方法论:构建"海平面"的高保真契约

传统的 Spec Coding 常常要求"频繁且有意的压缩 (Frequent Intentional Compression)"来为 AI 提供一份提炼过的说明书。而在 Zero-Doc 的理念下,我们将这种"压缩"直接具象化为测试用例的编写。

为了实现这一点,我们借鉴了软件工程先驱 Alistair Cockburn 提出的"海平面用例 (Sea-Level Use Case)"概念。

2.1 锚定海平面

想象一下,软件开发就像一片海洋:

  • 云端 (Cloud Level):是高层的战略目标(如"提升用户留存率"),这对 AI 写代码来说太抽象。
  • 海底 (Fish Level):是底层的具体函数实现(如"数据库连接重试逻辑"),这对 AI 理解意图来说太琐碎且充满了噪音。
  • 海平面 (Sea Level) :恰好是用户目标层级(如"用户想要重置密码")。

Spec Coding 强调将我们的意图锚定在"海平面"上。在这个层级,我们既不谈论虚无缥缈的愿景,也不纠缠于具体的代码实现,而是清晰地描述用户试图通过系统达成什么具体的、可观测的目标

2.2 结构化降噪:目录即地图,用例即契约

自然语言是模糊的,常常充满歧义。为了让 AI 精准理解海平面用例,我们需要一种多层级的结构化降噪方案:

  1. 宏观结构化(目录层):用测试文件的物理目录和动名词命名,构建出系统的能力地图。
  2. 微观结构化(代码层) :在具体的测试文件中,将断言分为 @MSS(主成功场景)和 @Extensions(扩展流程),将非结构化的需求转化为一份格式严整的测试模板。

2.2.1 宏观降噪:构建系统能力地图

在真实的生产级项目(例如一个典型的电商或内容平台)中,整个 specs 测试目录不再按底层技术组件(如 Controller、Service)划分,而是严格按照"用户目标(用例)"组织。

打开项目的 specs 目录,你看到的不是冷冰冰的代码文件,而是清晰的业务动作:

💡 命名注记 :在标准的用例(Use Case)命名规范中,强烈建议使用动名词或动宾结构 (如 RegisteringUserCreateOrder)来命名。因为用例描述的是"用户试图达成的具体目标和动作过程",而不是一个静态的系统功能模块或状态。这能更好地向 AI 和开发者传递动态的业务行为意图。

text 复制代码
apps/system/specs/
├── ClaimTask.spec.ts                 # 认领任务
├── ConfigurePaymentTable.spec.tsx    # 配置支付表格
├── CreateOrder.spec.tsx              # 创建订单
├── DeleteUserAccount.spec.tsx        # 注销账户
├── ManageUserData.spec.ts            # 管理用户数据
├── ManageSettlements.spec.tsx        # 管理结算列表
├── PerformPaymentAction.spec.tsx     # 执行支付操作
├── ReviewContentMachine.spec.ts      # 内容机器审核
├── SearchTasks.spec.ts               # 搜索任务
└── ViewIncomeSummary.spec.tsx        # 查看收益概览
... (共数十个独立业务用例)

基于这种平铺的用例文件,我们可以用 AI 生成 一份高信噪比的系统能力地图(索引文件 README_SPECS.md)

为什么一定要生成这份索引?因为真实的业务是有层级的,而文件系统如果是平铺的,随着用例增多会变得难以维护。用一份独立的 Markdown 索引来管理业务的模块与层级,可以极大地降低用例的管理成本。 不管上层的业务模块如何调整、重组,底层平铺的用例文件结构都不需要大改,只需更新索引即可。

当团队的新人或者 AI 想要了解"系统到底能做什么"时,不需要去翻阅语焉不详且早已过时的文档,只需看一眼这份地图:

markdown 复制代码
## 核心业务用例 (System Capabilities)

### 用户入驻与认证 (User Onboarding)
* **[管理用户资料数据 (ManageUserData)](./specs/ManageUserData.spec.ts)**:管理用户资料拉取、回填及多步表单验证。
* **[内容机器审核 (ReviewContentMachine)](./specs/ReviewContentMachine.spec.ts)**:用户提交材料的机器审核流程,支持自动识别与信息比对。

### 财务与结算系统 (Settlement System)
* **[管理结算单列表 (ManageSettlements)](./specs/ManageSettlements.spec.tsx)**:结算列表主页面,整合搜索、批量操作和创建入口。
* **[执行支付操作 (PerformPaymentAction)](./specs/PerformPaymentAction.spec.tsx)**:处理结算单的审批、绑定、付款、删除等业务动作。

你可以清晰地看到,这份地图和底层目录共同构成了一份永远不会过时的、活的 PRD。所有的命名都遵循动名词组,业务意图昭然若揭。

2.2.2 微观降噪:结构化测试契约

当我们从宏观地图点击进入任意一个具体的用例文件(例如"用户注册"),就会进入微观的契约层。

在传统方式下,这通常是一个充满高噪声的过程:开发者直接把一个几百行的 React 组件丢给 AI,里面混杂着 UI 样式、副作用管理和 DOM 事件,AI 极易迷失在这些技术细节中。

而在 Zero-Doc 方式下,我们将获得极高的信噪比。我们将业务契约直接写入测试文件的断言中。你可以看到更底层的结构化契约:

typescript 复制代码
// specs/RegisteringUser.spec.ts

describe('@UseCase RegisteringUser: 用户使用邮箱和密码注册新账户', () => {
    
    // @MSS: Main Success Scenario (主成功流程)
    it('@MSS-1: 提交有效信息应成功创建账户并返回成功消息', async () => {
        const result = await register('test@example.com', 'StrongPass123!');
        expect(result.status).toBe('success');
    });

    // @Extensions: 异常与分支流程
    it('@Ext-2a: 邮箱格式无效应拒绝并报错', async () => {
        const result = await register('invalid-email', 'StrongPass123!');
        expect(result.error).toBe('InvalidEmail');
    });
});

三、 辨析:Zero-Doc 契约 vs 普通单元测试

这种结构化的做法常常会引来一种质疑:"这不就是要求我多写点单元测试,然后把它们集中存放在一个测试文件夹里吗?这和普通的单测有什么区别?"

这是一个非常关键的问题。表面上看它们都使用了测试框架,但本质上,Zero-Doc 契约是披着测试外衣的"可执行文档(Executable Specification)"

两者的核心差异主要体现在三个方面。

首先是视角的本质不同。 普通单测是自下而上的"海底视角",关注实现细节(如 test_validate_email_regex),用来验证"代码写得对不对"。而 Zero-Doc 契约是自上而下的"海平面视角",它屏蔽底层技术,只关注业务意图(如 RegisteringUser),用来验证"系统做的事情对不对"。

其次是信息架构的不同。 普通单测往往平铺直叙,像一堆缺乏业务关联的零散零件。而 Zero-Doc 契约通过宏观的目录索引和微观的 @MSS 标签,将非结构化的需求翻译成了一张高信噪比的蓝图,它是用测试框架的壳,装了领域驱动设计(DDD)的魂

最后是生命周期的不同。 普通单测是代码的附庸,底层重构时往往跟着报废。但在 Zero-Doc 的理念下,契约是 AI 生成代码的输入源(Prompt 的具象化)。只要业务需求没变,无论底层代码被 AI 如何重写,这份契约都坚如磐石。在 Zero-Doc 的世界里,业务代码才是可以随时被 AI 抛弃和重写的衍生品,而这份测试契约,是系统唯一的、永不过时的资产。一旦契约确立,AI 便能顺藤摸瓜,生成具体的实现代码。

四、 全场景落地:统一的工作流闭环

这种方式最强大的地方在于,它不仅仅是文档,更是可执行的测试。这形成了一个自动化的反馈循环。

4.1 闭环引擎:AI 的自我修正

  1. Spec -> 测试 :AI 读取 PRD,自动生成包含 @UseCase@MSS@Extensions 标签的测试用例。
  2. 测试 -> 实现:AI 编写实现代码以通过上述测试。
  3. 自我修正:如果实现代码有误,测试会失败(红灯)。AI 收到报错信息后,会在"测试围栏"内自动调整逻辑,直至测试通过(绿灯)。

4.2 遗留系统治理 (Reverse Engineering)

面对没有文档的"屎山"代码,我们采用增量逆向策略:

  1. 逆向:让 AI 扫描老模块源码,反向生成测试断言。
  2. 固化:将断言保存为测试文件,形成"行为快照"。
  3. 重构:有了测试作为安全网,你可以大胆地进行重构。

4.3 新需求开发 (New Feature)

面对冗长的 PRD 文档:

  1. 转化:把 PRD 喂给 AI,让它自动提取并生成结构化的单测断言。
  2. 审查:开发者作为 human in the loop,审查测试用例是否覆盖了所有的 @MSS 和 @Extensions。
  3. 生成:AI 自动生成实现代码。

4.4 需求变更 (Legacy Change)

当业务规则发生变化(例如密码长度从 8 位改为 12 位):

  1. 定位:找到对应的测试文件。
  2. 修改:仅修改测试断言中的期望值。
  3. 修复:运行测试,AI 发现不匹配,自动定位并修复实现代码。这是一次精准的外科手术。

这本质上是一种用例驱动 (Use Case Driven) 的 Zero-Doc Spec Coding 模式。我们用宏观目录划定系统边界,用 @UseCase 圈定业务场景,用 @MSS@Extensions 穷尽业务分支。这个闭环彻底取代了传统的文档维护。

回望过去,为了对抗软件的熵增,开发者们常常需要小心翼翼、如履薄冰地设计各种复杂的系统架构(比如洋葱架构、六边形架构),试图用层层抽象来保护核心业务逻辑。但在 AI 编程时代,这种沉重的"防御性设计"可能不再是首选项。当 AI 拥有了强大的实现能力,我们不再需要过度设计复杂的代码架构,我们只需要设计好这套清晰的目录结构和契约蓝图就可以了。 只要契约在,系统随时可以推倒重来。

五、 终极图景:迎接"代码虚无主义"

如果明天 AI 模型进化了,上下文窗口无限大,推理能力强到能秒懂 10 万行代码,我们还需要写 Spec 吗?

如果真到了那一天,连程序员都不需要了。但在那一天到来之前,我们必须为系统建立坚固的"护栏"。

这并不是一场伪装成"AI 最佳实践"的 TDD 复兴运动,而是确立一种全新的人机协作范式。当你准备好让断言完全接管业务逻辑的描述,你也就准备好接受这种"代码虚无主义"------实现代码变得不再重要,重要的是你定义的测试契约。

结语

告别僵死的文档,拥抱鲜活的断言。Zero-Doc Spec Coding 以 @MSS@Extensions 为契约,确立了 AI 协作的唯一事实来源 。这不仅是开发门槛的降低,更是生产关系的重塑:人类定义意图,AI 交付实现。


附录:开箱即用的 Zero-Doc Skill

为了让你立刻体验 Zero-Doc 的威力,你可以直接在 Trae/Cursor 中安装我开源的 Skill,一键让你的 AI 编程助手掌握这套方法论:

bash 复制代码
npx skills add MertensMing/zero-doc-spec-coding-assistant
相关推荐
毛骗导演1 小时前
万字解析 OpenClaw 源码架构-跨平台应用之MacOS 应用
前端·架构
ZengLiangYi1 小时前
用 1300 行原生 JS 做了一个 Chrome DevTools 扩展,让前后端不再为接口报错截图扯皮
前端·javascript
A_Qyp1 小时前
JeechBoot前端表格内操作设置下拉
前端·javascript
YimWu1 小时前
面试官:OpenCode Agent 代理机制了解吗?
前端·agent·ai编程
chaors1 小时前
从零学RAG0x05实战应用:企业智能知识库
人工智能·github·ai编程
小小程序员mono2 小时前
JS 与 Vue Router 导航方式对比
开发语言·javascript·vue.js
IT星宿2 小时前
smart-unit:一个优雅的 JavaScript 单位转换库,告别繁琐的依赖管理
前端·javascript·typescript
Sgf2272 小时前
如何阅读 React 源码:系统化学习指南
前端·react.js·前端框架
李剑一2 小时前
解决 Cesium 网络卡顿!5 分钟加载天地图,内网也能流畅用,附完整代码
前端·vue.js·cesium