微服务

一个迭代的完整开发流程

从需求评审到上线复盘,一个规范的迭代要经过七道关。这篇文章按时间顺序拆解每个阶段的具体动作、产出物,以及最容易出问题的环节。

一、为什么需要流程

小团队常说"流程太重会拖慢速度"。这话有一半是对的——流程的价值取决于它能否减少返工。

一个没有流程的迭代通常长这样:

产品口头说需求 → 开发凭理解写代码 → 测试凭感觉验 → 上线出问题 → 相互甩锅

问题不在于"慢",而在于返工成本被隐藏了:需求理解偏差导致重写、边界场景没考虑导致线上 bug、没有回滚方案导致故障持续时间长。

一套合理的流程,本质上是把这些问题提前暴露。

二、七个阶段

阶段 1:需求评审

输入:需求文档(PRD)、原型图 参与:产品、前端、后端、测试 产出:确认后的需求 + 接口方案初稿

这个阶段要做的事:

动作 目的
梳理业务逻辑 确认理解一致,不是"听懂了"而是"说得出"
确认边界场景 空数据、超限、并发、异常流程怎么处理
当场提疑问 有歧义当场问清,别带回去猜
评估技术可行性 有没有实现不了的点、需要提前调研的技术

最容易出问题的环节就在这里。 需求的歧义如果不在评审时澄清,就会在开发时变成"我以为",在测试时变成"这不是 bug",在上线后变成"需求本来就是这样"。

一些值得当场问清的问题:

  • 这个状态流转有没有逆向流程?(比如"已发货"能不能撤回"待发货")
  • 数据量级是多少?(决定要不要分页、要不要缓存)
  • 失败怎么处理?有没有重试、有没有人工介入?
  • 和历史数据怎么兼容?
  • 权限怎么控制?谁能看、谁能改?

阶段 2:任务拆解与排期

产出:任务列表 + 工时评估 + 交付时间

把大需求拆成可独立开发、可独立验证的细任务:

❌ 粗粒度:"实现订单模块"(无法评估工时,无法并行)
✅ 细粒度:"订单表设计(2h)" / "下单接口(6h)" /
          "订单列表接口(4h)" / "超时取消任务(3h)" / "单元测试(3h)"

拆解的两个作用:

  1. 让估时可信——估一个 40 小时的任务误差极大,估 5 个 8 小时的任务误差小得多
  2. 让风险可见——某个任务估不出来,说明技术方案还没想清楚,要提前调研

风险点要显式标记:依赖第三方接口、涉及数据迁移、需要压测验证的,都要在排期时标出来,而不是等到做的当天才发现。

阶段 3:开发

技术侧的顺序通常是:

① 设计数据库表  →  ② 定义接口  →  ③ 写业务逻辑
   →  ④ 写单元测试  →  ⑤ 本地自测  →  ⑥ 联调前端

先设计表、再定接口、最后写逻辑,这个顺序很重要。反过来做(先写逻辑,边写边加字段)几乎必然导致表结构反复改。

开发阶段的几个实践:

实践 作用
接口先定义 前后端可以并行开发,不用等后端写完
单元测试 覆盖核心逻辑和边界,尤其是金额、状态流转
本地自测 提测前自己先跑通主流程
代码评审(CR) 提交前走评审,发现设计和实现问题

代码评审不是走形式。有效的 CR 会关注:有没有并发问题、异常处理是否完整、SQL 有没有性能隐患、边界条件是否覆盖。这些都是作者本人容易忽略的视角。

阶段 4:测试

产出:测试报告、bug 列表

测试要覆盖的层次:

层次 内容
功能测试 主流程能不能跑通
边界测试 空值、极值、超长输入、特殊字符
异常测试 网络中断、依赖服务不可用、超时
并发测试 同时下单、重复提交
兼容性 不同端、不同版本

bug 要闭环:修复 → 回归验证 → 关闭。不能出现"改了但没验证"的状态。

一个容易被忽略的点:测试环境的数据要和线上接近。用三条测试数据验证过的分页逻辑,在十万条数据下可能完全不同。

阶段 5:上线准备

产出:数据库脚本、配置变更清单、回滚方案

这个阶段常常被压缩甚至跳过,但它直接决定了出问题时的恢复速度。

准备项 说明
数据库变更脚本 DDL 和 DML 要分开,大表加字段要注意锁表
配置变更清单 新增了哪些配置、默认值是什么
回滚方案 代码怎么回滚、数据怎么回滚
预发布验证 在预发布环境完整走一遍
依赖检查 新依赖的服务、中间件是否就绪

大表加字段是个经典坑:直接 ALTER TABLE 在大表上可能锁表几分钟。常见做法是先用 pt-online-schema-change 之类的工具,或者选业务低峰期执行。

阶段 6:生产上线

发布策略:

