工程师估两周,主管报一周,会上承诺三天。三级之间没有一个人撒谎,每一级都觉得自己在做"合理修正"。结果是一个技术上还有一周工作量的任务,被对外承诺成三天,然后在第三周才交付,且交付时所有人都认为"估时不准"。
问题不在谁乐观,在估时每经过一层就被处理一次,而没有任何一层负责记录"被处理掉了多少"。
1. 压缩发生在哪三步
| 机制 | 每层在想什么 | 实际动作 | 后果 |
|---|---|---|---|
| 余量被视为虚高 | "工程师总会加 padding" | 按经验打折 | 折扣逐层叠加 |
| 只记得最好情况 | "上次类似的事很快就完了" | 用最乐观先例替代本次判断 | 忽略本次特有风险 |
| 承诺压力反向传导 | "先答应,再想办法" | 把谈判目标当成估时输入 | 估时被目标反向决定 |
第三行是根因:当"报多少"与"能不能做到"绑在一起考核,报数就从判断变成了谈判。谈判出来的数字无法用于排期,只能用于对外表态。
// 一次典型的逐层压缩,注意每一层的动作都"合理"
工程判断 10 工作日 // 含已知风险与联调
团队内部 8 工作日 // 去 20% 余量,"大家都这么干"
部门汇报 5 工作日 // 去联调,"联调可以并行"
对外承诺 3 工作日 // 取整、留好印象
实际交付 12 工作日 // 风险在末期集中兑现
2. 三种口径,向上该报哪个
估时从来不是一个数,是三个数加一个分布。只报一个数,接收方只能自己补另外两个——通常补成最好的那个。
| 口径 | 含义 | 适用场合 | 误用后果 |
|---|---|---|---|
| 最可能 | 一切按计划时的工期 | 内部任务分解 | 单独对外使用必然延期 |
| 乐观 | 顺利情况 | 压缩选项评估 | 被当成承诺 |
| 悲观 | 含已知风险 | 排期与缓冲测算 | 被当成"能力不足" |
| 区间 | 悲观–乐观之间 | 向上汇报与对外承诺 | 需要有解释成本 |
向上汇报建议用区间 + 一句风险说明,而不是给一个点值。点值一旦出口,就变成了契约,往后所有讨论都在围绕"为什么没做到",而不是"风险在哪"。
3. 去余量为什么必然发生
只要存在"报得少显得能干"的激励,去余量就会发生。这不是纪律问题,是结构问题。代价是可预测的:延期不在过程中出现,而是在末期集中爆发。
| 阶段 | 有余量时的形态 | 去了余量的形态 |
|---|---|---|
| 前 60% 时间 | 按计划推进,略慢 | 看起来更快,进度领先 |
| 60%–85% | 消化联调与返工 | 开始"还有一点" |
| 末期 | 正常收尾 | 风险集中兑现,一次性延期 |
| 汇报 | 偏差小、可解释 | 突变式延期,无人预警 |
第二种形态最伤信任:前两周一切正常,第三周突然说还要两周。接收方得到的结论是"估时不可信",而实际问题是"风险被前置隐藏"。
4. 不确定性与误差的关系
新领域、新依赖、新人的估算误差天然更大。此时压缩余量不是"更精确",而是放大方差:期望值不变,尾部变长。
| 任务类型 | 典型误差量级 | 压缩余量的效果 |
|---|---|---|
| 做过多次的同类改动 | 小,±20% 内 | 影响有限 |
| 熟悉领域的新功能 | 中,±50% | 尾部开始变长 |
| 新框架/新依赖首次接入 | 大,可能数倍 | 方差爆炸,几乎必然错过 |
| 探索性研究 | 不可估 | 压缩等于取消任务 |
第三、四行不该进入"估时—承诺"链条,应该进入时间盒机制。
5. 粒度决定可信度
估算的可信度随粒度衰减。超过某个长度之后,所谓的估时只是把不确定性写成了一个看起来很精确的数。
| 粒度 | 可信度 | 建议处理 |
|---|---|---|
| 半天以内 | 高 | 不必正式估,直接做 |
| 1–3 天 | 中高 | 可作为排期单位 |
| 1–2 周 | 中 | 必须拆到 3 天以内再承诺 |
| 超过 2 周 | 低,基本是猜 | 拆分成里程碑,只承诺第一个 |
一条实用规则:要承诺一个超过两周的任务,先把它拆成能被单独验证的三段,然后只对第一段给出日期。后面两段的日期在拆解完成后再给,这样承诺的准确度会显著上升而不需要更聪明的估算。
6. 缓冲放在哪
两种放法,效果差别很大。
| 放法 | 形态 | 优点 | 缺陷 |
|---|---|---|---|
| 逐项 padding | 每项加 20% | 单任务安全 | 总和远超真实需要,且被逐层扣掉 |
| 集中缓冲 | 在迭代或项目尾留一段 | 谁需要谁用,可观测消耗 | 需要有人守,容易被挪用 |
| 不设缓冲 | 直接按最可能排 | 数字好看 | 任何波动都变成延期 |
推荐集中缓冲,并让它的消耗可见:
// 缓冲消耗率是最有用的早期信号,比"进度百分比"可靠
缓冲总量 = 项目总工期 × [10%, 20%] // 按不确定性档位取,不是拍脑袋
消耗超 50% 而剩余工作 > 50% → 触发预警,重新评估范围
消耗超 80% 而工作未收尾 → 砍范围,不要砍验证
逐项 padding 的真实问题:它对上会被当成虚高扣掉,对下会被成员当成可支配时间用掉,两头都留不住。
7. 估时与承诺是两件事
| 维度 | 估时 | 承诺 |
|---|---|---|
| 性质 | 内部判断工具 | 对外契约 |
| 谁负责 | 执行者 | 承诺方(通常是主管) |
| 允许变化 | 随认知更新 | 变更需走流程并通知 |
| 出错后果 | 修正模型 | 失信,需要补救 |
| 正确用法 | 反复更新 | 尽量少给、给得晚 |
混淆两者就会出现最坏组合:用一次性的估时去做对外承诺,又不允许估时更新。此时团队被锁在一个早期最不准确的数字上,且没有合法途径调整。
变更承诺的重点不是审批,而是尽早通知并给出选项——让对方做选择,比让团队自己扛更可信:
// 承诺变更的最小流程:早发现给三选一,晚发现只给二选一
T-5d 发现偏差 > 20% → 通知 + 三个选项(延期 / 砍范围 / 加人)
T-2d 才发现 → 只给两个选项(延期或砍范围),不拿加班当方案
未通知而直接延期 → 记为流程失效,与估算误差分开统计
8. 追责估时不准的后果
一旦"估算偏差"被追责,最优点策略立刻变成普遍高估。
| 措施 | 短期效果 | 长期效果 |
|---|---|---|
| 偏差大就扣绩效 | 报数保守 | 估时全面虚高,失去参考价值 |
| 要求精确到天 | 数字更细 | 精度提升、准确度下降 |
| 只奖按时交付 | 更努力压缩 | 隐藏风险、砍验证 |
| 复盘偏差但不追责 | 短期无感 | 模型逐季变准 |
第四行需要时间才见效,这也是它常被放弃的原因。判断它是否有效,看的是同一类任务的偏差是否收敛,而不是某一次是否准时。
9. 历史数据怎么用
历史估时的价值不在平均值,而在同类任务的实际分布。平均值会把"经常提前"和"偶尔翻三倍"混成一个看似正常的数。
// 按任务类型取历史偏差分布,看尾部而不是看均值
$ jq -r '.[] | [.type, (.actual_days / .estimate_days)] | @tsv' est.json \
| awk '{v[$1]=v[$1]" "$2} END{for(t in v) print t": "v[t]}'
// 关心 p50 与 p90 的差距:差距大说明该类任务不可按点值承诺
| 统计量 | 回答什么 | 用途 |
|---|---|---|
| 中位数偏差 | 这类任务通常偏多少 | 校准下一轮估时 |
| p90 偏差 | 最坏情况偏多少 | 决定缓冲大小 |
| 偏差随粒度变化 | 拆小是否真的更准 | 决定拆分策略 |
| 按人分别看 | 谁系统性低估 | 私下校准,不公开排名 |
最后一行要谨慎:按人统计只用于一对一校准,一旦公开就变成考核,数据随即失真。
10. 校准的做法
// estimate-log.yaml:每条一行,字段少但必须填
- task: 支付回调幂等改造
type: refactor-existing // 类型决定可比性
estimate: {likely: 6, optimistic: 4, pessimistic: 12}
committed: 8 // 对外承诺值,单独记
actual: 11
slip_found_at: day-9 // 延期是在第几天被发现的
slip_found_at 是最容易被漏掉也最有用的字段:它区分"估错"和"发现太晚"。多数延期不是估错,是发现得晚,而这两者的对策完全不同——前者改模型,后者改预警节奏。
11. 症状对照
| 症状 | 更可能的根因 | 先动哪 |
|---|---|---|
| 每个季度都有末期集中延期 | 余量被逐层扣掉 | 集中缓冲 + 缓冲消耗预警 |
| 报数越来越乐观 | 承诺压力反向传导 | 把估时与考核解绑 |
| 估时普遍虚高 | 曾经因偏差被追责 | 改追责口径为复盘收敛 |
| 小任务准、大任务全错 | 粒度问题 | 超过两周强制拆分 |
| 目标一变全盘重排 | 没有区分估时与承诺 | 建立承诺变更流程 |
12. 边界
| 场景 | 为何正式估时流程收益低 | 该做什么 |
|---|---|---|
| 任务小于半天 | 估时成本接近任务本身 | 直接做,记账即可 |
| 完全重复性工作 | 已有稳定分布,无需再估 | 用历史 p50 直接排 |
| 探索性研究 | 结果未知,估时无意义 | 给时间盒,到点汇报发现 |
| 强外部截止的合规任务 | 日期不由估算决定 | 反推范围,砍需求 |
最后一行值得强调:当日期已经由外部决定时,估时的作用不是"算出日期",而是"算出在这个日期内能做多少"。方向反过来,整个链条就必然失真。
13. 自测
- 逐层压缩的三个机制中,哪一个使报数从判断变成谈判?
- 向上汇报为什么要用区间而不是点值?
- 去了余量之后,延期为什么集中在末期爆发?
- 集中缓冲与逐项 padding 的差别在哪,为什么前者更抗扣减?
slip_found_at这个字段能区分哪两种问题?- 外部截止日期已定的任务,估时的正确用途是什么?