跳過需求直接畫架構

症狀:聽完題目後立刻說「我們需要 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),根據這個選擇再設計。