跳過需求直接畫架構
症狀:聽完題目後立刻說「我們需要 Kafka、Redis、一個 API Gateway…」
問題:架構是需求的答案,不是起點。不知道 QPS、不知道讀寫比、不知道 consistency 要求,根本不知道需不需要 Kafka。
正確做法:先澄清 NFR(latency、throughput、consistency、durability),再估算量級,最後才設計。
NFR 都是事後補
症狀:「系統要快、要穩、要安全」——這些在文件裡確實有寫,但都是開發完成後補上去的,沒有驅動任何設計決策。
問題:NFR 定義太晚,等到效能問題出現才發現架構根本不支援。
具體案例:沒有在設計初期定「p99 latency < 200ms」,後來查詢加了 N+1 問題,上線前壓測才發現,這時要改已經很痛。如果一開始就有這個 NFR,設計階段就會加快取或 denormalize。
所有服務都要 Microservice
症狀:一個新功能,不管多小,都要「拆成微服務」。10 人團隊管 30 個 microservice。
問題:Microservice 解決的是「大型 team 的獨立部署和組織邊界」問題——它不是架構最佳實踐,它是一個有成本的組織設計工具。
拆得太細的代價:
- 服務間的網路呼叫 latency 加總
- Distributed transaction 的複雜性(沒有 ACID 了)
- 每個服務都要自己的 CI/CD、log aggregation、service discovery
- 新人 onboarding 要理解 30 個 service 的 interaction
正確做法:先做 Monolith,當你能清楚說出「這個模組的獨立部署需求、這個團隊有自己的上線節奏」,再考慮拆出去。
估算靠感覺不做 Back-of-Envelope
症狀:「我們預計流量不小,所以要 Sharding」——但沒有算過具體數字。
問題:沒有量化估算,不知道是需要應付 1K QPS 還是 1M QPS,架構設計就是在猜。Sharding 在 10K QPS 完全不需要,在 1M QPS 是必須的——這兩個設計完全不同。
5 分鐘的 back-of-envelope 計算(DAU × 每日操作數 / 86400 = QPS)就能確定量級,不需要精確。
UML 畫到沒人看
症狀:花了兩週畫了詳細的 UML 序列圖、類別圖、部署圖——然後沒有人在開發時參考。
問題:文件和實作脫離。圖在第一版就開始腐化,等開發完成圖和系統已經不一樣了。
有效的圖的原則:只畫「不畫就會誤解的部分」。架構決策和系統邊界值得畫,每個方法的細節不值得畫。圖的維護成本要遠低於溝通收益才畫。
Trade-off 選項自己都沒考慮過
症狀:選了 Kafka 但說不出「為什麼不是 RabbitMQ」「為什麼不是直接用 DB 的 polling」。
問題:沒有考慮過替代方案,就不知道選擇的成本是什麼。
每個架構決策都應該能說出:
- 我考慮了 A、B、C 三個選項
- A 的 trade-off 是 X vs Y,我選 A 是因為在這個場景 X 更重要
假設 Network 100% 可靠
症狀:服務呼叫沒有 timeout,沒有 retry,沒有 circuit breaker。
問題:下游掛了,上游一直等,connection pool 被耗盡,整個系統雪崩。
在分散式系統裡,「任何外部呼叫都可能失敗」不是邊界情況,是正常操作假設。參考 8 條 Fallacies。
以為分散式系統能做到 Strong Consistency + Availability + Partition Tolerance
症狀:「我們的系統需要 100% 可用,資料要強一致,而且要能在網路 partition 時繼續工作。」
問題:CAP Theorem 說這三個只能有兩個。如果你的系統需要 Partition Tolerance(分散式系統幾乎都需要),那麼在 partition 發生時必須在 Consistency 和 Availability 之間選一個。
正確做法:先確認業務需求對哪個更不能接受——短暫不一致(選 AP)還是暫時不可用(選 CP),根據這個選擇再設計。