08 · 架构决策记录与演进
上一章你学会了从 0 设计一个系统。但系统设计完不是终点——它会随业务长大、被后人接手、在你早忘了当初为什么这么做的时候继续运行。这一章讲怎么让架构活得久、长得好。
开场:最先丢失的,永远是为什么
想象一个场景。你接手一个三年前别人设计的系统,翻开代码,看到一个奇怪的设计:订单数据被同时写进了两个不同的存储,中间还有套对账逻辑。你的第一反应是:这不脱裤子放屁吗?写一个不就完了?于是你大笔一挥,删掉一个、合并逻辑——
三周后线上炸了。原来当年之所以这么设计,是因为有个监管要求订单流水必须落进一个不可篡改的存储,而主库要支持高频改单,两个诉求无法在一个存储上同时满足。这个理由,代码里一个字都没写,当年拍板的人也早就离职了。
这就是架构最致命的信息流失:代码和图能告诉你系统是什么,但几乎永远讲不清为什么这么选、当初放弃了什么。 而恰恰是后者,才是接手的人最需要、也最容易丢失的东西。
会议里讲过的原因,会在三次会议、两次离职、一年时间之后,蒸发得一干二净。等需要它的时候,只剩下一个看起来莫名其妙的设计,和一群不敢动它的人。
这一章给的解药很简单,简单到很多人不屑于做——把重要的架构决策,用一页纸记下来。 这页纸叫 ADR。
一、ADR:给架构决策建一本为什么的账
ADR = Architecture Decision Record,也就是架构决策记录。 它是一份轻量文档,每做一个重要架构决策,就写一份,记下这个决策的来龙去脉。
它的精髓在于足够轻:
- 一个决策一份,通常一页纸,几分钟能读完。
- 追加,不修改:决策变了就写新的一份,把旧的标记为被取代——保留历史,而不是抹掉历史。因为团队曾经怎么想、后来为什么改,本身就是宝贵信息。
- 和代码放在一起:例如仓库里一个
docs/adr/目录,让它随代码一起被版本管理、被搜索、被 review。
一个可以直接抄走的 ADR 模板
┌──────────────────────────────────────────────────────────┐
│ ADR-007:订单流水采用「主库 + 不可篡改日志」双写 │
├──────────────────────────────────────────────────────────┤
│ │
│ 状态:已采纳 │
│ (草稿 / 已采纳 / 已废弃 / 被 ADR-015 取代) │
│ │
│ 日期:2026-05-23 决策者:架构组 + 合规 │
│ │
│ ── 背景 / 上下文 ─────────────────────────────────── │
│ 监管要求订单流水必须落入「写后不可改」的存储以备审计; │
│ 但业务又要求订单可被高频修改(改地址、改数量)。 │
│ 单一存储无法同时满足「可改」与「不可篡改」。 │
│ │
│ ── 决策 ─────────────────────────────────────────── │
│ 主库存可变订单状态,服务高频读写; │
│ 同时把每次变更追加写入一份不可篡改日志,作为审计依据; │
│ 以日志为准做定期对账。 │
│ │
│ ── 考虑过的其它选项 ─────────────────────────────── │
│ A. 只用主库 + 软删除标记 → 否决:软删除仍可被改,过不了审计 │
│ B. 只用不可篡改存储 → 否决:无法支持改单,业务不可接受 │
│ C. 双写(本方案) → 采纳 │
│ │
│ ── 取舍与后果 ───────────────────────────────────── │
│ + 同时满足了合规与业务两个硬约束 │
│ − 引入双写,需要对账逻辑兜底两边不一致(已知复杂度) │
│ − 后人会觉得「多此一举」——本 ADR 就是写给你看的,别删! │
│ │
└──────────────────────────────────────────────────────────┘模板就六块,记牢这六个标题就够了:
| 字段 | 写什么 | 为什么不能省 |
|---|---|---|
| 标题 | 一句话说清这个决策是什么 | 方便日后检索 |
| 状态 | 草稿 / 已采纳 / 已废弃 / 被某 ADR 取代 | 让读者知道这条还算不算数 |
| 背景 / 上下文 | 当时面临什么问题、什么约束 | 后人最缺的就是当时的处境 |
| 决策 | 我们最终决定怎么做 | 这部分说明系统是什么,代码里也能看到 |
| 考虑过的其它选项 | 还想过哪些方案,为什么没选 | 放弃了什么,是 ADR 独有的价值 |
| 取舍与后果 | 这个选择带来什么好处、什么代价、什么已知债务 | 让后人清楚地继承这份有意的取舍 |
注意上一章的呼应:你在 07 的步骤 ⑧ 里,被反复要求说出我选了 A、放弃了 B、原因是什么,以及还有哪些未决问题。这些话逐字逐句就是一份 ADR 的决策、其它选项和取舍。 ADR 不是额外的负担,它只是让你把本来就该想清楚的东西,落在纸上别让它跑了。
二、强观点:记为什么比记是什么重要一百倍
这是这一章、甚至整个仓库最想让你记住的一条原则,值得单独拎出来反复说:
代码、架构图、API 文档,记录的全是系统现在是什么样——有哪些模块、怎样调用、数据怎么流动。这些东西,只要你愿意,随时能从系统本身读出来。
但为什么是这样、当初放弃了什么、在拿什么换什么,这些靠读代码读不出来。它只活在做决定那个人的脑子里,不写下来,就随风而逝。
为什么这件事这么金贵?有三个理由:
- 系统是什么样会自我证明,为什么这么做不会。 看代码就知道系统是什么样;但代码永远不会告诉你,团队本来想用更简单的方案 B,只是因为某个约束才忍痛上了复杂的方案 C。
- 没有为什么,后人只能在两种错误里二选一:要么不敢动,觉得这设计看着怪,但不知道动了会不会出事,于是系统僵化;要么乱动,像开场那个删双写的例子,直接踩雷。有了为什么,后人才能安全地判断这条约束还在不在,这个决策还成不成立。
- 为什么是可迁移的智慧,是什么只是一次性的结果。 一份好 ADR 里,团队为了 A 牺牲了 B 的推理,换个项目、换个系统,后人还能复用那套权衡思路——这正是本仓库一以贯之的信念。
💡 一句话立此原则:好的文档不重复解释代码做了什么,因为代码自己会说;好的文档解释代码为什么这么做,因为代码永远不会说。 把记录的力气,花在那些一旦丢失就再也找不回来的东西上。
这也正是 根 README 的三条阅读原则 里第一条的延伸:先问为什么,再看怎么做。看不到取舍,就等于没看懂。 ADR,就是把这条原则从阅读变成写作。
三、演进式架构:别想一次设计到位,要留好接缝
07 反复讲,架构是迭代出来的。但能迭代这件事本身,是要设计的——一个糟糕的架构,改一点就牵一发动全身,根本迭代不动。
演进式架构,英文是 Evolutionary Architecture。它的核心思想是:
既然你注定无法一次设计对,那就把架构设计成容易改对的样子。 重点不是现在完美,而是将来能低成本地替换某一块。
怎么做到容易改对?答案是留好接缝 seam:清晰的模块边界和接口。一个有好接缝的系统,长这样:
没有接缝(一团泥): 留好接缝(模块化):
┌─────────────────────┐ ┌────────┐ 接口 ┌────────┐
│ 所有逻辑揉成一坨 │ │ 模块 A │◀─────▶│ 模块 B │
│ 支付、库存、通知 │ └────────┘ └───┬────┘
│ 互相直接调来调去 │ │ 接口
│ 改一处,处处地震 │ ┌────────┐ 接口 ┌──▼─────┐
└─────────────────────┘ │ 模块 D │◀─────▶│ 模块 C │
└────────┘ └────────┘
想换掉「通知」? 想换掉模块 C?
→ 不可能,它和谁都缠在一起 → 拔掉它、换一个,只要接口不变,
其它模块毫无感觉接缝的价值,在于把将来的不确定性隔离开。 举几个上一章短链服务的例子:
- 你把短码生成做成一个有清晰接口的独立模块。第一版用预批发号段,将来如果想换成别的生成策略,只换这一块,跳转服务和存储毫不知情。
- 你把缓存藏在跳转服务的接口背后。第一版用进程内缓存,涨上去了换成 CDN——对调用方是透明的。
这正是每个模板第 12 节演进路线在传递的智慧:AI 对话产品的演进路线 里,MVP 阶段直接调外部模型 API,成长期才换成自建推理 + 连续批处理——之所以换得动,正因为调用模型这件事一开始就被收在一个清晰的边界后面。好的接缝,让演进从重写变成替换。
💡 设计时多问一句:这一块将来最可能被换掉吗? 最可能变的地方,就要用最干净的接口把它包起来,给它留好接缝。这是用现在多想一点,换将来少痛一片。
四、技术债:它不全是坏事,关键是记账
技术债这个词常被当成纯贬义——好像欠了债就是干了坏事。这是个误解。
技术债的真正含义,借自金融:为了现在更快地拿到价值,而有意识地选了一个将来需要偿还的权宜方案。 就像借钱办事——借钱本身不是错,关键是你知不知道自己借了、打不打算还。
技术债分两种,要分清:
┌───────────────────────────┬───────────────────────────┐
│ 有意识的债(健康) │ 无意识的债(危险) │
├───────────────────────────┼───────────────────────────┤
│ 「为了赶上发布,这版先用 │ 「我也不知道为什么这里这么 │
│ 最简单的方案,记 TODO, │ 写,反正能跑」 │
│ 下季度重构」 │ │
│ │ │
│ → 是理性的商业权衡 │ → 是失控,你甚至不知道欠了债 │
│ → 写进 ADR / backlog,排期还 │ → 哪天突然爆雷,完全没准备 │
└───────────────────────────┴───────────────────────────┘对一个 MVP 来说,故意欠技术债往往是正确的——07 里短链服务第一版的单存储 + 单机发号就是一笔债,但它换来了快速上线、验证需求,完全划算。错的不是欠债,而是:
- 不知道自己欠了债:无意识的债最危险;
- 欠了债不记录:团队还是会忘记为什么,回到本章开篇那个坑;
- 永远只借不还:债越滚越大,直到某天系统改不动了。
处理技术债的纪律就三条:① 有意识地借,明确这是权宜之计;② 把它记下来,一笔技术债就是一条该写的 ADR,背景要说明为什么暂时这样做;③ 安排偿还时机,挂进 backlog,定下当 X 发生时就还的触发条件,而不是有空再说。
把技术债当成记在账上、按计划偿还的负债来管理,而不是藏在地毯下、假装不存在的脏东西——这是成熟团队和草台班子的分水岭。
五、康威定律:你的架构,会长得像你的组织
聊架构演进,绕不开一条定律。它不是技术规律,而是社会学观察,却深刻影响每一个系统的最终形态:
康威定律 Conway's Law:系统的架构,会不可避免地长得像设计它的那个组织的沟通结构。
翻成人话:两个模块之间的接口,长得像这两个模块背后那两拨人之间的沟通方式。 如果两个团队天天开会、坐在一起,他们做出来的两个模块大概率紧密耦合;如果两个团队分属不同部门、只能靠邮件交流,他们的模块之间就会自然形成清晰甚至僵硬的边界。
组织长这样: 系统就会长成这样:
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ 支付团队 │ │ 物流团队 │ ───▶ │ 支付服务 │ │ 物流服务 │
│ (各自独立)│ │ (各自独立)│ │ (独立部署)│ │ (独立部署)│
└─────────┘ └─────────┘ └────┬────┘ └────┬────┘
几乎不沟通,各管各的 └─ 接口清晰、松耦合 ─┘
┌───────────────────────┐ ┌───────────────────────┐
│ 一个大团队啥都管 │ ───▶ │ 一个大单体,啥都揉一起 │
└───────────────────────┘ └───────────────────────┘康威定律对架构演进有两条极其重要的启示:
- 拆服务之前,先看团队结构。 你想把单体拆成微服务,04 讲过微服务,但如果团队还是一锅粥、谁都管所有事,那拆出来的微服务之间照样紧耦合、改一个动一片——架构边界和团队边界对不齐,拆了也是白拆。 想要松耦合的服务,先有边界清晰、能独立负责的团队。
- 反过来用它,也就是逆康威操作:想要什么样的架构,就先组织成什么样的团队。 你希望系统由几个独立演进的服务组成?那就先按这些服务把人分成几个能独立决策的小队,架构会自然朝你要的方向长。组织设计,本身就是一种架构设计。
💡 康威定律的本质提醒:架构问题,常常是组织问题伪装的。 当你发现两个模块怎么解耦都解不干净,先别急着改代码——去看看是不是背后那两拨人本就分不开。很多架构难题,真正的解法在组织结构里,不在技术里。
六、什么时候该重构 / 该升级架构:用判断,不用感觉
系统在长大,你迟早面临这个问题:现在这套架构,该不该动了? 新手常凭两种糟糕的依据做决定:
- 凭感觉:这代码看着真丑,重构吧——丑不是升级架构的理由,不影响任何质量属性的丑,可以先忍。
- 跟风:大厂都上微服务/中台/某新架构了,我们也上——别人的瓶颈不是你的瓶颈,照搬大厂成熟期的架构套自己的成长期,是头号过度设计。
那靠什么判断?靠前六章学的两把尺子:瓶颈和质量属性。
该不该升级架构?——拿这两把尺子量,而不是拍脑袋:
┌────────────────────────────────────────────────────────┐
│ 尺子一:瓶颈(来自 06 + 07 步骤⑦) │
│ 现在,某个质量属性是不是已经被架构卡住了? │
│ • 数据库读到冒烟、加再多缓存也压不住了? │
│ • 一个模块改动总是连累一片、发布越来越慢? │
│ → 真实的、量出来的瓶颈,才是升级的信号 │
├────────────────────────────────────────────────────────┤
│ 尺子二:质量属性的变化(来自 06) │
│ 业务对「要多好」的要求,是不是上了一个台阶? │
│ • 可用性要求从 99% 提到 99.99%? │
│ • 用户量/数据量进入了下一个量级(07 估算说的「100倍」)?│
│ → 质量目标变了,旧架构撑不住了,才升级 │
└────────────────────────────────────────────────────────┘把判断流程固化成一句话:
不是架构旧了、丑了就升级,而是某个我真正在乎的质量属性被当前架构卡住了,并且这个卡点是已经量出来的真实瓶颈,这时才升级。 升级架构是有巨大成本和风险的动作,它必须是为了换取某个具体的、当下需要的质量属性——这正是 06 质量属性与取舍 教你的判断方式。
而且,每一次决定升级架构,本身就是一个该写 ADR 的重大决策:背景要说明什么瓶颈逼我们动,决策要说明升成什么,其它选项要说明还能怎么扛,取舍要说明为这次升级我们付出什么。你看,本章所有的工具,最后都串回了 ADR。
🎯 随堂检验
- A微服务框架选 Spring Cloud 还是 Istio
- B哪个我们在乎的质量属性被真实量化的瓶颈卡住了——没有信号就不该动
- C能否一次性重写,彻底换掉旧架构
本章小结
- 最先丢失的永远是为什么:代码和图能说清系统是什么,但讲不清为什么这么选、放弃了什么——而后者才是后人最需要、最易蒸发的东西。
- ADR,也就是架构决策记录,是解药:一份轻量、追加不修改、和代码放在一起的文档,记下每个重要决策。模板就六块:标题、状态、背景、决策、考虑过的其它选项、取舍与后果。
- 强观点:记为什么比记是什么重要一百倍。 把记录的力气,花在那些一旦丢失就再也找不回来的东西上。
- 演进式架构:别想一次设计到位,而要把系统设计成容易改对的样子——在最可能变的地方留好清晰的接缝,也就是模块边界和接口,让演进从重写变成替换。
- 技术债不全是坏事:它是有意识的权宜之计。纪律是有意识地借、记下来、安排偿还时机;危险的是无意识的、不记录的、只借不还的债。
- 康威定律:架构会长得像组织的沟通结构。拆服务前先看团队边界;也可反向用它——想要什么架构,先组织成什么团队。架构难题常是组织难题的伪装。
- 何时升级架构,靠判断不靠感觉:不是旧了、丑了、别人上了就升级,而是某个真正在乎的质量属性被真实瓶颈卡住了才升级——用 06 的尺子量,别拍脑袋。
📌 真实案例:ADR 的起源
本章讲的 ADR,来自 Michael Nygard 2011 年的博文 《Documenting Architecture Decisions》——他提出用一个个轻量小文件,记录每个决策的背景 / 决定 / 状态 / 后果。这套格式后来成了业界标准。
- 📎 社区资源与各种模板 / 工具:adr.github.io
- 本仓库每个模板的关键决策与权衡一节,本质就是一组写好的 ADR。
结语:成为一个持续做出好判断、并把判断沉淀下来的人
读到这里,整套教程就走完了。让我们回到最开始、回到 根 README 里说的这个仓库存在的理由:
写代码正在消失,而架构判断力,正变得前所未有地稀缺和值钱。
这八章,你学的从来不是某门语言、某个框架——它们都会过时,今年流行的明年就换。你学的是一种不会贬值的东西:
会贬值的(AI 正在让它廉价): 不会贬值的(越来越稀缺):
• 某个语法怎么写 • 拿到模糊需求,问出对的问题
• 某个框架的 API • 在取舍中做出有依据的选择
• 某段样板代码 • 看清系统会死在哪、该换什么
• 一次性的实现 • 把「为什么」沉淀成可复用的智慧
──────────────────────── ────────────────────────────
→ 交给 AI → 这,才是未来开发者的核心而走完这最后两章,你应该对优秀的架构师有了一个比第一章更完整的画像。他不只是能设计出好系统的人,那是 07 的重点;更是一个持续地做出好的架构判断、并把每一个判断和它背后的理由都沉淀下来的人,也就是 08 的重点。
因为单次的好设计会随时间锈蚀,但不断判断 + 不断记录这个循环,会让你和你的系统一起,越来越强:
┌─────────────────────────────────────────┐
│ │
▼ │
做出一个架构判断 ──▶ 把「为什么」记成 ADR │
(用 01-07 的方法) │ │
▼ │
业务长大 / 出现新瓶颈 ◀───────────────┘
(用 06 的尺子重新判断,回到顶端)
↑
判断力在每一圈里复利增长代码会变,框架会换,连架构这个词的时髦说法也会一茬接一茬。但在动手之前先想清楚系统该长什么样、并能讲清每个选择为什么——这种判断力,会在你整个职业生涯里持续增值。这,就是这个仓库想送给你的东西。
最后一个练习,然后就靠你自己了
把模板当 ADR 来读。 现在回到
../templates/,挑任意一个系统,直奔它的第 8 节:关键架构决策与权衡。你会发现:那一节的每一条,其实就是一份压缩版的 ADR——它有背景,说明面临的选择;有决策,说明最终取向;有放弃的选项;也有取舍,说明代价。试着把 AI 对话产品的决策 1:流式还是一次性返回 按本章那张六块模板,亲手补成一份完整的 ADR。
做完这件事,你就同时拥有了这套教程的两样东西:像架构师一样判断,也像架构师一样把判断留下来。 剩下的,就是去真实世界里,一个系统接一个系统地练。
相关链接
- 上一章:07 · 从 0 到 1 设计一个系统 —— 第 ⑧ 步说出口的为什么,正是这一章要你记成 ADR 的内容
- 全程呼应:06 · 质量属性与取舍 提供判断何时升级架构的两把尺子;04 · 十大核心架构模式 提供微服务拆分与康威定律的背景
- 回到起点:根 README 与 教程总览 —— 重读这个仓库为什么存在,你会有新的体会
- 把模板当 ADR 读:
../templates/全部模板的第 8 节关键决策与第 12 节演进路线,是 ADR 思想和演进式架构最浓缩的实例
💬 评论