1. 一次取消续费需求,让我从“写完就行”改回“先想明白再动手”
我接到过一个看起来特别小的需求:“会员自动续费要允许用户在 App 内取消。”产品同学口述完毕,我脑子里已经闪过整个接口调用链:查订阅状态、调支付渠道的取消接口、更新本地订单表、给用户发一条已取消的站内信。听起来是不是很简单?真正动手后才发现,问题全埋在一堆“常识”里。
取消续费之后,用户这个周期剩余的天数还能不能用?如果用户当天已经扣了下一周期的钱,要退款还是直接关闭自动续费?用户取消后再次点击“续费”,要不要保留原来的支付方式?要不要灰度控制?渠道回调失败时,系统该站在“用户已取消”还是“订阅仍生效”这一边?这些问题没有一个写进需求表里,却全部会在代码评审时被翻出来。结果就是:接口写完,review 了三轮,又被叫去和产品对齐了整整一下午。大家讨论的早已不是代码本身,而是“需求到底是什么意思”。
这件事让我很认真地捡起了“规范驱动开发”(Specification-Driven Development,简称 SDD)。通俗地讲,SDD 不是在代码写完后补一篇文档,而是要求任何一次行为变更,都先产出一份可以被评审、被修改、被接受的“行为规格”,再让代码、测试和评审全部照着这份规格走。我这里说的规格,不是那种几十页、写完就没人看的 PRD,而是放进代码仓库里、能随 git 一起演进、能直接在评审时逐字对齐的小型 spec。
前后试了几周之后,我发现真正让我坚持下来的,是把 openspec-cn 这套思路整理成了适合我自己团队的操作规范。它没有发明什么新概念,只是把“需求背景、目标与非目标、方案取舍、验收标准、落地任务”这些本来就该有但往往散落在聊天记录里的东西,固定成了结构化的仓库资产。你只需要把目录搭出来,把 spec 写清楚,后面所有环节都会自动变得好办很多。
1.1 SDD 和“写设计文档”不是一回事
很多团队听到“先写文档再开发”,第一反应是拒绝。上一套文档流程已经够烦了,再来一个?但 SDD 跟我们印象里的“设计文档”有本质区别。
传统设计文档往往是在需求确定后、开发开始前,由架构师写的一份大而全的方案,包含总体架构、模块划分、数据库设计、接口清单。它的阅读成本高,维护成本更高,开发到一半需求变了,文档却没有跟着变。另一种常见情况是,开发结束之后补一份“系统设计说明”,这种文档只能用来交差,对代码质量没有任何帮助。
SDD 的规格文件走的是完全相反的路线:小步、短命、贴近当前变更。它不需要覆盖整个系统的宏伟蓝图,只需要把你正在做的这一次变更说清楚。比如“允许用户取消自动续费”,就只需要回答四件事:
- 为什么要做这个变更;
- 做出来后用户能感知到什么;
- 哪些是这次要做的,哪些是明确不做的;
- 怎样才算做完了,能被验收。
这份 spec 放在代码仓库的 specs 目录里,和代码一起走 Git 流程。实现代码之前,先开一个只包含 spec 修改的分支,让产品、后端、前端、测试一起 review 这份行为描述。确认没问题后再把 spec 合并进去,接下来实现的每行代码、写的每个测试用例,都以这份 spec 为基准。这不是把文档重做一遍,而是把“需求”从口头和聊天记录里移到一个有版本、有讨论记录、有明确状态的地方。
1.2 openspec-cn 帮我省掉了什么
说来也惭愧,我最初不是直接用了完整的 openspec,而是先从它的文档里借了目录结构和 spec 模板。openspec-cn 本质上是一套面向中文研发团队使用习惯整理出来的规范驱动开发操作约定。它借鉴了 OpenSpec 对目录、命名、评审流程方面的设计,但把模板文案、示例、决策记录方式都做了更适合国内团队直接上手的处理。
我实际用起来,最值钱的是它自动帮我解决了三件平时最消耗精力的事。第一,spec 模板规定了每一份需求文档必须包含哪些小节,产品提需求时不需要我再追着问“边界是什么”“异常场景怎么处理”;第二,目录命名有明确约定,任何一次变更在仓库里都有唯一的编号,PR、Issue、发布说明可以直接引用;第三,规范文件本身是 Markdown 编写的,改动走 Git diff,哪句话变了、谁在什么时候改的、理由是什么,全部留下痕迹。
用上这套约定后,我和产品同学的协作方式也变了。以前产品在 IM 里说一段需求,我听完点头,转头就开始设计。现在我会说:“我先把它写成 spec,你来帮我 review 一下目标和验收标准。”刚开始对方觉得形式化,后来发现有分歧时直接把 spec 里某一句话拉出来讨论,效率比翻聊天记录高很多。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 把 specs 目录搭对,等于成功了一半
很多人以为规范驱动开发的难点在“写文档”,其实真正的门槛在“目录怎么建”。目录决定了 spec 文件能否被自动归类、能否在多人协作时不冲突、能否被 CI 等工具识别。我从 openspec-cn 拿到并实际跑了几个项目后,最后沉淀下来的目录结构大概是这样的:
text复制<你的项目仓库根目录>/
├── specs/
│ ├── fe
