1. 这个项目是怎么从“小改动”长成“大工程”的
我最近刚结束一个内部系统的客户卡片优化项目,原计划两周交付,结果前后耗了一个半月。项目的起因到现在听起来都很普通——运营同学提了一句“把客户卡片做得好看一点,信息全一点”,于是我们排了个还算保守的工期:需求梳理4人日,后端开发5人日,前端开发5人日,联调测试4人日,再加2人日缓冲,总共20人日,差不多12个工作日就能上线。
但实际情况完全不是这样。最终这个项目投入了69个人日,按综合人力成本1200元/人日来估算,直接成本约82800元,是原计划24000元的3.45倍。真正让我难受的不是超支,而是回头复盘时发现,大部分成本都花在了“猜业务方想要什么”和“推翻已经做完的东西”上,技术本身反而没那么难。换句话说,需求边界不清不是“多花一点时间”的问题,它是在项目一开始就埋下了一颗雷。
为什么会变成这样?当时团队里产品、后端、前端一共三个人参与,业务方是运营小组。我们之所以没有在一开始把需求边界问清楚,是因为大家都觉得这只是个页面优化型的小改动,不值得兴师动众开两次评审会。后来我才意识到,越是看起来“小”的需求,越容易在边界上翻车,因为没人会认真定义“小”到底是什么范围,“全”到底指哪些字段,“好看”按什么标准验收。
1.1 一句话需求为什么会成为返工的起点
“客户卡片优化,信息全一点,展示好看一点”就是最原始的需求描述。这句话看起来有目标,实际上什么也没说,“好看”是主观审美,“信息全”没有字段清单,“优化”也没有说明哪些是本次要做的、哪些明确不做。三个人听到这句话,心里分别产生了三套不同的画面:后端想的是多拉几个接口把数据补齐,前端想的是重新设计卡片布局让视觉更精致,产品想的是跟运营再对一轮字段,最后做成一个信息层级更清晰的展示页。
这种“各自理解”的状态一直持续到开发中期才暴露出来。第一个版本做出来后,运营说不是这个意思,要的是能直接判断客户价值的卡片。于是我们又重新梳理需求、改原型、改接口、改前端、补数据。整个过程中最烧钱的其实不是改代码本身,而是每一次改版背后都要重新组织多方对齐,每次对齐都会产生新的分歧,分歧又带来新的改动。这类问题在需求文档里根本看不到,只在排期膨胀和团队情绪变差时才能感觉到。
这里想给所有做产品和技术的人一个经验:当需求只用一句话表述,并且这句话里找不到人、场景、数据口径和验收标准时,基本可以直接判定边界不清。这种需求不是“先做着再说”,而是“先做必然白做”。与其后面花三倍的时间补救,不如一开始就花半天把边界追问清楚,哪怕追问的过程会让业务方觉得啰嗦。
1.2 边界不清在项目里会表现出三种典型症状
我后来总结,需求边界不清通常跑不出三种症状:范围没定义、规则没定义、验收标准没定义。这三个症状在这个项目里恰好全中,而且互相叠加,让返工从一次变成了三次。
范围没定义的表现是:没人列出“本次要做”和“本次不做”的清单。我们默认“客户卡片优化”就是把信息展示得更完整,但运营心里想的是要能够在卡片上直接判断客户该不该跟进,这就多出了很多不在计划内的状态标签和提醒逻辑。规则没定义的表现是:关键字段的业务口径完全不一致。同一个“最近交易”,开发认为是指全部订单,运营认为应限定在近30天且必须区分已取消状态。同一个“客户等级”,后端当普通字段处理,运营希望它自动计算。验收标准没定义的表现则是:界面反复修改,运营每次反馈都是“感觉不对”“再大气一点”“按钮不够明显”,前端改了六轮,最后还是靠我们强行定义量化标准才收住。
这三类症状有个共同点:它们往往不会在需求评审阶段暴露,因为大家嘴上说的是同一件事,脑子里的画面却完全不同。等代码写完、页面出图,分歧才会集中爆发。所以建议每个项目在启动时都做一次“需求五问”自检,其中最关键的一问是:这个功能做完以后,用户应当看到一个什么样的页面,每一步操作之后页面如何变化,什么样的结果能被判定为“合格”。能当场答出来,边界才算是清楚的。
1.3 当时为什么没人站出来叫停
现在回头看,最让我后悔的是中间明明有多次机会可以叫停,但团队里的每个人都选择了往前走。原因主要有两个:一是怕显得不专业,项目已经启动了,突然说需求不清楚,好像是在否认自己前期的判断;二是大家当时都还抱着“先做出一个版本,让运营看到实物再反馈,我们根据反馈做调整”的侥幸心理。这种“用实物代替需求文档”的做法,在小项目里很容易被包装成敏捷迭代,实际上却把本该在文档阶段解决的问题,全部甩给了代码阶段。
我们项目里还出现过一次很典型的“评审流于形式”。产品拉了个需求评审会,运营讲了十分钟想要什么,大家问了几个问题就散了,没有形成任何书面结论。评审纪要里只写了“确认客户卡片增加最近交易、客户等级、跟进状态展示”,但“最近交易”的时间范围没写、“客户等级”的来源和计算规则没写、“跟进状态”是人工标记还是系统自动生成也没写。这种评审会开了等于没开。
所以后来我给自己定了一条规矩:需求评审没有形成明确的验收标准,就不算评审通过。所谓验收标准,不是“做得好看点”这种形容词,而是可观察、可测量、有明确边界的行为描述,比如“卡片上需要展示最近30天已支付订单数量,取消和退款订单单独打标,点击卡片能进入客户详情页”。看起来只是把需求说细了,但它能拦住绝大多数返工。
2. 三个引爆点:边界问题是如何一步步变成返工的
这个项目一共发生了三次明显的返工,每一次都对应一个当初没有定义清楚的问题。它们不是同一天发生的,而是在不同阶段相继引爆。
2.1 引爆点一:数据范围没定死,列表接口被重写
第一次返工发生在联调阶段。运营最初的诉求是“在客户卡片上展示最近交易”,我们后端理解成展示最近三个月的订单记录,于是按“订单创建时间倒序、取最近十条”的逻辑做了接口,前端也按这个逻辑设计了列表。结果运营看到demo以后说,我要的是“最近30天内已支付的订单”,还有取消和退款的状态也要显示出来,不然看不出这个客户近期是不是有异动。
这次返工看起来只是给接口加两个筛选条件,但实际上牵扯到卡片布局设计、列表字段调整、接口入参和返回结构变化、前端状态标签适配、还有测试用例重写。前前后后花了大概6个人日。问题不在改动量,而在于这种改动是在项目接近交付时才被提出来。数据范围被定义得太晚,错失了最便宜的修改窗口。
我从中总结出一个很朴素的原则:凡是需求里出现“最近”“最新”“全部”“部分”这类词,都必须强制追问具体时间范围、数量上限、排序方式和包含哪些状态。宁可多写一行字,也别让开发自己猜,因为开发猜的往往会和业务预期差很远。
2.2 引爆点二:同一个字段,三个人三种理解
第二次返工的引爆点是“客户等级”这个字段。后端一开始把它设计成数据库里的一个枚举字段,由运营手工修改,卡片直接展示。前端也按普通文本字段来做。但运营的真实期望是客户等级应当按规则自动变化:比如近30天成交金额超过某个阈值、退款率低于某个比例、跟进记录不少于几次,就自动升为高等级客户。产品经理理解的又不一样,以为这就是一个静态标签,不需要承担判断逻辑。
同一张卡片上,一个字段承载了三套完全不同的规则,等真正对到一起时,后端已经写完接口,前端已经排好版。最后只能把客户等级的计算逻辑单独抽成一个服务,重新定义数据来源和更新时机,再做一次历史数据的洗牌迁移。这次返工又花了差不多9个人日,比第一次还重。
这个字段问题的本质是“规则未定义”。在需求阶段如果多问一句“客户等级由谁维护、多久更新一次、有什么判断条件”,整个第二轮返工完全可以避免。现在我在做接口方案之前,一定会先确认字段的主数据来源:这个值是系统算出来的,还是人填的?是一次性的,还是周期性刷新的?更新以后历史数据变不变?这四个小问题,能提前干掉一大半“字段口径不一致”的坑。
2.3 引爆点三:主观验收标准,让界面改了六轮
第三次返工扩散到了前端,原因是运营对视觉效果的验收标准非常主观。第一次交付“客户卡片”后,运营说“按钮不够明显”,前端把按钮放大加粗;第二次说“重点信息不够突出”,前端把字号又改大一号;第三次说“整体不够大气”,这回前端已经不知道该怎么改了,只能先截图让运营挑。前前后后改了六轮,每次改动都不大,但每次都要重新走一遍自测和回归,累计消耗也不小。
最后我们实在受不了,拉着运营在会议室现场确认了一条验收标准:按钮必须出现在卡片右上角,在任何设备宽度下都不能被遮挡;按钮背景色与页面背景色的对比度要达到4.5比1;按钮上能直接看到“跟进”两个字。这条标准听起来有点死板,但它终结了所有“凭感觉验收”的争论。之后的界面调整都围绕这几个可量化的指标来讨论,再也没出现过“再明显一点”这种循环。
主观验收标准的可怕之处在于它没有终点。只要判断依据是感觉,任何一版都可能在下一轮被打回。要解决这个问题只有一个办法,把形容词变成数字和条件。设计层面可以量化颜色、尺寸、位置、对比度;业务层面可以量化字段、状态、跳转动作;逻辑层面可以量化超时时间、刷新方式、空数据展示。任何一个功能,只要验收标准能被写下来,它就能被执行。
3. 一次返工到底花了多少钱:账能算多细就多细
很多人觉得返工的成本没法算,只能感慨“浪费了很多时间”。实际上只要拆开看,成本是可以落到人日上的。这次项目我按阶段做了个简单的人力投入表,虽然不精确,但足以说明问题。
3.1 人力成本明细:从原计划到实际投入
我按照“需求梳理、后端与接口、前端展示、联调测试、数据整理与发布支持”五个阶段做了拆分,分别记录原计划、第一版实际投入和返工新增投入。需要说明的是,这里的数字不包含产品经理和运营的参与时间,只统计研发侧的直接投入,即便如此对比也已经足够扎眼。
| 阶段 | 原计划(人日) | 第一版实际(人日) | 返工新增(人日) | 合计实际(人日) |
|---|---|---|---|---|
| 需求梳理与原型 | 4 | 6 | 8 | 14 |
| 后端与接口开发 | 5 | 10 | 9 | 19 |
| 前端展示开发 | 5 | 8 | 8 | 16 |
| 联调与测试 | 4 | 7 | 6 | 13 |
| 数据整理与发布支持 | 2 | 4 | 3 | 7 |
| 合计 | 20 | 35 | 34 | 69 |
我的直观感受是:返工新增的34个人日,比第一版实际投入还接近总量的一半。第一版虽然也有边界漂移,但好歹做出了东西;返工阶段则是把已经做出来的东西推翻重来,这种损耗几乎没有产出增量,纯粹是在为最初的模糊买单。如果按1200元/人日折算,这次返工直接人力成本约40800元,整个项目最终成本超过原计划近5.9万元,而其中一半花在返工里。
这里我强烈建议大家在项目结束后做一次同样的拆账。不需要精确到财务级别,只要把“原计划”“第一版实际”“返工新增”三列数字填出来,摆到项目复盘会上,比任何警告都有用。数据一旦被摊开,业务方会直观看到“模糊一句话”对应多少成本,下次提需求时也会下意识更谨慎。
3.2 看不见的隐性成本,往往比账面贵三倍
上面的人力账还只是直接成本,隐性成本更高。第一阶段晚上线一个月,运营团队原计划用“客户卡片”支持月底客户分层回访,结果只好继续用旧的Excel表手工处理,整整一个月的时间被打散。更麻烦的是,因为返工期间反复调整接口和字段,原先依赖这个卡片页面的另外一个数据周报功能也跟着阻塞,等于用一个模糊的需求拖住了两个交付任务。
团队信任也在被消耗。前两次返工时,运营和开发的关系还算客气,到了第三次,大家开会已经明显带着防备。运营觉得开发总是做错,开发觉得运营说话不算数,产品夹在中间两头安抚。这种情绪成本不会出现在项目账本里,但它会影响后续所有协作效率。我们后面再做下个需求时,运营会刻意多写几句背景,开发也会反复确认,看着是变谨慎了,实际上是双方都不愿意再为边界不清承担无谓成本。
我常用一个比喻解释隐性成本:返工就像装修时改水电,改一次不仅要多付材料费,还要赔偿已经贴好的瓷砖和刷好的墙。账面支出只是拆除费,额外的时间、等待、焦虑、信任损耗才是真正的大头。所以复盘项目时,不要只看“增加了多少人日”,也要记录“哪些关联需求被延迟了”“团队关系发生了什么变化”“下次沟通成本是变高了还是变低了”。
3.3 一个可以用来提前预警的粗算公式
后来我把这次的经验简化成一个预警公式,用来在项目早期判断需求边界是否已经失控。公式是:返工风险成本约等于“未明确需求点数量×信息传递次数×平均参与人数×需求变动周期”。举这个项目的例子:未明确的需求点至少有三个(交易范围、客户等级、验收标准),每个点的信息传递次数在两次以上,平均参与人数三人,需求变动周期持续三周,那么风险成本就是3×2×3×3,等于54个人日级别。虽然这个计算非常粗糙,但它能快速给出一个直觉判断:当这个值超过团队可承受范围时,就应该立刻停下来重新对齐需求。
这个公式的价值不是精确预测成本,而是在需求一开始就提醒你:“这里有没有需要追问的点?”如果有,就当场追问,别让模棱两可的东西流到开发阶段。实际使用时,我还会做一个更朴素的检查:把需求文档里的名词都圈出来,凡是找不到准确定义的名词,都是潜在的风险点。名词越抽象,风险越高。边界清晰的需求,必然是由具体名词和动词组成的,比如“查询近30天成交订单”“展示退款状态”“点击跟进按钮跳转详情页”,而不是“优化客户信息展示”。
4. 返工过程中的真实困境与排查实录
很多人以为返工就是“把原来的代码删掉重新写”,实际遇到的麻烦比这琐碎得多。
4.1 最麻烦的不是重写界面,而是处理历史数据
当“客户等级”从静态字段变成动态计算规则后,最大的问题不是写新逻辑,而是旧数据怎么办。数据库里已经存了几千条手工维护的客户等级,新的计算规则一上线,这些旧值立刻失效。我们面临两个选择:要么保留旧等级再叠加一个新字段,让两张信息源共存;要么写一次性脚本把历史数据全部按新规则重算。最后选了后者,因为叠加字段会让卡片展示逻辑变得非常别扭。
写数据脚本本身不难,难的是定义重算规则。既然运营说要按“近30天成交金额、退款率、跟进记录”综合判断,那么这三个指标各自占多少权重、数据缺失的客户怎么处理、重算是一次性还是每天定时跑,这些规则在返工前根本没有定义。我们只能再拉运营开了一次规则确认会,结果会上发现运营自己也没完全想清楚,最后是产品帮着拍板定了一套简化版规则:近30天成交金额大于一万元且退款率低于10%的客户,标记为高等级,其余不变。
这种“帮业务补规则”的活儿特别耗人,因为在规则补完之前,所有代码都只能停在半空中。我后来在项目里养成一个习惯,凡是涉及历史数据的字段调整,先准备一个数据现状清单,列出存量数据量、字段空值率、取值分布、手工维护记录数。把现状摊到桌面上谈规则,会比漫无目的地对齐快很多。
4.2 已上线的页面要不要回退,是返工里最难决策的一环
第二次返工时,客户卡片其实已经上线了一个版本,部分运营同事已经在日常使用。我们一度想直接下线旧版、重做新版,但发现这个决定牵扯太多:已经有人在旧版里做过客户跟进记录,如果页面下线,这些记录的入口会消失;报表系统里还有脚本在定时读取卡片页的接口,接口如果改掉,报表也会跟着挂。最后只能采用“新旧接口并存、前端灰度切换”的方式,既保住旧逻辑的兼容,又逐步把用户切到新页面。
这个过程看着简单,实际上非常煎熬。我们每天都要确认旧接口还有没有调用方、新接口返回的数据是否完整、空值和异常有没有兜底。返工本身已经够烦,再叠加一套兼容逻辑,整个人都处于高度紧张状态。现在回想,如果一开始就把“客户等级”的规则问清楚,根本不需要这个并行期。
这类问题在项目初期很难预料,但可以用一个机制降低风险:任何接口对外提供时,都记录调用方清单和字段依赖关系。有了这个清单,改接口前就能快速评估影响面。我们这次属于运气好,只影响了一个内部报表;如果当时有几个第三方系统在调这个接口,返工代价还要翻倍。
4.3 返工时最容易爆发的三类争执,以及怎么按下去
返工期间团队里出现了不少争执,最典型的三类是:业务指责开发一开始不问清楚,开发指责业务没给需求;产品在中间当传话筒,两边的话都传但两边都不满意;还有一个是开发内部为了“要不要保留旧接口”吵得不可开交。吵到最后,纯粹是在为边界模糊的历史原因互相找补,对推进项目没有任何帮助。
我的处理方式是尽量把争执引导到“事实+影响+方案”的框架里。业务说开发没问清楚,就不用争论当时谁对谁错,直接列出这次返工的触发点和新增成本,让大家对着数字说话。开发内部对技术方案有分歧,就把两个方案的维护成本、上线速度、风险影响摆出来,用表格对比后投票,不允许凭个人偏好硬扛。产品在中间传话,也要求每次传话必须带原始需求原文,不能只转述“客户觉得不行”,必须明确是哪个字段、哪种场景、什么预期。
经历过这次返工,我特别认同一个原则:复盘时不要找人背锅,要找流程漏洞。人记性会模糊,情绪会平复,但流程漏洞如果不补,下次换一拨人依旧会踩同一个坑。所以后面对齐需求时,我们不再依赖谁记得快、谁记性好,而是全部落成文字,哪怕多写两句也认了。
5. 复盘之后,我们给需求边界上了几道锁
项目结束后,我没有立刻接新需求,而是带着团队花了大半天把这次返工的教训固化成了流程。现在团队内部对需求边界有一套自己的约束,虽然不敢说百分百杜绝返工,但至少再遇到类似“客户卡片优化”这种一句话需求时,大家会条件反射地停下来追问。
5.1 需求模板:把描述的出口堵住
我们重新设计了一份需求模板,要求所有需求必须回答五类问题:目标用户是谁、在什么场景下使用、每个数据字段的来源和口径是什么、交互反馈如何、验收标准是什么。以“显示最近交易”为例,按这个模板写下来会变成:目标用户是运营客服人员,在查看客户详情时看到近30天订单列表;订单数据来源于订单库,按支付时间倒序;已取消和退款订单显示状态标签;点击某一条订单可以跳转订单详情;验收标准是列表最多50条、分页加载、首屏能在1秒内打开。
这个模板没什么玄机,就是把容易遗漏的问题变得无法跳过。一开始运营会觉得烦,觉得我们“事多”,但真正跑了两三个需求之后,大家发现前期多花半小时填模板,能让后期少开三四次无效对齐会,慢慢也就接受了。
5.2 “不做清单”比“必做清单”更管用
这个项目给我们另一个启发是:一定要明确“本次不做什么”。返工阶段我们有无数次想顺手加功能:在客户卡片上增加备注快捷编辑、加一个客户趋势小图表、把页面改成可配置化……每一个听上去都很合理,但一旦放进来,交付时间又要往后推。后来我们立了一条规矩:需求方案里必须有专门的“不做清单”章节,比如“本版本不做导入导出、不做客户等级自定义配置、不做历史趋势图”,并且所有相关人员签字确认。
“不做清单”能有效压制范围蔓延。很多时候业务方不是故意要加需求,而是看到demo以后才想起来“原来这里还能加个功能”。如果事先没有明确不做什么,这种临时起意很容易变成新需求,把排期越撑越大。有了“不做清单”,我们遇到类似情况就可以翻出清单确认,确实超出范围的,就排到下个迭代再评估,而不是当场改需求。
5.3 变更流程要“贵”一点,但别挡住合理需求
返工次数多了以后,我们引入了变更申请机制。任何在开发中途提出的需求变更,必须填写变更说明,包括变更内容、影响到的模块、预计新增人日和上线时间变化。业务方每次提变更前都会先掂量一下是否真的有必要。这本来是个常识性的管理动作,但以前项目规模小,大家总感觉走流程太僵硬,结果反而吃了更大的亏。
当然,这个机制不能完全拦住紧急需求。前阵子有个上线前发现的合规字段,需要临时补在卡片上,时间窗口只有两个工作日。我们走的是紧急变更通道,产品经理、后端负责人、业务负责人在半小时内确认方案,当天就介入开发,最终赶在截止时间前完成。所以流程的目的是“让成本透明”,而不是“让做事变慢”。只要所有人清楚变更要付出什么代价,就不会随意变动边界。
5.4 我自己现在判断需求边界,就看三个问题
最后分享一个我自己一直在用的方法。拿到任何一个新需求,我都会先问自己三个问题:这个功能给谁用?用户做完哪一步算完成?什么场景明确不在本次范围内?如果三个问题都能当场给出明确答案,我就敢说这个需求边界是基本清晰的,可以直接进入技术方案;如果任何一个问题要犹豫超过30秒,我就会立刻约需求方做一轮澄清。
这三个问题看着简单,但在被返工教育之前,我很少认真去用。大多数模糊需求只要走完这套追问,都会变成可执行的描述。边界清晰的成本是前期的几分钟对话,边界不清的代价是后面几十个人日的返工。这个账,怎么算都划算。