跳到主要内容

第 5 章 技术决策:从业务约束到技术方案

副题:为什么选这个、不选那个——以及为什么这个"为什么"是可以学会的

本章是全书的方法论中心。第 1 章我们拿到了地图,第 4 章我们把一句话需求翻译成了需求清单。现在需求清单在手,要开始选型了:语言用什么?框架用什么?数据库用什么?本章回答的不是"该选什么",而是"怎么选"——一个可以用在任何技术选择上的九步决策模型。

本章要建立的认知

  1. 技术选型不是"背答案",是从业务约束里推出来的;
  2. 九步决策模型:业务目标 → 业务约束 → 技术问题 → 候选方案 → 评价维度 → 方案选择 → 收益 → 代价 → 未来演进条件;
  3. 一句话记住它:约束是选型的输入,代价是选型的输出——决策包含"不做什么",且从不一劳永逸。

5.1 选型为什么这么难

先看一个你多半经历过的场景。

某个技术群里有人问:"社区交易类产品,数据库用 PostgreSQL 还是 MySQL?"半小时内,评论区分成两派:一边说"PostgreSQL 功能强、JSON 好用、事务靠谱";另一边说"MySQL 生态大、云厂商支持好、出问题一搜一堆答案"。双方各自贴出三四个"权威"链接,谁也说服不了谁。最后有人抛出一句:"跟着大厂走准没错,某大厂用的就是 X。"于是提问的人更迷茫了。

这就是选型难的真实样子:不是没有答案,是答案太多。PostgreSQL、MySQL、MongoDB、SQLite;React、Vue、Svelte;Node、Python、Java、Go——每一个选择都有人推荐、都有人踩过坑、都有成功的公司和失败的案例。1-3 年的开发者面对这种局面,最常见的应对方式是:

  • 看招聘要求——"反正以后跳槽要会这个";
  • 看 star 数和社区热度——"用的人多总没错";
  • 看朋友/同事推荐——"他踩过的坑比我走过的路多";
  • 看教程——"教程用什么我就用什么"。

这些方式不能说错,但有一个共同的毛病:它们都无法被论证。别人问你"为什么选这个",你只能回答"因为它火"或者"大家都这么用"。而"因为它火"不是一个技术理由——它解释不了你的业务为什么需要这个技术,也回答不了"业务变了之后要不要换"。

选型难,还难在第二个地方:选错的代价来得晚。语言、框架、数据库不是写错一行代码——它们是地基。地基选错了,不是当天就塌,而是半年后业务要加一个功能时,你发现"当初那个选择让这件事变得极其难做"。到那时候,迁移成本高得让人宁可忍受别扭。所以选型又是一个"决策时看不出好坏、事后才知代价"的典型问题。

本章要解决的就是这两件事:给选型一个可以论证的方法,让每个选择都能说清楚"从哪来、到哪去";同时把"事后代价"提前到决策时就想清楚。

还有一个心态层面的根源值得先拆掉:大多数人把选型当成考试,而不是设计。考试有唯一正确答案,考的是你知道得多不多;设计没有标准答案,比的是你在约束下的权衡好不好。把选型当考试的人,会一直焦虑"我是不是选错了"——因为总有一个"更好的答案"在别处;把选型当设计的人,关心的是另外两个问题:"我的约束分析全不全?我的代价清单诚不诚实?"这两个问题是可以回答的,回答完,选型焦虑就变成了选型论证。本书采用后一种态度,这也是本章只给方法、不给答案表的原因——答案表第二天就过时,方法十年后还在。

先看一个贯穿本章的例子:为我们的案例产品选数据库。

5.2 走一遍:为案例选数据库

图5-1 新(核心图) 图稿占位
技术决策模型九步
目标与约束来自业务,选择是翻译,收益与代价是签收,演进条件是到期日

决策现场

时间回到案例的阶段 1:一个人开发,一台服务器,需求清单刚定稿。要做一个社区交易产品——有人发内容、评论,将来还要上架商品、下单付款。现在的问题是:数据用什么存?

为什么第一个选数据库?因为数据是系统的"记忆",是最难替换的部分。前端框架想换,重写页面就行;后端语言想换,重写逻辑就行;数据库想换——要把全部数据迁移过去,还要保证迁移期间不出错。所以数据库选型是选错代价最高的决策,适合作为第一个完整示例。

这里顺带回答一个你可能已经冒出来的问题:**为什么不先选架构形态?**架构也是重决策,但阶段 1 的架构问题用九步走一遍会非常短——目标是快速验证想法,约束是一个人加一台服务器,候选是单体与微服务,评价维度里"开发与部署复杂度"权重压倒一切,结论是单体,代价是将来拆分成本高(第 26 章再评估)。九步走到极简时就是这样:它不总是大工程,但即使是三句话,也把"为什么是单体"变成了可论证的答案,而不是"大家都这么干"。

