选型不是挑一个能赢的,是把会输的先划掉。
一、四十分钟定下的框架,第五个月重写了六个模块
2025 年 8 月,陆远的产品写到第二个月。周五晚上,他把三个候选框架的 README 并排开了三个窗口,看了两份 benchmark 截图,四十分钟后选定 C:语法最新、示例最漂亮、讨论最热。第五个月,C 的核心库停更满 14 个月,仓库里也没有主版本迁移指南,他只能把已经写好的 6 个模块重写一遍,每个模块 18 小时。
以下情境为教学假设,人物、引语和数字不代表经核实的真实案例。
那次返工没有出现在任何一次发布记录里,因为它吃掉的是本该用来做功能的时间。108 小时相当于两周半的工程时间,而这 108 小时本可以用一次 8 小时的选择流程换掉。
选型的成本不在选的那几天,而在押错之后的返工。 大多数人选型时比较的是「哪个更好用」,真正该比较的是「哪个错了以后更便宜」;前者是偏好,后者才是可以记账的成本。
判据必须在半小时内能判定。 需要读完三十页文档、跑完一整套 demo 才能打分的判据,在实际决策里等于没有;它只会把决定推迟到某个更疲惫的晚上。
排除法的顺序是先划掉不可逆的,再比较会变的。 运行时、升级退出、许可这三项一旦错,代价是重写;运维方式与外包难度错了,明年还有机会改。
二、八个判据:每条只给 0、1、2
八个判据覆盖的是「选错以后有多贵」,不是「用起来有多爽」。每条只给三档:2 分是明确有利,1 分是可接受但有代价,0 分是这条上有硬伤。八条乘以三档,一共 24 格。
| 判据 | 0 分(硬伤) | 1 分(可接受) | 2 分(有利) |
|---|---|---|---|
| 分发与运行时 | 需要用户自装运行时或自建环境 | 单文件或容器可分发 | 一条命令启动,托管平台原生支持 |
| 语言熟悉度 | 没写过,语法与惯用法都要现学 | 写过示例,没写过生产项目 | 写过生产项目,能预估坑在哪 |
| 运维与托管 | 只能自管服务器 | 有托管但要手工配置 | 托管成熟,配置即部署 |
| 生态与关键库 | 支付、邮件、对象存储都要自己写 | 六类里有一半现成 | 六类关键库都有维护中的实现 |
| 升级与退出 | 无迁移指南,核心库停更 | 有指南但要跨两个大版本 | 有指南、有 codemod、有长期支持 |
| 许可与合规 | 许可与商业分发冲突 | 许可清楚但有条款要读 | 宽松许可,无附加条款 |
| 外包可得性 | 本地找不到会的人 | 能找到但报价明显偏高 | 招聘市场上供给充足 |
| 调试与可观测 | 出错只能打日志猜 | 有堆栈但没有追踪 | 断点、性能剖析、结构化日志齐全 |
三档不是偷懒,而是刻意的:
- 0 分不等于自动出局,只有落在不可逆项上的 0 分才是。运维方式掉到 0 分还能明年换托管,升级退出掉到 0 分只能重写。
- 三档让 24 格能在一张纸上手算,也让「差一分」有具体含义:差的是某一项从可接受掉到有硬伤,而不是评分人的心情。
- 不给判据加权重。一个人的项目里,权重只会把 0 分平均掉;该做的是先看有没有 0 分,再看总分。
八条里最容易自欺的是「生态与关键库」。把「社区活跃」换成「六类关键库各自有没有维护中的实现」,判据就从一句感觉变成了半小时内能查完的事实。
判据的顺序也有讲究:把「升级与退出」「许可与合规」放在前半段,让不可逆项尽早暴露;把「调试与可观测」放最后,因为它最容易被工具的宣传页影响。
三、三个候选:24 格打分与两项决胜
三个候选的形状不一样:A 是成熟全栈框架,约定齐全,代价是笨重;B 是轻量框架加自建,自由度高,代价是每一层都要自己选;C 是新潮但生态薄的框架,写起来最快,代价是没人替你兜底。
| 判据 | A 成熟全栈 | B 轻量 + 自建 | C 新潮薄生态 |
|---|---|---|---|
| 分发与运行时 | 2 | 2 | 2 |
| 语言熟悉度 | 2 | 2 | 1 |
| 运维与托管 | 1 | 0 | 1 |
| 生态与关键库 | 2 | 2 | 1 |
| 升级与退出 | 2 | 1 | 0 |
| 许可与合规 | 2 | 2 | 2 |
| 外包可得性 | 2 | 1 | 0 |
| 调试与可观测 | 1 | 2 | 1 |
A 拿到 14 分,B 12 分,C 8 分。C 的 0 分落在「升级与退出」:核心库停更 14 个月,仓库里没有主版本迁移指南。这一项不可逆,所以 C 在第二轮之前就被划掉——排除的依据是那一格 0 分,而不是总分排序;即使 C 靠其他项把总分追到 12 分,这一格仍然足以让它出局。
剩下的 A 与 B 只差 2 分,而且差异集中在两项上:运维与托管 A 1 分、B 0 分;外包可得性 A 2 分、B 1 分。这两项正好是未来十二个月会变的——托管平台会变,招聘市场也会变。另外两项有差异的(升级与退出 2:1、调试与可观测 1:2)方向相反、互相抵消,不构成决策依据。
4 小时的 spike 不是做 demo,是验证四条必经路径。代码控制在 200 行以内;超过 200 行说明你在提前写业务,验证结论会失真。
| 路径 | 最小验收动作 | 不通过就换的理由 |
|---|---|---|
| 登录 | 用真实会话中间件走通登录与登出 | 框架没有可替换的会话层 |
| 列表 | 从数据库读 50 行并分页渲染 | 分页要自己写 ORM 才有 |
| 后台任务 | 注册一个每 5 分钟执行的任务并看到日志 | 任务只能靠外部 cron 触发 |
| 一次部署 | 从空环境部署到可访问,记录耗时 | 部署超过 10 条手工命令 |
任一条走不通,当天换候选,不再补做第二轮评分。这一步的意义是:把「文档里看起来可以」变成「我亲手跑通过」,而 4 小时足够暴露路径级的问题。
spike 的实际耗时也要记进 ADR。4 小时是预算,不是标准答案;真花了 6 小时,说明候选的路径比想象中长,这个偏差本身就是选型信息。
四、复算:13.5 倍与 25% 概率下的期望
24 格 = 8 个判据 × 3 个候选
A = 2+2+1+2+2+2+2+1 = 14 / 16
B = 2+2+0+2+1+2+1+2 = 12 / 16
C = 2+1+1+1+0+2+0+1 = 8 / 16
A 与 B 的差 = 14 − 12 = 2
运维与托管差 = 1 − 0 = 1
外包可得性差 = 2 − 1 = 1
两项合计 = 1 + 1 = 2
返工 = 6 个模块 × 18 小时 = 108 小时
选型 = 4 小时列判据 + 4 小时 spike = 8 小时
108 ÷ 8 = 13.5
期望返工 = 108 × 25% = 27 小时
27 ÷ 8 = 3.375
13.5 倍是「一定选错」时的比值:花 8 小时,省 108 小时。这个数字不需要精确到小数,它只需要说明量级——选型流程的成本比一次返工低一个数量级。
25% 是给自己留的余地:即使你有七成把握,期望返工仍有 27 小时,是选型成本的 3.375 倍。反过来算,只有当选错概率低于 7.4%(8 ÷ 108)时,跳过这 8 小时才划算;而这个把握,没人能在读完三个 README 之后拿出来。
这个账也有边界。返工 108 小时的前提是错的栈已经写进 6 个模块;如果只写了一个模块,返工约 18 小时,8 小时的流程只值 2.25 倍(18 ÷ 8),仍然划算但不再压倒性。如果一个模块都还没写,先做 4 小时 spike 就够,不必列全表。
五、行动清单与复算验收
- 把八个判据写成一张表,每条先写 0 分长什么样,再写 1 分与 2 分。
- 给三个候选各填 8 格,填不出的格子记 0,不许留空。
- 先看「升级与退出」列,出现 0 分的候选当场划掉,不参与第二轮。
- 对剩下的候选只比较未来十二个月会变的两项,写出差几分。
- 用 4 小时做 spike,代码上限 200 行,超了就删回 200 行以内。
- spike 必须跑通登录、列表、一个后台任务、一次部署四条路径。
- 任一条路径走不通,当天换候选,不补做第二轮评分。
- 把判据表、24 格分数与 spike 结论写成一份 ADR,标注日期与候选版本。
验收标准:八个判据 24 格全部有分、被划掉的候选能指出具体 0 分项、spike 四条路径全通且代码不超过 200 行,三条同时满足才算选型结束。
验收的对象不是「选定了一个框架」,而是「留下了能复盘的证据」。半年后你怀疑自己选错时,能翻出当时的 24 格和四条路径记录,而不是只剩一句「当时觉得它挺好」。
如果三条里有任何一条没做到,先别开始写业务代码。你省下的不是 8 小时,是把返工概率重新交回给运气。
使用边界与实操验收
候选少于两个时不要用这套表。 只有一个可行选项时,八条判据会退化成给既定结论找理由;这时该做的是写清楚「为什么只有一个」,而不是打分。
硬约束要先于打分。 合规、支付牌照、数据驻留这类要求不接受 1 分,它们非 0 即 2;先把这类候选划掉,再进 24 格,否则高分会让不合规的候选活到第二轮。
spike 通过不等于选型正确。 200 行只覆盖四条路径,覆盖不了性能、并发与长尾错误;它证明的是「这条路能走通」,不是「这条路好走」。
这套方法不适用于已有流量的迁移。 迁移的成本主要在数据、用户与兼容期,选型表只算了新代码的返工;那种场景该用 07 的 strangler 做法,而不是重新选一次框架。
什么时候该停下来。 如果两个候选分差不超过 2 分且都没有 0 分,说明判据已经没有区分度;随机选一个,把省下的时间放进 spike 与上线后的观察窗口。
关键参考与核验范围
核验日期:2026-10-26。以下文档用于核对概念与规则,本文所有数字均取自全组教学基线,不取自这些文档。
- The Twelve-Factor App :用于核对运行时、配置与部署边界的通用概念。
- TechnicalDebt :用于核对「返工即利息」这一表述的边界。
- Architecture Decision Records :用于核对选型结论的存档格式与最小字段。
引用口径。 三份文档只用于确认「十二要素」「技术债作为利息」「决策记录格式」这三个概念的原始表述;候选分数、返工小时与选错概率均来自本文的教学基线,不来自文档。
核验范围。 上述三个入口在 2026-10-26 实测可公开访问(HTTP 200);未核验各项目的最新版本、价格与配额。
如何自行复核。 用你的八条判据重填 24 格,再用「模块数 × 单模块返工小时 ÷ 选型小时」复算倍数;若结果低于 3,说明你的返工面太小,可以把流程压缩成一次 spike。
系列导航
- 下一篇:单体优先:九个模块、一条依赖方向与一次边界检查
- 回到目录:一个人的架构:技术选型、模块边界与演进
- 相关阅读:独立开发的工程与技术策略 、系统架构设计专题
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。