初创团队如何用规范驱动开发实现高效协作
1. 什么是“规范驱动开发”?它真不是给大厂准备的PPT术语
Spec-Driven Development(SDD),中文常译作“规范驱动开发”,这个词刚听上去特别像那种挂在CTO办公室白板上的战略口号——高大上、抽象、带着点学术腔。但在我带过的6个早期创业团队里,它从来不是用来写汇报材料的,而是每天早上站会时,工程师盯着产品文档里那几行加粗的接口字段、前端同学反复确认的错误码定义、测试同学提前写好的边界用例表格时,所有人心里默认的那条“不许越界的红线”。它解决的不是“怎么写代码”的问题,而是“怎么让三个人在没有专职项目经理的情况下,还能同步对齐需求、不返工、不扯皮”的生存问题。
核心关键词——
spec(规范)
,在这里不是指ISO标准或RFC文档那种动辄几百页的庞然大物,而是一份轻量、可执行、版本可控、且被所有角色共同维护的“契约文本”。它可以是一份YAML格式的OpenAPI 3.0描述文件,可以是TypeScript接口定义+JSDoc注释组合的
.d.ts
文件,也可以是Confluence页面上用表格列清楚的“输入字段名|类型|是否必填|示例值|业务含义”的需求清单。关键不在形式,而在它是否具备三个硬性特征:
可读性(非技术人员能看懂)、可验证性(能自动生成测试或校验逻辑)、可追溯性(每个字段变更都能查到谁、何时、为什么改)
。我见过太多初创团队把PRD当spec用,结果开发到一半发现“用户头像URL支持HTTPS”这条没写清楚,后端默认只存相对路径,前端拼接出错,上线前两小时全员加班改;也见过用Figma设计稿当唯一spec的团队,设计师改了个按钮颜色,没人通知后端这个状态码要新增一个,结果埋下线上500错误的伏笔。Spec-driven不是增加流程负担,而是把那些本该在编码前就厘清的模糊地带,用最小成本固化下来。它最适合的人群,不是已经建立成熟流程的大厂,恰恰是资源紧张、沟通链路短、但容错率极低的早期创业公司——因为在这里,一次需求理解偏差,可能直接导致MVP延期两周,错过关键融资窗口。
2. 为什么初创公司比大厂更需要Spec-Driven?这不是反直觉,而是反常识
很多人第一反应是:“大厂流程重、人多、系统复杂,才需要spec来对齐吧?” 这是个典型的认知陷阱。真相是: 大厂有冗余人力、有专职BA、有成熟的变更管理流程、甚至有专门的“需求冻结期”,它们能靠组织能力兜底spec的缺失;而初创公司什么都没有,spec就是它唯一的“组织能力替代品”。 我用三个真实场景拆解这种不可替代性:
2.1 场景一:从0到1搭建支付网关,Spec是避免“技术债雪崩”的第一道防火墙
去年帮一家做跨境SaaS的种子轮团队重构支付模块。他们最初用Node.js快速对接了Stripe,但没定义任何规范,所有逻辑都散落在路由处理函数里。当需要接入PayPal时,后端同学直接复制粘贴了Stripe的代码,只改了API地址——结果PayPal返回的
payment_status
字段是
completed
/
failed
,而Stripe是
succeeded
/
requires_action
,前端按老逻辑判断,导致用户付款成功却显示“支付失败”。如果当时有一份YAML格式的
payment_result_spec.yaml
,明确约定统一返回字段
status: enum[success, failed, pending]
和
message: string
,那么Stripe和PayPal的适配器只需各自负责字段映射,核心业务逻辑完全复用。这份spec不到50行,却让后续接入Alipay、本地银行网关的工期缩短了70%。大厂可能用一套微服务治理平台自动校验字段,但初创公司买不起、也等不及,一份手写的spec就是最轻量的“契约式编程”。
2.2 场景二:产品、设计、开发三方协作,Spec是消灭“我以为”的翻译器
我们曾为一款教育App设计课程购买流程。产品经理在飞书文档里写:“用户点击购买按钮后,弹出支付弹窗,显示价格、优惠券、最终实付金额。” 设计师据此做了高保真原型,其中优惠券区域标注了“最多可选3张”。但开发同学实现时,后端API只返回了一个
discount_amount
数字,没传可用优惠券列表,也没传限制数量。结果前端只能硬编码“最多3张”,后来运营想临时改成“不限张数”,全链路都要改。如果当时有一份
checkout_ui_spec.json
,用JSON Schema明确定义:
{
"type": "object",
"properties": {
"available_coupons": {
"type": "array",
"items": { "$ref": "#/definitions/coupon" },
"maxItems": 3
}
}
}
那么后端就知道必须返回数组且控制长度,前端渲染逻辑自然解耦,运营策略调整只需改配置,无需发版。这里spec的价值,不是约束技术,而是把产品脑中的“我以为用户会这样理解”,翻译成机器可读的、各方无歧义的指令。
2.3 场景三:技术选型摇摆期,Spec是保持架构稳定的锚点
团队A在做实时协作编辑器,初期用Firebase Realtime DB,后来因成本考虑想切到自建WebSocket+Redis。如果没有spec,迁移就是一场灾难:Firebase的
onChildAdded
事件语义和自建服务的
document_update
消息格式完全不同,前端要重写所有监听逻辑。但我们提前定义了
collab_event_spec.avsc
(Apache Avro Schema),规定所有协作事件必须包含
event_id: string
,
timestamp: long
,
payload: bytes
,且
payload
内嵌结构化数据。迁移时,后端只需保证新服务发出的消息符合Avro Schema,前端完全不用动——因为消费方只认schema,不认底层传输协议。大厂可能用Kafka Schema Registry强制校验,初创公司用一个
.avsc
文件+CI里的
avro-tools compile
命令,效果等价。Spec在这里,成了技术演进的“隔离层”,让团队敢于试错,而不怕推倒重来。
提示:Spec不是越多越好。初创公司的spec必须遵循“最小可行契约”原则——只定义当前迭代必需的、跨角色协作的关键契约点。一份覆盖全部100个API的OpenAPI文档,不如一份精准定义“用户注册”“登录态刷新”“支付回调”这三个核心流程的spec有用。我建议团队每周站会花10分钟评审spec变更,确保它始终是“活的文档”,而不是尘封在Git历史里的古董。
3. Spec-Driven落地四步法:从写第一行YAML到形成团队肌肉记忆
Spec-Driven不是买个工具就能跑起来的流程,它本质是一套协作习惯的养成。我在三个不同技术栈的初创团队(React+Node、Flutter+Go、Vue+Python)验证过这套四步法,平均4-6周就能让团队形成条件反射。关键不在于工具多炫酷,而在于每一步都解决一个具体痛点,让成员立刻感受到“这玩意儿真省事”。
3.1 第一步:选定“契约载体”,拒绝完美主义,先跑通再优化
载体选择的核心标准只有一条: 所有角色(产品、前端、后端、测试)能否在5分钟内看懂、修改、并验证修改是否生效? 基于这个标准,我淘汰了Swagger Editor(学习成本高)、Postman Collections(无法定义类型约束)、甚至GraphQL Schema(对非技术角色太抽象)。最终锁定三个轻量方案:
-
API契约 :OpenAPI 3.0 YAML文件(
.openapi.yaml)。优势是生态成熟,VS Code装Redocly插件,保存即生成交互式文档;openapi-generator能一键生成TypeScript客户端、Spring Boot服务端骨架;CI中用spectral做规则校验(如“所有POST接口必须有requestBody”)。我们团队用它定义所有外部HTTP接口,文件放在/specs/api/目录下,与代码同库管理。 -
前端组件契约 :TypeScript接口 + JSDoc注释(
.d.ts文件)。例如ButtonProps.d.ts:/** * @description 按钮组件属性契约 * @see https://confluence.example.com/button-spec * @example <Button size="large" variant="primary" onClick={handleClick} /> */ export interface ButtonProps { /** 按钮尺寸,影响padding和font-size */ size: 'small' | 'medium' | 'large'; /** 按钮样式变体 */ variant: 'primary' | 'secondary' | 'ghost'; /** 点击事件,必须提供可追踪的event_id */ onClick: (event: { event_id: string; target: 'button' }) => void; }产品在Confluence写需求时,直接引用这个文件路径;设计师检查UI时,对照
size枚举值确认是否支持“large”;前端开发时,IDE自动提示类型错误。契约就在代码里,零额外维护成本。 -
数据模型契约 :JSON Schema(
.schema.json)。用于定义数据库表结构、消息队列事件、配置中心参数。例如用户表契约user.schema.json:{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "required": ["id", "email", "created_at"], "properties": { "id": { "type": "string", "pattern": "^usr_[a-z0-9]{8}$" }, "email": { "type": "string", "format": "email" }, "status": { "type": "string", "enum": ["active", "inactive", "pending_verification"] } } }后端用
ajv库在入库前校验;前端表单提交前用@json-schema-form/core做实时校验;DBA用它生成建表SQL。一份schema,三方受益。
注意:不要试图一步到位。建议从最痛的一个点切入——比如后端总抱怨前端传参格式错,那就先用OpenAPI定义所有入参;如果UI走查总发现状态遗漏,那就先用TS接口定义组件props。让团队第一次尝到“改spec就能自动修复bug”的甜头,比开10场培训管用。
3.2 第二步:建立“契约即代码”工作流,让Spec成为CI/CD流水线的一环
Spec一旦脱离代码仓库,就会迅速失效。我们强制所有spec文件与对应服务代码同库、同分支、同PR。关键是在CI中加入三道自动门:
-
语法门 :
yamllint .openapi.yaml检查YAML格式,jsonlint user.schema.json验证JSON语法。失败则PR无法合并,杜绝“手抖多打个逗号”导致整个文档失效。 -
一致性门 :用
openapi-diff对比PR分支与主干的OpenAPI变更,自动生成差异报告。如果新增了/v1/users/{id}/deactivate接口,但没在changelog.md里记录,CI会失败并提示:“检测到新增接口,请更新变更日志”。这强迫团队养成“改spec必写日志”的习惯。 -
契约门 :最关键的一步—— 运行基于spec生成的测试用例 。我们用
openapi-backend库,将.openapi.yaml自动转换为Express中间件,模拟所有API行为。CI中启动这个mock服务,然后运行前端E2E测试(Cypress)和后端集成测试(Jest)。如果spec里定义了GET /users返回{ "data": [{ "id": "string" }] },但后端实际返回{ "items": [...] },测试立即失败。这意味着: spec不是文档,而是可执行的契约;违反spec=代码错误,必须修复。
这套CI流水线,我们花了3天搭建(用GitHub Actions),但它让团队对spec的信任度飙升。以前大家觉得“改个spec又不编译,随便写”,现在看到CI红了,第一反应是“我是不是改错了spec?”,而不是“测试环境挂了?”。契约真正长出了牙齿。
3.3 第三步:定义“契约变更协议”,让每一次修改都有迹可循、有据可依
Spec不是静态文档,它必须随业务演进。但初创公司最怕“随意改”,所以必须立下三条铁律:
-
黄金法则一:禁止直接修改生产环境spec 。所有变更必须通过PR发起,且PR标题强制格式:
[SPEC] [BREAKING|MINOR] api/v1/users.yaml: add email_verified field。BREAKING表示破坏性变更(如删除字段、改类型),MINOR表示向后兼容(如加字段、扩枚举)。CI会扫描标题,如果是BREAKING,则强制要求关联Jira任务ID和回滚方案。 -
黄金法则二:每个字段变更必须附带“业务上下文”注释 。在OpenAPI的
description字段里,不写“用户邮箱”,而写:“用户注册时填写的邮箱,用于发送验证码(见PR#123)和密码重置(见PR#456);若为空,则用户未完成邮箱验证流程”。这样,半年后新人接手,一眼明白这个字段为什么存在、影响哪些功能。 -
黄金法则三:建立“契约快照”机制 。每次发布正式版本(如v1.2.0),用脚本自动将
/specs/目录打包为specs-v1.2.0.tar.gz,上传至内部MinIO存储,并生成SHA256校验码。当线上出现诡异问题,运维同学一句curl -s https://specs.example.com/specs-v1.2.0.tar.gz | sha256sum,就能确认当前线上服务是否真的运行着标称的v1.2.0契约——这比翻Git历史快10倍。
我们曾用这套协议处理过一次危机:某次紧急热修复,后端同学绕过PR直接改了数据库字段名,导致前端调用失败。但因为spec快照存在,我们5分钟内定位到“线上实际运行的是v1.1.9契约,而非标称的v1.2.0”,立刻回滚数据库变更,避免了更大范围故障。契约快照,就是初创公司的“时间机器”。
3.4 第四步:培养“契约思维”,让Spec成为团队日常对话的语言
工具和流程只是骨架,真正的灵魂是人的习惯。我们通过三个动作,把Spec-Driven刻进团队DNA:
-
每日站会新增30秒“契约对齐” :每人只说一句:“今天我的工作是否会影响任何spec?如果有,我已更新PR并@相关人”。比如前端说:“今天改登录页,会新增
login_method: 'email' | 'phone'字段,PR#789已提”。后端听到,就知道要去实现这个字段。没有长篇大论,只有契约变更的即时广播。 -
Code Review强制检查项 :在GitHub模板中加入一条:“✅ 已检查本次变更是否需更新对应spec文件(路径:/specs/xxx)”。Reviewer不点勾,PR不能合并。刚开始大家嫌麻烦,但两周后,90%的PR都主动附带了spec更新,因为不更新,代码就合不了。
-
新人入职第一课:读懂spec,再碰代码 。我们给新人一个任务:用Postman调通
GET /health接口,但不给任何代码链接,只给/specs/api/health.yaml。他必须自己看OpenAPI定义,构造请求头、理解响应结构。完成这个任务,才算通过“契约入门考试”。这比讲1小时“我们为什么用Spec”有效得多。
实操心得:别指望一次培训就改变习惯。我们坚持了8周,每周五下午设为“契约健康日”:团队一起用
openapi-diff扫描所有spec,找出过期字段、缺失描述、不一致枚举值,当场修复。8周后,团队自发开始用$ref复用公共schema,用x-example补充真实业务示例——这才是Spec-Driven真正扎根的标志。
4. 规范驱动开发的实战细节:从OpenAPI字段设计到前端类型安全落地
Spec-Driven的价值,最终要落到每一行代码、每一个API调用、每一个UI渲染上。这里不讲虚的,直接拆解我们在真实项目中打磨出的、可直接抄作业的细节方案。这些细节,往往决定了Spec是沦为摆设,还是真正成为生产力引擎。
4.1 OpenAPI设计:如何写出既严谨又易用的API规范?
很多团队的OpenAPI文档写得像教科书,字段堆砌、示例缺失、约束模糊。我们总结出“三要三不要”原则,并附上真实案例:
-
要定义精确的枚举值,不要用
string糊弄
错误示范:status: type: string description: 用户状态正确做法:
status: type: string description: 用户账户状态。active=已激活,inactive=已停用,pending_verification=待验证邮箱 enum: [active, inactive, pending_verification] example: active为什么? 枚举让前端能直接生成下拉选项、做状态映射;后端用
enum可自动生成校验逻辑;测试同学能一键生成所有状态的测试用例。example字段更是神器——我们用openapi-sampler工具,基于example自动生成Mock数据,前端联调时再也不用手动构造{"status": "active"}。 -
要使用
allOf复用公共结构,不要重复造轮子
错误示范:在/users和/orders两个接口的响应里,都写一遍分页字段page,per_page,total。
正确做法:定义components/schemas/Pagination.yaml:Pagination: type: object properties: page: type: integer example: 1 per_page: type: integer example: 20 total: type: integer example: 156然后在各接口中复用:
components: schemas: UserListResponse: allOf: - $ref: '#/components/schemas/Pagination' - type: object properties: data: type: array items: $ref: '#/components/schemas/User'为什么? 一处修改,全局生效。比如运营要求分页
per_page最大值从100改为200,改Pagination.yaml一个文件,所有接口自动继承。 -
要为关键字段添加业务规则注释,不要只写技术类型
错误示范:email: type: string format: email正确做法:
email: type: string format: email description: | 用户邮箱地址。规则: - 必须为有效邮箱格式(RFC 5322) - 注册时强制验证(发送验证码邮件) - 修改时需二次验证(原邮箱收确认码) - 作为密码重置唯一凭证 example: user@example.com为什么? 技术类型(
string)告诉机器怎么处理,业务规则告诉人为什么这么处理。测试同学看到“修改时需二次验证”,立刻知道要写两条用例:修改邮箱未验证、修改邮箱已验证。
4.2 前端类型安全:如何让TypeScript成为Spec的天然延伸?
Spec写得再好,如果前端还是
any
乱飞,就前功尽弃。我们的方案是:
让TypeScript类型完全由OpenAPI生成,且保证100%可追溯
。
-
生成策略 :用
openapi-typescript(非openapi-generator)生成TS类型。原因:openapi-typescript生成的类型是纯类型声明(.d.ts),不带运行时代码,体积小、IDE友好;且它保留了OpenAPI的description和example,生成的类型注释就是spec原文。
命令:npx openapi-typescript https://localhost:3000/openapi.yaml --output src/types/api.ts --use-options --default-export生成的
api.ts里,字段注释直接来自spec:/** * 用户邮箱地址。规则: * - 必须为有效邮箱格式(RFC 5322) * - 注册时强制验证(发送验证码邮件) * ... */ email?: string; -
类型使用规范 :禁止手动写接口类型。所有API调用必须用生成的类型:
// ✅ 正确:使用生成的User类型 const user = await apiClient.get<User>('/users/{id}', { params: { id } }); // ❌ 错误:手动定义interface interface MyUser { name: string; }为什么? 手动类型必然滞后于spec。我们用ESLint规则
@typescript-eslint/no-explicit-any配合自定义规则,扫描代码中所有interface/type定义,如果文件名不包含generated,则报错。强制让开发者“拥抱生成,远离手写”。 -
错误处理契约化 :Spec不仅要定义成功响应,更要定义所有可能的错误。我们在OpenAPI中为每个接口定义
400,401,404,422,500响应:responses: '422': description: 请求参数校验失败 content: application/json: schema: $ref: '#/components/schemas/ValidationError' components: schemas: ValidationError: type: object properties: code: type: string enum: [invalid_email, password_too_short, duplicate_username] message: type: string field: type: string example: email前端调用时,错误处理逻辑就变成:
try { await apiClient.post('/users', userData); } catch (error) { if (isValidationError(error)) { // 类型守卫,由生成的类型提供 showFieldError(error.field, error.message); // 精准定位到出错字段 } }效果 :用户注册时邮箱格式错,前端直接在邮箱输入框下方显示“邮箱格式不正确”,而不是弹个笼统的“请求失败”。这就是Spec驱动的用户体验。
4.3 后端契约执行:如何让Spec不只是文档,而是运行时的守护者?
后端是Spec的最终执行者,也是最容易“阳奉阴违”的环节。我们的方案是: 用中间件把spec变成一道不可逾越的墙 。
-
请求校验 :用
express-openapi-validator(Node)或fastapi-openapi-validator(Python)中间件,在路由入口处自动校验:- 路径参数、查询参数、请求体是否符合OpenAPI定义的类型、格式、枚举、必填项。
-
如果spec定义
id是string且匹配正则^usr_[a-z0-9]{8}$,而用户传了123,中间件直接返回400 Bad Request,附带详细错误信息:“id must match pattern ^usr_[a-z0-9]{8}$”。
价值 :前端再也不用写“if (id.length < 8) return error”,后端也不用在每个控制器里写校验逻辑。校验逻辑集中、统一、可配置。
-
响应校验(可选但强烈推荐) :开启
validateResponses: true,中间件会在响应发送前,校验返回数据结构是否符合spec定义的200响应schema。虽然会带来微小性能损耗(<1ms),但它能100%杜绝“后端改了代码,忘了改spec”的低级错误。我们只在开发和测试环境开启,生产环境关闭。 -
动态契约生成 :对于高度动态的接口(如搜索API,支持任意字段组合),我们用
json-schema-faker根据search_request.schema.json自动生成海量测试数据,喂给混沌测试工具(如Chaos Mesh),模拟各种边界条件。这比人工写测试用例高效10倍。
常见问题速查表:
问题现象 排查思路 解决方案 前端调用API报 400,但后端日志没记录检查 express-openapi-validator中间件是否在日志中间件之前注册调整中间件顺序,确保校验日志先于业务日志 TypeScript类型生成后,IDE提示 Cannot find moduleopenapi-typescript生成的api.ts路径未被tsconfig.json的include包含在 tsconfig.json中添加"include": ["src/**/*", "src/types/api.ts"]OpenAPI中 example字段没生效,Mock数据全是nullopenapi-sampler默认不使用example,需加参数--use-examplesnpx openapi-sampler --use-examples --output mock-data.json spec.yaml团队抱怨“写spec比写代码还累” 检查是否在定义过度细节(如所有字段的 maxLength)遵循“最小可行契约”,只定义影响协作的关键约束;用 x-nullable: true代替nullable: true(OpenAPI 3.0 bug workaround)
5. 初创公司Spec-Driven避坑指南:那些没人告诉你的血泪教训
Spec-Driven听起来很美,但我在多个项目踩过的坑,远比教科书里写的多。这些教训,都是真金白银换来的,有些甚至导致过线上事故。分享出来,不是为了吓退你,而是帮你绕开那些本可避免的深坑。
5.1 坑一:把Spec当“需求文档”写,结果写成了天书
这是最普遍的误区。我见过一个团队,花两周写了3000行OpenAPI文档,覆盖了所有未来可能用到的API,连“用户注销设备”这种还没排期的功能都定义好了。结果呢?文档没人看,因为太厚;开发时发现spec和实际业务逻辑冲突,但改spec要走流程,干脆绕过spec写代码;最后文档成了“考古资料”,没人敢动。
我的解法
:Spec必须遵循“Just-in-Time”(及时制)原则——只定义
下一个迭代周期内必须交付
的契约。我们用Jira的“Sprint Backlog”视图,把每个用户故事(Story)拖到“Ready for Spec”列,产品同学必须在此列完成对应的spec片段(通常1-3个接口),才能拖到“In Progress”。这样,spec永远是“小而精”的,永远和代码进度严格对齐。一个迭代结束,spec文档增长不超过200行,团队毫无压力。
5.2 坑二:Spec和代码不同步,版本混乱成灾难
某次发布后,前端突然报错
Cannot read property 'name' of undefined
。排查发现,后端在
/users
接口的响应里,把
user.name
字段改成了
user.full_name
,但没更新OpenAPI文档。前端用旧spec生成的类型,还在访问
name
字段。更糟的是,Git历史里有5个不同分支的
openapi.yaml
,没人知道哪个是“权威版本”。
我的解法
:建立“单一事实源”(Single Source of Truth)。我们规定:
-
唯一权威spec
:只有
main分支根目录下的openapi.yaml是权威版本。 -
所有环境指向同一spec
:本地开发、测试、预发、生产环境,都通过环境变量
OPENAPI_URL=https://api.example.com/openapi.yaml加载spec(后端服务启动时下载并缓存)。 -
代码生成强制绑定
:CI中,
openapi-typescript命令的输入URL必须是$OPENAPI_URL,而不是本地文件路径。这样,如果生产环境的spec变了,前端构建就会失败,因为生成的类型和线上API不匹配。
一句话: 让环境决定spec,而不是让分支决定spec 。从此再没出现过“本地能跑,线上报错”的诡异问题。
5.3 坑三:过度追求自动化,忽略了人的因素
有团队迷信工具,搞了一套全自动流程:产品在Notion写需求 → Notion webhook触发脚本 → 自动生成OpenAPI → 自动提交PR → 自动合并。结果呢?产品同学为了“让脚本能解析”,把需求写成冰冷的JSON格式,失去了业务语境;生成的spec缺少
description
,全是
field1
,
field2
;PR合并后,没人Review,错误spec直接上线。
我的解法
:自动化只做“体力活”,不做“脑力活”。我们只自动化:
-
openapi-diff生成变更报告(体力:比对文本) -
openapi-typescript生成类型(体力:字符串转换) -
CI中运行基于spec的测试(体力:执行命令)
而 所有需要判断、决策、沟通的环节,必须由人完成 : - 产品写spec描述,必须用自然语言,解释业务意图(脑力)
- PR合并前,必须有人(通常是Tech Lead)Review,确认变更合理(脑力)
-
每周五的“契约健康日”,团队一起讨论spec是否还反映真实业务(脑力)
工具是杠杆,人是支点。没有支点的杠杆,一推就倒。
5.4 坑四:Spec成了甩锅工具,破坏团队信任
最危险的苗头是:后端说“你spec没写清楚,所以我的实现有问题”,前端说“你代码没按spec来,所以我的调用失败”。Spec本应是协作的桥梁,结果变成了互相指责的武器。
我的解法
:推行“契约共担”文化。我们在团队公约里写明:
- Spec是集体创作,不是产品单方面输出 。每个新接口的spec初稿,必须由产品、前端、后端三人一起在白板上画完流程、字段、状态机,再由产品整理成文。
- Bug归因,先问“spec是否覆盖此场景” 。如果没覆盖,责任在spec;如果覆盖了但实现不符,责任在实现者;如果覆盖了且实现正确但业务逻辑错,责任在需求本身。
-
每月复盘“契约失效案例”
。例如某次支付失败,根本原因是spec没定义网络超时后的重试策略。复盘后,我们立刻在
payment_spec.yaml里新增x-retry-policy扩展字段,并写入团队知识库。
效果 :当Spec从“考核标准”变成“改进工具”,团队才真正拥抱它。
最后分享一个小技巧:我们给每个spec文件加了一个
x-maintainer字段,例如:components: schemas: User: x-maintainer: "@backend-team" # ... 其他定义这样,当有人想改
User结构时,GitHub PR会自动@@backend-team,提醒他们评估影响。一个小小的扩展字段,让责任归属变得无比清晰。Spec-Driven的终极目标,从来不是写出完美的文档,而是让一群聪明人,在资源有限的情况下,用最简单的方式,达成最可靠的协作。它不性感,不炫技,但它像空气一样,当你拥有时习以为常,一旦失去,立刻窒息。
更多推荐
所有评论(0)