DDIA 導讀 CH2 — 非功能需求 (Non-functional Requirements)

2026年4月13日

💎 加入 E+ 成長計畫 與超過 1000+ 位工程師一同在社群成長,並獲得更多深度的軟體前後端學習資源

在開發軟體產品時,產品本身要達到的功能會被歸類為功能需求 (functional requirement)。舉例來說,在社群媒體網站中,讓使用者可以瀏覽動態牆、能留言、能按讚,這些都屬於功能需求。但要讓一個產品受使用者青睞,除了功能本身以外,還有其他需要看重的。

舉例來說,效能就是多數使用者在乎的。先前有不少研究指出,如果一個電商網站的加載變快,將能顯著提升使用者的留存率。以多數人的使用經驗來說,相信不會想要逛一個每次進去都得等五秒、十秒的電商平台或社群媒體。效能就是屬於非功能需求,而除了效能以外,軟體產品的可用性、資訊安全等,也都是重要的非功能需求。

從我們的觀點看,身為軟體工程師,能把功能實作出來是最基本的;如果想要成為資深工程師,就不能只是讓東西能動就好,「做好非功能需求的設計」是不能不面對的門檻。

在眾多非功能需求中,作者在這個章節著重其中四種,包含效能、可靠性、可擴展性,以及可維護性,以下讓我們分別來討論。

效能 (Performance)

當提到軟體效能時,相信多數人會想到延遲度 (latency) 與吞吐量 (throughput) 這兩個衡量指標。

所謂的延遲度是指請求進到系統到系統回應的這段時間,理想上如果延遲越低會越好。例如某支 API 的回應速度能在一百毫秒內,延遲度就會比五百毫秒回應來得低。而吞吐量則是指某個系統每秒鐘能處理多少請求或資料,例如每秒可以處理萬筆寫入請求,理想上越高會越好。

雖然以理想的狀況來說,低延遲與高吞吐 (low latency and high throughput) 是軟體系統設計者的目標。但就現實來說,在資源有限的狀況下,兩者經常會有取捨。假如今天一台機器處理的請求量多起來,可能 CPU 正在處理某個請求,導致新進來的請求無法馬上處理,這樣延遲度就會增加。

作者在下方可擴展性的篇幅中,會多談吞吐量,以下讓我們先針對延遲度來討論。

拆解回應時間

在看延遲度時,書中有特別進一步拆分。當一個請求進來後,會先有網路延遲,接著可能會需要排在佇列上等待被處理,接著才會真正被處理;處理完之後回傳又會再有網路傳輸的時間。雖然書中沒細談,在實務上這個流程可以拆到更細。舉例來說,在請求送到客戶端後,又可以拉出另一個流程細節,在 關鍵渲染路徑 (critical rendering path) 一文中,我們有談到從前端的角度如何拆解關鍵渲染路徑。

在實務上拆解這樣的流程會很有幫助,具體會推薦在流程中的每一個節點,都要衡量相關的時間。這樣當今天請求回應變慢,可以立即看出是哪一段不尋常,讓團隊能加速找出問題所在。

為什麼推薦用中位數與百分位數衡量

在衡量延遲度時,書中推薦不要用平均數來衡量 (我們在 SLO 是什麼? 如何為團隊設定 SLO? 主題文中有談過同樣的觀點)。

這是因為當用平均數來衡量,沒辦法清楚得知有多少使用者遇到延遲度高的請求。舉例來說,如果平均回應時間是 200 毫秒,這看起來可能很不錯;但有可能有一大群很快、另一大群很慢的請求,只看平均沒辦法看出那群很慢的請求有多慢。

反之,如果用中位數與百分位來衡量,就能夠清楚許多。假如中位數 (俗稱 p50) 是 200 毫秒,就代表有一半的請求超過 200 毫秒才完成回應。如果第 95 百分位 (俗稱 p95) 是 1.5 秒,就能夠看出有 5% 的請求超過 1.5 秒才獲得回應。對於使用者數量龐大的軟體系統來說 (例如千萬量級以上),即使 5% 也超過 50 萬,數量上相當可觀,用百分位數就能讓軟體團隊去照顧到這一塊。

除了不要用平均數這點,作者在這個區塊中也有談到 SLO,書中有關 SLO 的內容基本上我們在 SLO 是什麼? 如何為團隊設定 SLO? 主題文中都有討論到 (甚至談得比書中提的深),因此推薦還不熟的讀者可以回顧。

可靠性 (reliability)

對應用程式來說,可靠意味著使用者在用的時候,不會有預期外的問題,例如功能無法如期運作、效能太差跑不動等。

不過軟體應用的運作過程中,難免會出問題,幾乎不可能打造完全沒問題的軟體產品。所以從系統的角度來看,更關鍵的點是要有韌性 (resilience),意即假如有出現錯誤,系統也能夠容錯並繼續如期運作。在業界,有混沌工程 (chaos engineering) 這種行之有年的做法 (最有名的是 Netflix 的 Chaos Monkey),會在生產環境上刻意注入不同類的錯誤,然後確保系統都能在這類錯誤出現時,仍然持續運作。

在書中,作者把常見的錯誤分成三種類別,硬體故障 (hardware faults)、軟體錯誤 (software errors)、人為錯誤 (human errors)。

磁碟壞掉、網路海纜被深海魚類咬壞、因為龍捲風導致電網被摧毀等狀況,都可能導致硬體故障。由於應用程式最終仍然需要跑在硬體上,所以當這類硬體故障發生,也可能導致服務不可用。針對硬體故障,最直觀的解決方法就是增加冗餘 (redundancy),也就是多準備硬體以備不時之需。舉例來說,假如資料中心遇到天災,可以透過多地區資料中心的備份,把請求導去別的資料中心來處理 (備註:我們在 什麼是爆炸半徑 (blast radius)? 如何有策略地縮減? 一文有談到相關內容)。

比起硬體故障,軟體錯誤導致的影響範圍通常會比較大。因為硬體的故障多半是局部的 (假如某個颱風造成東亞地區的硬體設備損毀,在北美區的不會受影響),但軟體錯誤的影響範圍則難有這類自然的限縮。舉例來說,在 2025 年的 Cloudflare 全球事故(新聞連結),就是因為軟體上的錯誤導致影響範圍擴及全球。

最後,人為錯誤則是指因為人為操作而造成的錯誤。例如我們在 什麼是功能旗標 (feature flags)? 為什麼要用功能旗標? 一文談過,當年 AWS 因為人為配置錯誤,造成上億美元損失的錯誤,就是人為錯誤的一種。在軟體設計上,讓軟體介面簡單易懂、有充足的測試、上線時有監控等,能有效降低人為錯誤帶來的損害。

閱讀更多

除了上面提到的點,在 DDIA 第二章,作者還談到了可維護性與可擴展性,如果你對完整 DDIA 第二章的導讀感興趣,我們在 E+ 成長計畫中的主題文,有完整的版本。對更深入了解這個主題,以及其他前後端開發、軟體工程、AI 工程主題感興趣的讀者,歡迎加入 E+ 成長計畫一起成長 (連結)。

🧵 如果你想收到最即時的內容更新,可以在 FacebookInstagram 上追蹤我們