Software Architect · 模块 02
在架构里几乎不存在“正确”的选项。只有一种选项:“我们有意识地为这个属性付出这样的代价。”
Latency · consistency · maintainability · cost of complexity
架构师不去追逐 best practice。他要做的是,命名选择的轴线,以及每个轴线上需要付出的代价。
没有代价的“决策”不算决策
飞机比火车快,但更贵、更挑天气、还不会把你送到市中心。"飞机更好"是一种糟糕的架构语言。
trade-off 就是用一个属性去交换另一个属性。系统里最常见的几条轴:latency vs. throughput、consistency vs. availability、simplicity vs. flexibility、time-to-market vs. maintainability、operational cost vs. development speed、vendor control vs. build cost。
专业的对话听起来是这样的:"我们选 managed Postgres,因为团队小,运维速度对我们而言比对 storage layer 的完全掌控更重要。"或者:"我们现在不引入 Kafka,因为我们用不到 replay 和 high throughput,但 operational complexity 明天就会变得非常真实。"
复杂度必须买到一个具体的能力
在一居室里塞一套工业级厨房,做饭是能做。住人就难了。
复杂度并不总是坏事。有时它是必要的:multi-region、event sourcing、sharding、service mesh、CQRS、Kubernetes。但每一项都必须买到一个具体属性——这个属性要么已经重要,要么几乎可以肯定即将变得重要。
如果团队说不清这份复杂度到底买到了什么,通常就是 over-engineering。如果团队为了"简单"而对已经存在的痛点视而不见,那是 under-engineering。
只有当 trade-off 真正改变了决策,它才有用。
例子:REST 还是 GraphQL
菜单适合菜式标准化的餐厅。沙拉自选台适合每位客人都想自己搭配的场景。
REST 适合资源稳定、缓存有效、客户端形态相似、API 需要对外集成保持简单的场景。GraphQL 适合客户端多样、数据形态各异、前端经常被 overfetching 或 underfetching 折磨的场景。
trade-off:GraphQL 把灵活性交给客户端,代价是 observability、字段级 authorization、缓存、rate limiting 和性能控制都变得更复杂。REST 运维上更简单,但可能让 endpoint 数量增多,并把客户端逼到多轮请求。
机场有塔台,但这不等于自行车停车场也得有一个。
抛开 Netflix、Uber、Amazon 各自的体量,直接抄它们的架构,就是 cargo cult。大公司的负载、团队、compliance、legacy 和宕机成本都和你不同。他们的决策在他们的语境里也许正确,搬到你这里却可能有害。
架构师必须能这样说出口:"是的,这是行业里的 pattern。不,我们的问题还不在那一档。"
- 当前决策落在哪些 trade-off 轴上? - 这份复杂度买到了什么? - 如果选最简单的方案,会发生什么? - 哪个信号会告诉我们,该加复杂度了?