首页 / 资讯中心 / 文章详情

规格驱动开发实战:从需求分析到可执行契约的完整方法论

规格驱动开发实战:从需求分析到可执行契约的完整方法论 ★ FEATURED ARTICLE
很多人把“需求分析”和“写代码”当成两件事中间隔着一道“评审会开了大家点头了代码写出来一看全不对”的脏河。我最近带团队把一个库存订单项目从头走到尾把“规格驱动开发”这套玩法完完整整落了一遍工具用的是团队内部攒的 Spec-Kit。这篇文章把我踩过的坑、拆过的心得、以及从需求到规格再到可执行契约的施工路径全部分享出来。适合正在被需求不清、前后端扯皮、验收靠吵这些问题折磨的团队负责人、后端、前端、测试和产品同学参考。1. 为什么需求分析到开发之间总隔着一层“翻译损耗”1.1 需求口头传递的损耗到底出在哪我先问一个问题一个需求从产品经理嘴里说出来到开发手里写成代码中间到底经过了几手常见路径是产品讲给项目经理项目经理整理成会议纪要纪要发给开发开发照着纪要里的半句话开始设计表结构测试拿着同一个纪要想验收点最后对不上。问题不在于谁偷懒而在于我们用了不适合做精确沟通的工具。自然语言天生适合表达意图不适合表达约束。一个“订单超时后要自动关闭”需求方脑子里想的是“用户好久没付款这单别占库存了”开发脑子里想的是“定时任务扫一次然后改状态”测试想的是“我到底该等几分钟才能验收”。同一个词三个解释。更麻烦的是需求方通常只描述“正常路径”。用户会取消、会改地址、会付款失败、会重复点击提交。这些边界没有被显式写出来开发只能靠猜猜的结果就是系统上线后在线上“长”出各种奇怪的异常分支。我在这个项目里学到最狠的一课是需求文档根本不是给开发看的是给所有人对齐用的“契约”。只要它还是一篇散文就一定会被各自解读。1.2 规格驱动开发想解决的问题规格驱动开发Spec-Driven Development核心就一句话在写代码之前先把“行为规格”写出来让它成为团队唯一的真相来源。行为规格不是PRD也不只是接口文档而是用结构化方式描述“系统在什么条件下、做什么事、产生什么结果”。具体解决三个问题需求语义不唯一用 Given-When-Then 和 数据契约代替“应该”“可能”“尽量”这类模糊词。验收标准靠感觉验收不是临到提测才想而是需求定稿时就跟规格绑定一条规格就是一条验收项。开发和测试没有共享基线前端、后端、测试各自维护自己的理解规格只有一份所有人都向它看齐。这套玩法不是新东西测试领域叫 BDD架构领域叫“契约优先”。Spec-Kit 做的是把这些方法收敛成一个可操作的工具链让团队不需要记一堆散落的规范也能把规格落成可校验、可执行的东西。2. 三种思维先当用户再当系统最后当施工队2.1 用户思维把“想要什么”翻译成“怎样算完成”需求分析的第一步不是画流程图而是把自己丢进用户的场景里。我常用一个土办法每个核心需求都先写一句“作为一个XX角色我希望在XX条件下达到XX目的”然后立刻追问“那我怎么证明这个目的达到了”举个例子。库存订单系统里有个需求叫“库存不足时不允许下单”。如果只写到这开发一定会问是下单时校验还是提交后异步校验是整单拒绝还是部分拒绝提示文案是什么并发下单时怎么办用用户思维转一圈应该得到这样的描述作为一个买家当我在商品详情页提交购买数量超过库存的订单时我希望系统立即阻止提交并提示“库存不足”这样我就不用等发货时才知道买不了。这还不算完。真正扎实的做法是把“立即阻止”背后的可观察结果写出来接口返回 4xx、前端弹出提示、库存数量不发生变化。这三条就是验收标准。用户思维最难的地方是别急着给方案。需求方说“我要一个批量导入功能”你不要马上想 Excel 解析怎么写而是先问“你希望导入之后系统做什么数据格式错了应该提示到什么程度中途失败是回滚还是跳过”方案是施工阶段的事需求阶段只负责把“完成的样子”钉死。2.2 系统思维把需求拆成可交互的契约用户思维管“外面看起来什么样”系统思维管“里面各模块怎么协作”。这时候眼中不再有“用户”而是有“订单服务”“库存服务”“支付回调”“消息队列”这些系统部件。我在这一阶段最爱做三件事列领域对象、画状态流转、定接口边界。列领域对象就是找出系统里到底有哪些“名词”。还是拿订单举例订单、订单项、库存快照、支付单、售后单。每个名词都要有明确的定义尤其注意“同名不同义”的情况。比如“订单状态”在订单服务里是“待支付/已支付/已关闭”在售后流程里叫“可退款/不可退款”这俩不能混在一个字段里。画状态流转是把状态机的合法路径标出来。很多线上事故就是因为状态枚举写得很随意导致订单从“已支付”直接跳到“已取消”钱退了货没退或者货发了状态还停在待发货。状态流图不需要工具表格就够了我后面会演示。定接口边界是明确“谁调用谁、传什么、返回什么”。这一步不做前后端就会各写各的字段名联调时花一周对齐参数。规格驱动开发里这块直接用数据契约来钉后面会细说。2.3 工程思维施工方案、节奏与风险系统思维把“系统长什么样”定了工程思维管“怎么把它盖出来”。这一步要回答的不是“功能是什么”而是“先做哪块、后做哪块、哪些可以凑合、哪些必须死磕”。我习惯在这个阶段把需求按“MoSCoW”分四类Must必须有、Should应该有、Could可以有、Wont这次不做。凡是 Could 和 Wont直接请出本期范围。任何团队都容易在砍需求时犹豫但如果一条需求进不了规格文档就坚决不排期这是硬规矩。工程思维还要求算清楚“施工顺序”。我的原则是先打通数据链路最粗的那条线。比如库存订单系统最核心的链路是“下单 - 扣库存 - 支付回调 - 发货”。先把这个链路用最简方式跑通再补校验、补异常、补管理后台。如果一开始就想着把权限、日志、风控全部做齐项目大概率延期。三种思维的关系可以看成三道过滤网用户思维过滤掉“不该做”的系统思维过滤掉“说不清”的工程思维过滤掉“现在不该做”的。全部过滤完剩下的才是能写进规格的东西。3. Spec-Kit 是什么以及我为什么在多个方案里选了它3.1 定位与核心能力补一句背景。Spec-Kit 不是某个商业平台的付费产品是我们在某个项目里基于开源生态自己攒的一套轻量级规格管理工具集。它沉淀了团队内部“怎么写规格、怎么校验规格、怎么让规格驱动代码”的一整套约定。核心组件就四块需求条目库用结构化 Markdown 管理每条需求带编号、优先级、状态。规格文档引擎把 Given-When-Then 行为规格渲染成团队可读的网页。数据契约校验器用 JSON Schema 描述接口/消息格式接入 CI 后自动比对。桩代码生成器根据契约生成前后端的接口骨架保证两端从第一行代码就对齐。听起来好像也没什么黑科技但它解决了团队协作里最烦人的“信息分散”问题。以前我们的需求在在线文档里、接口定义在调试工具里、测试用例在用例管理平台里、代码注释在 IDE 里每次对齐信息都要开四个窗口。Spec-Kit 把这四样统一成一份“规格源”其他都是它的派生品。3.2 为什么不用“更好的 PRD”或“接口文档”你可能觉得我把 PRD 写细一点不就行了我把接口文档维护好不就行了我试过都不是最佳方案。传统 PRD 的问题是它本质是“给人看的叙述文档”。写得再细也经不起“需求变更”和“字段调整”的反复折磨而且 PRD 和代码没有天然的双向绑定关系代码跑偏了文档不会报警。接口文档的问题是它只描述了“传输层长什么样”没描述“行为上应该发生什么”。比如接口文档告诉你POST /orders接受什么参数、返回什么结构但它不会告诉你“库存不足时应该返回哪个错误码、订单状态应该保持什么值、此时是否要发送通知”。行为规格和数据结构契约缺一不可。工具对比下来我的选择逻辑是这样方案优点致命伤适配场景在线文档 PRD门槛低、人人会写无法自动校验越写越散早期想法收集接口文档结构清晰只覆盖接口层行为语义缺失联调辅助传统用例管理可回溯滞后于开发常被忽略测试执行记录Spec-Kit 规格驱动单一来源、可校验、可生成代码前期建模成本高中大型系统开发选它的根本原因是它把我最痛的那个点治了不需要靠人勤快才能保证文档不烂。规格是机器可校验的写错了可能在 CI 就报红而不是线上才炸。4. 从需求分析到 Spec-Kit 落地的完整施工过程4.1 第一批规格怎么定需求条目化第一步把所有需求从“散文”改成“条目”。我一般用一个表格管理编号需求名称用户价值优先级依赖REQ-001用户提交订单买家能下单Must无REQ-002库存校验防止超卖MustREQ-001REQ-003订单超时自动关闭释放无效库存ShouldREQ-001REQ-004订单导出 CSV运营做数据分析CouldREQ-001这里有个细节每条需求必须有“依赖”列。否则排期的时候永远不知道某条需求为什么卡住。我习惯先理依赖关系后谈时间估算。条目化之后做一次“规格评审”不是拿着文档念而是逐条过三个问题这条需求有明确的验收标准吗有异常路径吗涉及的接口/数据契约定了吗过不去的退回补充。这个环节会把项目前期的模糊地带全部暴露出来。4.2 行为规格怎么写Given-When-Then行为规格是 Spec-Kit 的核心表述单元标准句式是Given系统的前置状态包括用户身份、已有数据、时间条件。When触发动作包括用户操作、外部回调、定时任务。Then期望结果包括返回值、状态变化、副作用。用订单超时关闭举例。这条规则如果写在 PRD 里大概是“订单超时后系统自动关闭”。写成行为规格是这样Feature: 订单超时关闭 Scenario: 支付超时关闭订单并释放库存 Given 存在一笔状态为“待支付”的订单 And 该订单的创建时间在30分钟之前 When 定时任务执行订单超时扫描 Then 该订单状态变为“已关闭” And 该订单占用的库存数量被释放 And 系统向买家发送“订单已关闭”通知我特别强调 And 那一行的价值。很多人写规格只写主结果“订单状态变为已关闭”但“释放库存”和“发送通知”恰恰是线上最容易漏的分支。把它们写进 Then开发和测试就都赖不掉。写行为规格时有一个原则一条 Scenario 只描述一个完整的业务规则不要贪多。如果发现一个 Scenario 里有超过三个 And通常意味着它在描述多个规则应该拆分。4.3 数据契约怎么定JSON Schema行为规格管“业务规则”数据契约管“传输格式”。我用 JSON Schema 描述接口和消息结构交给 Spec-Kit 作为校验基准。举个例子创建订单接口的请求体{ $schema: http://json-schema.org/draft-07/schema#, title: CreateOrderRequest, type: object, required: [buyerId, items], properties: { buyerId: { type: string, format: uuid }, items: { type: array, minItems: 1, items: { type: object, required: [skuId, quantity], properties: { skuId: { type: string }, quantity: { type: integer, minimum: 1 } } } }, couponCode: { type: [string, null] } } }我把契约评审的要领总结成三看看必填required 里少一个字段轻则联调返工重则线上漏数据。看类型约束quantity是 integer 不是 number否则前端传1.5就静默入库了。看枚举与格式状态字段尽量用 enum 约束避免字符串随手写。数据契约一旦定稿别在代码里“顺手”改。任何字段变更必须先改规格文件再动代码。Spec-Kit 接入 CI 后后端接口返回和前端传参都会和这份 Schema 做比对不一致直接报错。4.4 规格如何驱动开发完整工作流Spec-Kit 落地到日常开发我们形成了一套固定动作产品在需求条目库里新增需求条目评审通过后进入规格撰写。技术负责人撰写或审阅对应的行为规格与数据契约。契约定稿后用 Spec-Kit 生成前后端接口桩代码两端基于同一份结构开始开发。开发实现过程中如果发现规格不合理必须提交“规格变更申请”不能自己改代码绕过。测试用例直接从规格自动映射每个 Scenario 对应一条用例的骨架。CI 流水线里同时跑“契约校验”和“规格用例”任何一端偏离规格构建就失败。这个流程最关键的地方是把“沟通”变成了“校验”。以前对齐需求靠开会现在对齐需求看 CI 跑没跑绿。人有状态好坏、记忆偏差机器没有。5. 施工方案坑怎么填节奏怎么排5.1 契约优先边界先行施工现场最容易乱的地方是“接口还没定两边同时开工”。我经历过的真实场景前端按“下单后返回订单详情”的假想联调后端按“下单后返回支付二维码”的假想设计两边代码都写完了一对接才发现整个页面要推翻。契约优先就是治这个病的。动工之前凡是跨模块的接口和消息一律先把 JSON Schema 和关键状态流转表定掉。边界不稳内部怎么盖都是危楼。具体排施工顺序我按三个梯队走第一梯队主链路契约。订单、库存、支付这些核心对象的 Schema先定先审。第二梯队各服务的内部行为规格。定每个服务在自己的领域内该干什么。第三梯队管理后台、报表等辅助功能。这些不涉及主链路晚点定不影响大局。5.2 节奏控制规格冻结日是底线我们把迭代周期定为两周其中有一个雷打不动的节点迭代第二周的周三下午规格冻结。冻结之后任何人不得新增或修改本期规格只能把变更请求扔进下个迭代的待办池。为什么非要设一个“冻结日”因为开发最怕的不是需求变而是需求边做边变且变更不汇总。冻结日制造了一个临时性的“确定性窗口”让开发能专心把代码写完。需求方如果临时说“这里要加个功能”我们不会直接拒绝而是请他确认是否重要到值得延期一般到这一步60% 的临时需求自己就消失了。节奏示意图用时间线表格表示阶段时间窗口核心动作需求澄清D1-D3条目化、写用户故事、划优先级规格撰写D2-D5行为规格、数据契约初稿规格评审D5-D6评审例会逐条过 Scenario规格冻结D7 下午锁定本期全部规格实现与验证D7-D13开发、联调、测试映射复盘与变更归集D14收集变更排入下期这个节奏在团队里跑了两个迭代以后大家明显松弛下来因为都知道“不会突然被改规格”。5.3 状态管理防止规格漂移规格写得再好也会面临“漂移”。所谓漂移是代码已经按新逻辑走了但规格文档没人更新两三个月后文档成了废纸。我们在 Spec-Kit 里给每条规格配了生命周期状态草稿、评审中、已冻结、已实现、已废弃。任何状态变更都要有记录。开发提了一个接口变更构建时发现契约校验不过系统就会强制要求他修改规格文件否则合并请求无法通过。这套机制的底层逻辑是让“描述系统的文档”和“系统本身”始终绑定。谁破坏绑定谁就在 CI 里留下红色记录。不要让团队靠自觉维护文档要靠自动化流程维护文档。6. 实操中常见的问题与排查技巧实录6.1 规格写得像散文怎么办新手写规格最大的毛病是条件描述不精确。比如写“用户登录后可以查看订单”这不算行为规格因为没有状态、没有输入范围。我会在评审时把这类描述打回要求补全“Given用户未登录时请求订单详情接口”和“Then返回 401 且不暴露订单数据”。排查方法是做一次“找形容词运动”把规格里所有“自动、尽快、允许、相应”这类词圈出来逐个逼问——多快算快允许的条件是什么相应是返回什么圈完基本就改出一半问题。6.2 需求方不看规格怎么拉回来总有需求方觉得“你们技术搞这套太麻烦直接按我说的做就行”。我的处理策略不是逼他看文档而是把规格渲染成一个带编号的需求清单每次给他看“你上个月提的 12 条需求现在 10 条已经可以在测试环境看到了还有 2 条因为规格没定卡在评审里”。用进度事实倒逼他参与评审。另外我坚持让产品经理在规格上签字电子签名即可。这个动作看着形式化却能极大降低“我当时不是这么说的”的频率。签过字的规格就是验收依据出了争议直接翻记录。6.3 前后端代码都对联调就是跑不通这类问题九成出在“数据契约不一致”而且往往是隐性的。字段名一样但语义不同类型一致但格式不同请求参数和响应参数搞混。排查技巧先别盯代码把后端实际返回的一截响应摘出来再拿前端实际发出的请求摘出来和 Spec-Kit 里的 Schema 三方对拍。我用过一个笨办法在 CI 里加了一条“契约对拍任务”每次联调构建自动把前端请求 mock 数据和后端响应真实数据都拉出来做结构比对字段不一致直接打印 diff。这个任务上线后联调扯皮时间缩短了至少一半。6.4 变更管理失控从“静默改码”到“规格变更单”最常见的失控场景是开发发现某个字段加个默认值更省事于是悄悄改了代码没改规格。后面做数据分析的人发现字段对不上查了三天最后发现是某次顺手改的。我们的对策是推行“规格变更单”。哪怕是加一个可选参数也要在需求条目库里建一条变更记录说明变更理由、影响范围、是否需要回填数据。变更单审批之后才允许改规格和代码。一开始团队会觉得繁琐但实施一个月后每个人都尝到了“翻变更记录就能定位线上问题”的甜头。有一次线上订单状态异常我们花了十分钟就锁定是某个变更单引入的支付回调顺序问题而不是像以前那样满地找日志。还有个隐藏收益是这些变更单沉淀下来以后成了团队的能力地图。哪个模块最容易变、哪个需求总被返工拉一张变更统计表就清清楚楚后续改进都不用靠拍脑袋。7. 最后分享一点个人体会这套规格驱动开发加 Spec-Kit 的玩法最大的价值不是“文档规范了”而是“团队不再靠记忆和直觉协作”。我踩过不少坑最深刻的体会是需求分析不是问得越细越好而是要问出“可校验的边界”。用户思维让你问对人系统思维让你问全模块工程思维让你问准节奏而规格驱动开发让你把问到的答案固定成契约。如果你正准备在团队里推这套东西我的建议是别贪大先挑一个迭代周期里最核心的一条链路试水。把那条链路的规格写到 CI 能自动校验的程度让团队感受一次“跑绿了就是真的对齐了”的体验后续推广会顺畅得多。工具永远不完美但“唯一事实来源”的理念一旦立住很多扯皮自然就消失了。
阅读完成 · 觉得有帮助?
咨询建站