第一步到第三步:目标、约束、技术问题

业务目标:验证"社区 + 交易"的想法能不能成立,尽快上线拿到真实反馈。

业务约束(这一步最关键,也是最容易被跳过的):

  • 一个人开发,没有专职 DBA;
  • 一台服务器,资源有限;
  • 上线时间紧,优先选"踩坑少"的方案;
  • 数据量目前很小,但内容会增长,将来要收钱——交易数据不能出错;
  • 内容和商品的属性可能会变(标签、规格),表结构不想频繁改。

技术问题:数据用什么存?具体拆成两个:要不要用关系型数据库?用哪个关系型?

注意,到这里为止,我们还没提任何一个具体技术——三个问题里,前两个是纯业务的,第三个才是技术的。这就是决策模型的第一个纪律:先搞清楚目标、约束和技术问题,再谈方案。大多数选型灾难,都始于跳过前两步直接讨论"MySQL 和 PostgreSQL 哪个好"。

第四步:候选方案(先粗筛,再细比)

把所有候选列出来,先做一轮粗筛,把明显不合适的排除掉:

  • SQLite:零部署、单文件,本地开发神器。但它的写锁是库级的——多个用户同时写数据时只能排队,并发一上来就成瓶颈;而且它更像"给单机程序用的文件库",不适合"多用户同时访问的线上服务"这个场景。"一个人本地玩"是它的主场,但案例要上线、要有多个用户同时读写。排除。
  • MongoDB:文档型数据库,schema 灵活,内容/商品这种"属性多变"的数据看起来很适合。但案例将来要收钱:订单、支付、库存这些数据需要强事务和强一致,文档型数据库虽然近年也支持了事务,但起步晚、心智模型不同(文档内嵌 vs 关系引用),且对账、报表这类交易场景的工具链远不如关系型成熟。排除——不是 MongoDB 不好,是"要收钱"这个约束把它排除了。
  • PostgreSQL 和 MySQL:两个主流关系型数据库,都支持事务、都有成熟的索引和运维方案。进入细比。

这就是粗筛的价值:候选不是越多越好,也不是越少越好。粗筛后剩下 2-3 个真实候选,决策才有意义——只有一个候选是"没得选",十个候选是"没有标准"。

顺便对照一下"跳过前两步直接选型"会发生什么:如果一开始就在"MySQL 还是 MongoDB"里吵,这场讨论注定没有裁判——候选和维度都是悬空的,每个人拿自己的偏好当标准,谁也说不动谁。选型讨论吵不出结果,绝大多数时候不是信息不够,而是输入缺失:目标、约束、技术问题没有定,讨论"哪个好"就是无效讨论。决策模型的第一步价值就在这里:它把讨论从"哪个好"(无解的吵架)变成"哪个更匹配"(可论证的比较)。

第五步到第六步:评价维度、方案选择

对剩下的两个候选,按案例的约束定评价维度:

评价维度权重(为什么)PostgreSQLMySQL
事务与一致性能力高——将来要收钱,数据库迁移代价极高,必须为交易预留强(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-2 图稿占位
约束→选型映射示例
约束变,评价权重变,选择就变——选择是约束的映射,不是技术的排名

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 章北极星目标);
  • 反推(理解方向):看到一个已有系统,从技术方案反推它的约束——这是"看懂一个系统、解释它为什么这样设计"。

反推不是玄学,是三个固定问题,和正推共用同一个模型:

  1. 它解决了什么问题?(这个技术为什么存在)
  2. 什么样的业务会先遇到这个问题?(它的约束画像)
  3. 它牺牲了什么?(它的代价)

演示一次。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、单体还是微服务),都会用同一张九步表走一遍,到时候你可以对照本章,看模型怎么一次次被使用。

九步速查(后续章节回指本章时,翻回这里即可):

  1. 业务目标——业务要达成什么,答案里不许出现技术名词;
  2. 业务约束——人/时间/钱/数据量/合规/团队真实技能;
  3. 技术问题——把诉求翻译成问题清单(宽度合适);
  4. 候选方案——粗筛到 2-3 个真实候选;
  5. 评价维度——按约束定权重,流行度只作参考;
  6. 方案选择——做决定,把理由写下来;
  7. 收益——具体到可以验证;
  8. 代价——与收益成对出现,只讲收益就是埋雷;
  9. 演进条件——写到期日,触发时增量重走,不重做。

下一章

技术栈定了:单体、React + Node.js、PostgreSQL。但"用什么存"回答了,还没回答"怎么存"——六个业务对象(用户、内容、评论、商品、订单、支付)怎么变成数据库里的表?业务流程怎么变成接口?

下一章,业务模型变成数据模型:设计一个系统的第二份关键图纸。