第 5 章 技术决策:从业务约束到技术方案
副题:为什么选这个、不选那个——以及为什么这个"为什么"是可以学会的
本章是全书的方法论中心。第 1 章我们拿到了地图,第 4 章我们把一句话需求翻译成了需求清单。现在需求清单在手,要开始选型了:语言用什么?框架用什么?数据库用什么?本章回答的不是"该选什么",而是"怎么选"——一个可以用在任何技术选择上的九步决策模型。
本章要建立的认知
- 技术选型不是"背答案",是从业务约束里推出来的;
- 九步决策模型:业务目标 → 业务约束 → 技术问题 → 候选方案 → 评价维度 → 方案选择 → 收益 → 代价 → 未来演进条件;
- 一句话记住它:约束是选型的输入,代价是选型的输出——决策包含"不做什么",且从不一劳永逸。
5.1 选型为什么这么难
先看一个你多半经历过的场景。
某个技术群里有人问:"社区交易类产品,数据库用 PostgreSQL 还是 MySQL?"半小时内,评论区分成两派:一边说"PostgreSQL 功能强、JSON 好用、事务靠谱";另一边说"MySQL 生态大、云厂商支持好、出问题一搜一堆答案"。双方各自贴出三四个"权威"链接,谁也说服不了谁。最后有人抛出一句:"跟着大厂走准没错,某大厂用的就是 X。"于是提问的人更迷茫了。
这就是选型难的真实样子:不是没有答案,是答案太多。PostgreSQL、MySQL、MongoDB、SQLite;React、Vue、Svelte;Node、Python、Java、Go——每一个选择都有人推荐、都有人踩过坑、都有成功的公司和失败的案例。1-3 年的开发者面对这种局面,最常见的应对方式是:
- 看招聘要求——"反正以后跳槽要会这个";
- 看 star 数和社区热度——"用的人多总没错";
- 看朋友/同事推荐——"他踩过的坑比我走过的路多";
- 看教程——"教程用什么我就用什么"。
这些方式不能说错,但有一个共同的毛病:它们都无法被论证。别人问你"为什么选这个",你只能回答"因为它火"或者"大家都这么用"。而"因为它火"不是一个技术理由——它解释不了你的业务为什么需要这个技术,也回答不了"业务变了之后要不要换"。
选型难,还难在第二个地方:选错的代价来得晚。语言、框架、数据库不是写错一行代码——它们是地基。地基选错了,不是当天就塌,而是半年后业务要加一个功能时,你发现"当初那个选择让这件事变得极其难做"。到那时候,迁移成本高得让人宁可忍受别扭。所以选型又是一个"决策时看不出好坏、事后才知代价"的典型问题。
本章要解决的就是这两件事:给选型一个可以论证的方法,让每个选择都能说清楚"从哪来、到哪去";同时把"事后代价"提前到决策时就想清楚。
还有一个心态层面的根源值得先拆掉:大多数人把选型当成考试,而不是设计。考试有唯一正确答案,考的是你知道得多不多;设计没有标准答案,比的是你在约束下的权衡好不好。把选型当考试的人,会一直焦虑"我是不是选错了"——因为总有一个"更好的答案"在别处;把选型当设计的人,关心的是另外两个问题:"我的约束分析全不全?我的代价清单诚不诚实?"这两个问题是可以回答的,回答完,选型焦虑就变成了选型论证。本书采用后一种态度,这也是本章只给方法、不给答案表的原因——答案表第二天就过时,方法十年后还在。
先看一个贯穿本章的例子:为我们的案例产品选数据库。
5.2 走一遍:为案例选数据库
决策现场
时间回到案例的阶段 1:一个人开发,一台服务器,需求清单刚定稿。要做一个社区交易产品——有人发内容、评论,将来还要上架商品、下单付款。现在的问题是:数据用什么存?
为什么第一个选数据库?因为数据是系统的"记忆",是最难替换的部分。前端框架想换,重写页面就行;后端语言想换,重写逻辑就行;数据库想换——要把全部数据迁移过去,还要保证迁移期间不出错。所以数据库选型是选错代价最高的决策,适合作为第一个完整示例。
这里顺带回答一个你可能已经冒出来的问题:**为什么不先选架构形态?**架构也是重决策,但阶段 1 的架构问题用九步走一遍会非常短——目标是快速验证想法,约束是一个人加一台服务器,候选是单体与微服务,评价维度里"开发与部署复杂度"权重压倒一切,结论是单体,代价是将来拆分成本高(第 26 章再评估)。九步走到极简时就是这样:它不总是大工程,但即使是三句话,也把"为什么是单体"变成了可论证的答案,而不是"大家都这么干"。
第一步到第三步:目标、约束、技术问题
业务目标:验证"社区 + 交易"的想法能不能成立,尽快上线拿到真实反馈。
业务约束(这一步最关键,也是最容易被跳过的):
- 一个人开发,没有专职 DBA;
- 一台服务器,资源有限;
- 上线时间紧,优先选"踩坑少"的方案;
- 数据量目前很小,但内容会增长,将来要收钱——交易数据不能出错;
- 内容和商品的属性可能会变(标签、规格),表结构不想频繁改。
技术问题:数据用什么存?具体拆成两个:要不要用关系型数据库?用哪个关系型?
注意,到这里为止,我们还没提任何一个具体技术——三个问题里,前两个是纯业务的,第三个才是技术的。这就是决策模型的第一个纪律:先搞清楚目标、约束和技术问题,再谈方案。大多数选型灾难,都始于跳过前两步直接讨论"MySQL 和 PostgreSQL 哪个好"。
第四步:候选方案(先粗筛,再细比)
把所有候选列出来,先做一轮粗筛,把明显不合适的排除掉:
- SQLite:零部署、单文件,本地开发神器。但它的写锁是库级的——多个用户同时写数据时只能排队,并发一上来就成瓶颈;而且它更像"给单机程序用的文件库",不适合"多用户同时访问的线上服务"这个场景。"一个人本地玩"是它的主场,但案例要上线、要有多个用户同时读写。排除。
- MongoDB:文档型数据库,schema 灵活,内容/商品这种"属性多变"的数据看起来很适合。但案例将来要收钱:订单、支付、库存这些数据需要强事务和强一致,文档型数据库虽然近年也支持了事务,但起步晚、心智模型不同(文档内嵌 vs 关系引用),且对账、报表这类交易场景的工具链远不如关系型成熟。排除——不是 MongoDB 不好,是"要收钱"这个约束把它排除了。
- PostgreSQL 和 MySQL:两个主流关系型数据库,都支持事务、都有成熟的索引和运维方案。进入细比。
这就是粗筛的价值:候选不是越多越好,也不是越少越好。粗筛后剩下 2-3 个真实候选,决策才有意义——只有一个候选是"没得选",十个候选是"没有标准"。
顺便对照一下"跳过前两步直接选型"会发生什么:如果一开始就在"MySQL 还是 MongoDB"里吵,这场讨论注定没有裁判——候选和维度都是悬空的,每个人拿自己的偏好当标准,谁也说不动谁。选型讨论吵不出结果,绝大多数时候不是信息不够,而是输入缺失:目标、约束、技术问题没有定,讨论"哪个好"就是无效讨论。决策模型的第一步价值就在这里:它把讨论从"哪个好"(无解的吵架)变成"哪个更匹配"(可论证的比较)。
第五步到第六步:评价维度、方案选择
对剩下的两个候选,按案例的约束定评价维度:
| 评价维度 | 权重(为什么) | PostgreSQL | MySQL |
|---|---|---|---|
| 事务与一致性能力 | 高——将来要收钱,数据库迁移代价极高,必须为交易预留 | 强(MVCC 多版本并发控制,业界公认扎实) | 强(InnoDB,满足常规事务需求) |
| 数据模型灵活性 | 高——内容标签、商品属性多变,不想频繁改表 | 强(JSONB 类型,可索引可查询) | 中(JSON 支持较弱,早期版本更弱) |
| 生态与中文资料 | 中——一个人开发,踩坑要查得到 | 中(社区活跃,中文资料渐多) | 高(LAMP 时代积累,资料最多) |
| 部署运维成本 | 中——一台服务器,都要装要配 | 低 | 低 |
| 许可证 | 低——商业产品要留意 | BSD,无附加义务 | GPL 双许可,商用需注意条款 |
按权重看,事务能力和数据灵活性是案例约束下的关键维度,这两项 PostgreSQL 占优;MySQL 的生态优势是"中"权重维度。方案选择:PostgreSQL。
但这里必须把话说完整:这不是"PostgreSQL 比 MySQL 好"的排名。如果你的约束是"团队五个人全熟 MySQL,云厂商还送 MySQL 实例",那评价维度的权重就会变成"生态与团队熟悉度"最高,MySQL 就是正确答案。同一个技术问题,约束不同,评价维度权重不同,选择就不同——这就是为什么"同样的业务,不同团队选型不同":不是有人选错了,是大家的约束本来就不一样。
第七步到第八步:收益与代价(选完就要认账)
收益:事务能力强,为阶段 3 的交易功能预留了地基;JSONB 让内容标签、商品属性不用改表就能扩展;BSD 许可,商用无附加义务。
代价:中文资料和云厂商默认支持不如 MySQL 普及——一个人开发,遇到冷门报错要自己啃英文文档;JSONB 字段是半结构化的,针对它的复杂查询和校验比结构化字段费劲;如果当初团队更熟 MySQL,学习成本就是额外的。
**只讲收益不讲代价,是选型最危险的姿势。**代价不会因为没讲就消失,它会在半年后的某个深夜以"迁移成本"的形式找上门。所以决策模型里,收益和代价必须成对写下——哪怕代价只是"少一点中文资料"。
第九步:未来演进条件
写下触发重新评估的信号:
- 用户量增长到缓存、读写分离都压不住,需要考虑更复杂的存储架构;
- 团队技能结构变化(来了一个 MySQL 专家,或要引入某个只有 MySQL 生态才有的方案);
- 业务出现关系型数据库明显不适配的场景(比如海量非结构化数据)。
演进条件不是"以后再说"的借口,是给未来自己的提醒:写下来,业务到那个信号时,就知道"该重新评估了"。没有这一条,选型就是"一次定终身";有了这一条,选型变成"带到期日的决策"。
九步走完,案例的数据库选型有了一个可以完整说清楚来龙去脉的答案:PostgreSQL。它可能不是"最好的数据库",但它是"这个业务、这个约束下,论证最完整的答案"。
为了把"选择是约束的映射"这件事钉死,做一个对照实验:把案例的约束改两条——团队五人、全都熟 MySQL,云厂商还送 MySQL 托管实例。重走第五、六步:"生态与团队熟悉度"的权重立刻升到最高,结论翻转为 MySQL。技术问题没变、候选没变,变的只有约束,于是选择变了。这就是为什么网上"PostgreSQL 还是 MySQL"的争论永远没有终局——两边都在用自己的约束吵别人的题。下次再看到这类争论,你的第一反应不应该是"哪个对",而是:他的约束是什么?和我的像吗?
5.3 九步模型:每一步在问什么
先说明这一节和 5.2 的关系:5.2 是演示——跟着案例走一遍九步;这一节是解剖——把九步拆开看每一步。同一个模型的两个视角:上面看"九步走起来什么样",这里看"每一步为什么长这样、坑在哪"。读到这里如果觉得某些步骤似曾相识,那是对的——同一批步骤,上一节讲"怎么走",这一节讲"为什么这么走"。
上一节走了一遍,现在把九步单独拆开,看每一步"在问什么、常见的坑是什么"。以后你用它做任何选型,都在心里对照 5.2 开头那张九步图。
第 1 步 · 业务目标:你要达成什么? 在问"业务到底要什么",答案里不允许出现技术名词。"快速验证想法""支持 1 万人同时在线""三个月内上线"——这些是目标;"用微服务""上 K8s"——这些不是。 坑:把技术当目标。很多人嘴上说目标是"快速上线",心里想的是"用上我心仪已久的某新框架"。目标一旦被技术偷换,后面八步全部失真。 案例回看:我们的目标是"验证想法、尽快上线拿反馈"——这个目标决定了后面所有步骤的基调:一切增加复杂度的选项都要为它让路。
第 2 步 · 业务约束:边界在哪里? 人、时间、钱、数据量、合规、团队技能——一切限制条件。约束是选型的输入里最重要的部分。 坑:漏掉约束。最常见的漏项是"运维人力"——选型时没人提"以后谁来管它",半年后这东西变成了团队里没人愿意碰的遗产。另一个常见漏项是"团队真实技能"——不是"我们希望会",是"现在真会"。 案例回看:一个人开发、一台服务器、将来要收钱——"一个人"和"要收钱"这两条约束,一个压低了运维复杂度预算,一个抬高了数据可靠性下限,后面候选和维度全是它们推出来的。
第 3 步 · 技术问题:业务诉求翻译成什么问题? 把前两步翻译成一个"技术问题清单":"要存数据且将来要事务"→"选什么数据库";"要记住登录状态"→"怎么保持会话"。 坑:翻译得太宽或太窄。"用什么数据库"是合适的宽度;"PostgreSQL 还是 MySQL"太窄(跳过了粗筛);"怎么存储"太宽(没有候选空间)。 案例回看:我们把它拆成两个问题——"要不要用关系型"(粗筛问题)和"用哪个关系型"(细比问题),一个决策拆成两级,每一级候选数量都控制在 2-3 个。
第 4 步 · 候选方案:有哪些真实的选项? 先粗筛到 2-3 个真实候选。粗筛的标准是"明显不满足第 2 步约束的排除"。 坑:只有一个候选(没得选,决策是假的);列十个候选(没有标准,决策是废的)。还要小心"夹带私货"——候选列表本身就是一种立场,少列一个对你不利的方案,等于提前做了决定。 案例回看:SQLite 和 MongoDB 在粗筛中被排除,不是它们"不好",是它们各自被一条硬约束排除——SQLite 被"多人并发在线"排除,MongoDB 被"将来要收钱"排除。
第 5 步 · 评价维度:谁重要? 定维度 + 定权重。权重来自第 2 步的约束,不来自个人偏好。 坑:用"流行度"当唯一维度。流行度是一个结果——它是别人的约束和选择产生的结果,不是你的评价依据。参考它可以,单独当标准不行。 案例回看:五条维度里,事务能力和数据灵活性权重最高,因为它们直接对应"要收钱"和"属性多变"两条约束;生态权重只给"中",因为一个人开发虽然要查资料,但这不是决定成败的维度。
第 6 步 · 方案选择:做决定。 按权重比较,选一个,然后把理由写下来。 坑:不敢选。"两个都差不多,先都试试"是选型里最贵的话——并行维护两套方案的成本,远超"选错再换"的成本。选型必须产生一个决定,哪怕决定是"选 A,同时记录 A 的风险"。 案例回看:PostgreSQL 在关键维度占优,选择它,同时把"中文资料少"写进代价列——决定不假装完美。
第 7 步 · 收益:它带来了什么? 写下这个方案给你的东西。 坑:收益写得空。"性能好"不是收益,"在 X 并发下 P99 延迟 < 200ms"才是。收益要具体到可以验证。 案例回看:收益是"为阶段 3 的交易预留了事务地基""JSONB 让属性扩展不用改表"——都是可以回头验证的承诺。
第 8 步 · 代价:你付出了什么? 写下这个方案让你牺牲的东西。这是全书最重要的一个习惯:收益与代价永远成对出现。 坑:只写收益不写代价。任何技术都有代价——没有代价的技术说明你没想清楚。代价包括但不限于:学习成本、运维成本、生态风险、迁移成本、团队约束。 案例回看:代价是"中文资料与云厂商支持略少,冷门报错要啃英文文档"——不大,但写下来了,这就是诚实。
第 9 步 · 未来演进条件:什么信号出现时需要重新评估? 写下"到期日":出现什么信号,这个决策要重来。 坑:以为选型一劳永逸。业务会变,约束会变,昨天的最优解今天可能是负担。没有第 9 步的决策记录,就没有"该换的时候知道该换"的触发点——大多数"技术债"不是当年选错了,而是当年没写到期日。 案例回看:信号是"用户量增长到缓存/读写分离都压不住""团队技能结构变化"——第 16 章我们会看到,阶段 2 真的触发了其中一条。
一句话总结九步:前三步问业务,中间三步做翻译,后三步签收并定到期日。前两节说的"约束是选型的输入,代价是选型的输出",就是这张图的两个端点。
九步之外还有一个常被忽略的环节:信息收集。第 4 步列完候选、第 5 步开始评价之前,你需要真实的资料——官方文档、性能对比、迁移案例——而不是论坛印象和"我记得好像"。"凭印象评价"和"按证据评价"是两种完全不同的决策质量;九步模型的每一步都默认你手上拿着证据,没有证据的九步只是把偏见流程化。
九步不是每次都要走完
看到这里你可能会问:以后每次选个组件库、挑个工具也要走九步吗?当然不是。判断标准是"决策的代价 × 可逆性":
- 代价高、难逆转的决策——数据库、语言、架构形态——值得走完整九步,因为它们错了要花大价钱改;
- 代价低、容易换的决策——组件库、工具脚本、某个 npm 包——三步就够:目标是什么 → 候选快速比一轮 → 选一个先试,不行就换。
"试错成本低"本身就是一个决策结论,它来自你对代价的判断。决策模型最大的价值不是让所有决策都变重,而是让你知道哪些决策该重、哪些该轻:把重的做重,把轻的做轻——这个分寸感本身就是决策能力的一部分。
落到案例上:阶段 1 的决策清单里,数据库(PostgreSQL vs MySQL)、架构形态(单体还是别的)、后端语言(Node 还是 Python/Java)走完整九步——它们代价高、难逆转;而前端组件库、构建工具、代码风格这类,三步就走,选一个先跑起来,别扭了再换。这个分工本身就写在 5.5 的决策记录里:重决策有完整论证,轻决策只有一行结论。
与"该轻则轻"相反的另一层也要防:把"完美论证"当成拖延的借口。模型最容易被反噬的地方就在这里——论证变成了不做决定的理由。完美论证不存在:足够好的论证(约束分析完整、代价清单诚实)+ 明确的决定 + 写下的到期日,就是一份合格的决策;剩下的交给第 9 步去跟踪。
5.4 为什么"为什么"可以学
现在到了本章最要紧的一个问题:这一套方法凭什么成立? 技术选型真的可以从"公说公有理"变成"可以论证"吗?还是说,这只是把玄学包装成了流程?
答案是:它成立,因为 Web 技术的问题空间是收敛的。
展开说。过去二十年,Web 系统面对的业务问题,翻来覆去其实就那么几类:要快(性能)、要可靠(数据不能丢)、要并发(人多)、要安全(不能被人搞)、要可维护(团队协作)、要能演进(业务会变)。每个问题,业界都演化出了成熟的方案形态——缓存解决快、事务解决可靠、索引解决查询慢、负载均衡解决并发、加解密解决安全、分层解决可维护。第 2 章讲过:每个技术都是被某类业务问题逼出来的(演进循环:复杂度上升 → 旧方案无法承受 → 新技术出现)。
这个事实带来一个推论,也是本章最重要的认知:
看懂一个技术选择 = 反推出它背后的约束。
看到"某系统用了 Redis",不要问"Redis 是什么"(名词地图的思维),要问"它的什么业务约束让缓存被逼出来了?"——答案多半是"读多写少、热数据集中"。看到"某系统用 JWT 不用 Session",要问"它的什么约束让无状态更合适?"——答案多半是"多端、多服务"。技术方案是约束的函数,函数是可逆的:顺着方案,能推出约束。
所以决策模型不是一套"选型流程",它是一个翻译器:业务约束从一端进,技术方案从另一端出。九步就是这台翻译器的内部结构。学会用它,你就同时学会了两个方向的翻译:
- 正推(设计方向):拿到一个业务需求,从目标约束出发,推出一套技术方案——这是"从业务需求出发做出基本的技术方案"(第 1 章北极星目标);
- 反推(理解方向):看到一个已有系统,从技术方案反推它的约束——这是"看懂一个系统、解释它为什么这样设计"。
反推不是玄学,是三个固定问题,和正推共用同一个模型:
- 它解决了什么问题?(这个技术为什么存在)
- 什么样的业务会先遇到这个问题?(它的约束画像)
- 它牺牲了什么?(它的代价)
演示一次。Redis:它解决了"热数据读写慢"的问题;会先遇到这个问题的业务,是读多写少、热数据集中、能容忍短暂不一致的;它牺牲的是缓存与源数据的一致性保证和一份额外的运维。所以看到某系统用 Redis,你就能反推出它的约束画像;反过来说,如果你的业务写多读少、强一致,用 Redis 就不是"跟上潮流"而是"引入麻烦"。
再演示一次。单体架构:它解决了"多人协作、快速迭代"的问题——一个代码库、一次部署、最简单的协作模型;会先遇到这个问题的业务,是团队小、业务边界模糊、把速度放在第一位的;它牺牲的是部署互相影响、故障面大、扩展只能整体扩。所以看到"还在用单体"的公司,先别急着笑——它的约束可能是"团队五个人、业务还没定型",单体在那个约束下就是最优解,等到约束变了(第 26 章),它自然会动。
这里还能再挖出一层:Web 技术的"标准件"化。过去二十年,解决"快""可靠""并发""安全"的成熟方案已经收敛成少数几类标准件——缓存、消息队列、关系型数据库、负载均衡、日志监控……新框架层出不穷,但翻来覆去解决的是同一批问题。这意味着:技术地图上的"新",大多是旧问题的新包装。看到一个"划时代"的新技术,先别急着学——先反推它解决什么问题,再对照标准件清单:如果它只是把缓存做得更快,你的学习优先级就排在后面;如果它解决了一个新类型的问题,那才值得投入。这个判断法,也是第 28 章延伸学习路线的方法论基础。
| 第 1 章四问(读者视角:理解一个系统时问) | 九步决策模型(工程师视角:设计一个系统时走) |
|---|---|
| 业务为什么遇到了这个问题 | 业务目标 → 业务约束 → 技术问题 |
| 为什么产生这种技术方案 | 候选方案 → 评价维度 → 方案选择 |
| 这个技术内部到底怎么工作 | (选定方案后的原理——从第 6 章起逐章展开) |
| 它解决了什么,又付出了什么代价 | 收益 → 代价 → 未来演进条件 |
四问是九步的压缩版:读者读一个系统时不需要重建候选和评价过程(那是作者的工作),只需要看到"问题、答案、机制、代价"四个切片;工程师设计一个系统时,四个切片不够,必须把候选、评价、选择显式走完——因为设计要对自己的选择负责,而理解只需要对别人的选择释然。
这也回答了一个你可能有的疑问:第 1 章预告本书看技术时说的是四个问题,为什么当时不直接把九步给出来?因为四问是读者视角、九步是工程师视角——读一本讲"理解系统"的书,四个切片就够了;到自己动手做选型时,才需要九步的完整武器。第 1 章先给你望远镜(看懂别人的系统),本章再给你扳手(做自己的决策)——工具分开发放,各归其位。
这一节还回答了 5.1 开头的问题:为什么同样的业务,不同团队选型不同?因为约束不同(团队技能、时间、预算、数据量预期),评价维度的权重就不同,方案自然不同。选型不是"谁的答案对"的比赛,是"谁的约束匹配谁的方案"的映射。而"大厂用什么"之所以不能照抄,也是因为你复制的只是别人的答案,不是别人的约束——大厂的约束(海量流量、顶级运维、充足人力)和你(一个人、一台服务器)根本不是同一个输入,怎么可能期待同一个输出。
读到这里,你手上已经有了这本书最重要的两件工具:第 1 章的地图和本章的模型。从下一章开始,每一个技术主题都是这两件工具的一次联合演示——你可以边读边验证:这一章的四问,对应着模型的哪几步?
这套能力还有一个现实的验收场景——面试。面试官问"你们项目为什么用 X 不用 Y",答"因为它火"和答"因为我们的约束是 A、B,评价维度里 C 的权重最高,所以选了 X,代价是 D,出现 E 信号就要重新评估"——高下立判。本章练的东西简历上写不出来,但面试一开口就见真章。
5.5 决策记录:把选型变成可追溯的东西
方法有了,还差一个习惯:把决策写下来。
九步走完,如果不写下来,它只是一个想法;写下来,它才成为一份可以追溯、可以评审、可以在未来重新打开的文件。我们把案例阶段 1 的技术栈选型全部走一遍九步(篇幅所限,这里只给结论,论证过程略——你现在已经知道怎么论证了),得到一份决策记录:
| 技术选择 | 业务目标 | 关键约束 | 为什么选它 | 代价 | 未来演进条件 |
|---|---|---|---|---|---|
| 单体架构 | 快速验证想法 | 一个人、一台服务器 | 结构最简单、改动最快 | 规模上来后拆分成本高 | 团队 > 5 人或模块边界清晰后评估拆分 |
| 数据库 PostgreSQL | 数据可靠、将来收钱 | 要事务、属性多变 | 事务强、JSONB 灵活、许可自由 | 中文资料与云厂商支持略少 | 用户量/存储架构变化时重评(见 5.2) |
| 缓存 Redis | — | — | 不上:业务没到,没被逼出 | 省下的复杂度就是收益 | 首页变慢、读多写少信号出现时评估(阶段 2) |
其余三行同样走九步,这里压缩给你看。后端语言:目标是前后端一个人写,约束是单人开发——评价维度里"前后端同语言"权重最高,选择 Node.js,代价是动态类型对大型工程的约束弱,演进条件是工程变大后考虑 TypeScript 或换语言。前端框架:约束同样是单人开发、要生态,选择 React——换成 Vue 完全等价,本书不站队——代价是包体积与版本迭代快。微服务与 K8s:和 Redis 同理——不上,演进条件写进记录:单体痛点集中爆发时评估(阶段 5,第 26 章)。
这张表有四个地方要单独说。
第一,它把"不做什么"也写进去了。决策不只是选择,还包括放弃。Redis 很好、K8s 很酷,但阶段 1 的业务没有逼出它们——"业务逼出技术"(第 1 章声明、第 3 章展开的原则)在这里第一次落地为具体决策。省下一个没被逼出的技术,省下的不只是安装配置,是它带来的整个复杂度:缓存一致性、服务发现、容器编排……这些复杂度不是免费的,而"不上"是唯一免费的选项。
第二,每个"为什么"都能被追问。有人问"为什么用 Node.js",你可以指着他看到的那一列:前后端同语言、单人开发。被追问不可怕,答不上来才可怕——决策记录就是把"答不上来"变成"指给你看"。
第三,它是可评审的。团队场景下,选型不再靠开会时嗓门大,而是看谁的约束分析更完整、谁的代价清单更诚实。即使最终决定不由你拍板——老板拍板、技术委员会说了算——决策记录也能让讨论有据可依:你的约束分析会被认真对待,你的代价清单会让"被否决"有据可查。
第四,它是活的。演进条件列就是"到期日"清单——阶段 2 首页变慢那天,你不是从零开始想"要不要加缓存",而是打开这份记录,看到自己当年写下的信号:该评估了。
这张决策记录压缩成四列,就是本书每章必备的业务-技术对应表——它是决策记录的可视化:业务诉求(目标+约束)、技术选择、为什么(评价+选择)、代价/取舍(代价+演进条件)。本章的对应表如下:
| 业务诉求 | 技术选择 | 为什么 | 代价/取舍 |
|---|---|---|---|
| 一个人快速把想法验证上线 | 单体架构 + 基础前后端 | 结构最简单、改动最快 | 规模上来后拆分成本高,需提前留边界 |
| 数据要可靠、将来要收钱 | PostgreSQL | 事务强、JSONB 灵活、许可自由 | 生态与中文资料略少,冷门问题要啃英文文档 |
| 内容/商品属性多变 | JSONB 字段 | 免去频繁改表 | 复杂查询校验比结构化字段弱 |
| 前后端一个人写 | Node.js + React(Vue 等价) | 同语言,心智负担最小 | 动态类型约束弱,工程变大要补 TS 或重评 |
| 要不要缓存 | 阶段 1 不上 Redis | 业务没到,没被逼出 | 首页变慢后重新评估(演进条件已写入记录) |
| 要不要微服务/K8s | 阶段 1 不上 | 同上 | 单体痛点集中后评估 |
每一行都在本章正文里有支撑(单体与 PostgreSQL 的完整论证在 5.2;Node/React/微服务的压缩论证和 Redis 的"不上"决策在本节前半部分)。读完这章,你可以拿着这张表反问自己:如果这是我的项目,每一行我会怎么填?填不上来的那一行,就是你这块知识地图上还没连上的点。
最后说一句维护:决策记录不是文档负担,一张表就够,放在团队 wiki 或项目 README 里都行。它只在两个时刻需要更新——决策变更时(把旧行标记"已过期",写上触发它的演进条件和新的决策)和复查时。演进条件触发了怎么办?不是重走九步,而是增量重走:先看约束哪条变了,再看候选里有没有新选项,最后对照上次的代价清单验证"当年付的代价,现在还成立吗"——大部分复查到第三步就能结束。第 16 章和第 26 章,你会看到案例的两次真实复查:一次是阶段 2 的"要不要加缓存",一次是阶段 5 的"要不要拆服务"。
5.6 常见误区与纠偏
九步模型不难,难的是在真实世界里坚持用它。五个最常见的误区,提前打预防针。
误区一:"选型 = 选最流行的。" 流行是别人约束下的结果,不是你的评价依据。纠偏:把"流行度"从评价维度降级为参考信息——它可以作为"生态风险"的一个子指标,但权重由你的约束决定。
误区二:"选型一次定终身。" 没有第 9 步的选型,会在业务变化时失去重新评估的触发点。纠偏:每个决策记录都写演进条件,并把"检查演进条件"放进迭代节奏(第 27 章会看到这是迭代循环的一部分)。
误区三:"大厂用什么,我照抄准没错。" 你复制的只是答案,不是约束。纠偏:看到任何系统的技术选型,先反推它的约束(5.4 的反推练习),再问"我的约束和它像吗"——不像,就抄不得。
误区四:"我要选'最好的'。" 没有最好的技术,只有约束下最合适的技术。纠偏:把"最好"从问题里删掉,换成"在这个约束下,哪个方案代价最小"。
误区五:"技术债都是当年选错了。" 大量技术债是当年约束下的正确决策,只是演进条件触发了、没有人重新评估。纠偏:看到"烂代码/老系统",先问"它当时的约束是什么",再决定是重构还是继续付利息(第 20 章会展开技术债的完整讨论)。
五个误区背后是同一个问题:把决策模型当成教条,而不是工具。模型是给你用的,不是让你供着的——该轻则轻,该重则重,该写记录就写记录,该复查就复查。记住这一点,本章的内容才算真正生效。
5.7 实战:反推训练
方法讲完了,做三个练习。下面的选型现象都是真实世界常见的,先自己按"解决什么问题 → 约束画像 → 牺牲了什么"反推一遍,再看参考答案。
练习 1:某内容社区用 JWT 不用 Session。 你的反推:① 它解决了什么问题?② 约束画像?③ 牺牲了什么? 参考答案:它解决"无状态会话"问题——服务器不存会话,天然支持多端(Web/App)与横向扩展;约束画像是多端优先、API 可能被第三方调用;牺牲的是吊销能力——用户改密码后旧 token 可能仍有效,需要额外的黑名单机制。第 13 章会把这组权衡完整展开。
练习 2:某电商大促前把订单处理从同步调用改成消息队列异步。 你的反推:① 解决了什么?② 约束画像?③ 牺牲了什么? 参考答案:它解决"同步链路在峰值扛不住"的问题——扣库存、发短信、调支付渠道都是耗时操作,同步等待会拖垮整个请求;约束画像是大促峰值流量、链路里有慢依赖;牺牲的是最终一致性——用户看到的状态可能短暂不一致,排查链路也变长了。第 17 章引出、第 26 章回收的正是这条认知链。
练习 3:某创业公司的技术栈是 Python + Django + MySQL。 你的反推:① 解决了什么?② 约束画像?③ 牺牲了什么? 参考答案:它解决"快速交付 CRUD 型业务"——一套全家桶从数据库到模板全都配好;约束画像是团队 Python 背景、业务以增删改查为主、速度优先;牺牲的是高并发与极致性能的上限,真到了那个规模要补缓存、异步等一堆零件。
三个练习做下来你会发现:反推不是猜,是顺着"问题 → 约束 → 代价"走一遍——和正推共用同一个模型。下次看到一个技术选型,先别问"这是什么"(名词地图),先问这三问(决策地图)——这就是第 1 章说的升级,现在你有了升级的工具。
最后补一句:练习的参考答案不是标准答案。如果你在练习 1 里推出来的约束是"这社区要接第三方登录、移动端为主",只要三问都能自洽回答,就是合格的反推。反推没有对错,只有自洽与不自洽——自洽意味着你掌握了它的决策逻辑,不自洽说明你漏了它的某条约束,那正是你要补的认知缺口。
本章小结
- 选型难,难在答案太多、代价来得晚;破解方法不是知道更多答案,而是学会论证答案;
- 九步决策模型:目标、约束、技术问题来自业务;候选、评价、选择是翻译;收益、代价、演进条件是签收和到期日——约束是选型的输入,代价是选型的输出;
- 为什么它可以学:技术方案是约束的函数,看懂方案 = 反推约束;四问(读者视角)与九步(工程师视角)是同一个翻译器的两个视图;
- 决策要写下来:决策记录让"为什么"可追溯、可评审、可到期;决策包含不做什么;
- 本章的对应表就是案例阶段 1 的技术栈决策记录——本书后续每一章的关键技术选择(Session 还是 JWT、要不要 Redis、要不要 K8s、单体还是微服务),都会用同一张九步表走一遍,到时候你可以对照本章,看模型怎么一次次被使用。
九步速查(后续章节回指本章时,翻回这里即可):
- 业务目标——业务要达成什么,答案里不许出现技术名词;
- 业务约束——人/时间/钱/数据量/合规/团队真实技能;
- 技术问题——把诉求翻译成问题清单(宽度合适);
- 候选方案——粗筛到 2-3 个真实候选;
- 评价维度——按约束定权重,流行度只作参考;
- 方案选择——做决定,把理由写下来;
- 收益——具体到可以验证;
- 代价——与收益成对出现,只讲收益就是埋雷;
- 演进条件——写到期日,触发时增量重走,不重做。
下一章
技术栈定了:单体、React + Node.js、PostgreSQL。但"用什么存"回答了,还没回答"怎么存"——六个业务对象(用户、内容、评论、商品、订单、支付)怎么变成数据库里的表?业务流程怎么变成接口?
下一章,业务模型变成数据模型:设计一个系统的第二份关键图纸。