策略 做法 适用
停机发布 停服 → 部署 → 启动 内部系统、可接受停机
滚动发布 逐台替换,其余继续服务 集群部署的常规选择
蓝绿发布 新旧两套环境,切流量 要求快速回滚
灰度发布 先放量给部分用户 高风险变更
夜间发布 低峰期执行 影响面大的变更

上线后必须观察:

  • 应用日志有没有异常堆栈
  • 监控指标:QPS、响应时间、错误率、CPU/内存
  • 数据库:慢查询、连接数
  • 业务指标:下单成功率、支付成功率

观察期建议至少 30 分钟,高频业务要更长。很多问题不会在上线瞬间暴露,而是在流量爬升后才显现。

阶段 7:迭代复盘

产出:问题清单 + 改进项

复盘要回答三个问题:

  1. 这个迭代遇到了什么问题?
  2. 哪些是可以提前避免的?
  3. 下次怎么改?

复盘要聚焦流程,不聚焦人。"某某写了个 bug"没有价值,"为什么这个 bug 没被测试发现"才有价值。

三、分支管理

代码管理的基本规则是:禁止直接向主分支提交。

典型的分支流转:

feature/xxx   →   dev   →   release/预发布   →   master(生产)
  开发分支        测试        预发布验证          生产发布
分支 用途 谁能提交
feature/* 功能开发 开发本人
dev 集成测试 通过 CR 后合并
release/* 预发布验证 由负责人合并
master 生产 只接受 release 合并

主分支保护是硬性要求:开启分支保护、禁止 force push、必须通过 CR 才能合并。这些用 Git 平台的设置就能做到,不依赖自觉。

四、那些容易被压缩的环节

实际项目中,排期紧张时最先被砍掉的是下面这些——而它们恰恰是降低风险的关键:

被砍掉的 短期看 长期看
需求评审 省了半天 返工两天
单元测试 省了几小时 线上 bug 排查一天
代码评审 省了一小时 设计问题带到线上
回滚方案 省了半小时 故障持续几小时
复盘 省了一小时 同类问题反复出现

一个实用的判断标准:如果某个环节被砍掉后,出问题的成本远大于做它的成本,那它就不该被砍。

五、赶不上交付时间怎么办

这是工程实践中真实且高频的问题。合理的处理方式是切范围,而不是降质量:

第一步:把需求分成"核心闭环"和"边缘增强"

核心闭环:用户能走通主流程(比如"能下单并支付")
边缘增强:运营后台图表、非核心报表、边缘渠道适配

先保核心闭环,边缘的可以下个迭代补。

第二步:准备降级方案

如果某个功能没测完,可以用开关控制:

  • 先上线页面,但用配置开关把请求路由到兜底逻辑
  • 允许运营在后台临时手工处理少量数据
  • 新功能默认关闭,验证后再打开

第三步:调整人力

把熟悉这块业务的开发抽调去攻坚核心难题,其他任务交给能胜任的人。测试侧集中火力测核心路径。

第四步:尽早向上同步

这一步最关键。不要在截止日才说做不完,而是在发现偏差的第一时间就带方案沟通:

"如果必须当天上线,我们能交付 A 和 B,C 和 D 要延期一周。是否可以接受?"

带方案沟通,而不是只报问题——这是工程沟通里最重要的一条。

一个基本判断

"准时上线一个范围收窄的版本" 通常比 "延迟上线一个完整版本" 更符合商业逻辑。

但前提是:范围收窄是有意为之的决策,而不是质量滑坡的结果。两者的区别在于——前者有明确的边界和兜底方案,后者是"没测完就上"。

小结

  • 一个迭代的七阶段:需求评审 → 拆解排期 → 开发 → 测试 → 上线准备 → 生产上线 → 复盘
  • 需求评审是最容易出问题的环节,歧义不在这里澄清,就会在后面每一步放大
  • 开发顺序:先设计表 → 再定接口 → 最后写逻辑,反过来必然反复改表
  • 代码评审关注并发、异常、SQL 性能、边界——这些是作者本人容易忽略的视角
  • 上线准备不能省:大表加字段注意锁表,回滚方案要提前想好
  • 发布后必须观察(建议 ≥30 分钟),很多问题在流量爬升后才暴露
  • 分支管理:禁止直接提交主分支,主分支保护靠平台设置而不是自觉
  • 排期紧张时优先砍范围,而不是砍质量——先保核心闭环
  • 发现偏差要尽早带方案沟通,不要等到截止日
  • "准时上线一个收窄的版本"优于"延迟上线一个完整版本",但前提是收窄是主动决策

流程的价值不在于"规范",而在于把返工成本提前暴露。任何环节如果做它的成本低于不做它的返工成本,它就值得保留。

留下点什么

评论基于 GitHub Discussions(giscus)。在项目根目录配置.env.local填入 NEXT_PUBLIC_GISCUS_* 四个变量后自动开启。