前端系統設計面試:在沒有正確答案時做決定並說清楚取捨

文字解析 · 1 支影片 · 產生於 2026-10-01 00:54

🎧 語音解析📝 筆記✍️ 練習

🎧 語音解析 21m42s · TTS 講解與作者原聲交錯;點章節可跳。
邊聽邊看逐句講稿,點任一句從那裡開始
章節(8)

1. Outline

  1. 起點 · How Senior Frontend Engineers Think in System Design Interviews
    把「系統設計面試在找正確答案」這個前提拆掉,改成一套可執行的三步驟:釐清需求 → 用 steel thread 選最薄的起點 → 講清楚取捨與回頭修正的條件。

2. YouTuber 的思維推導

How Senior Frontend Engineers Think in System Design Interviews

I Code It · 11m07s · 字幕 en · vision=off (已取樣 9 個時間點驗證:畫面全是講者說話與 B-roll,沒有圖表、程式碼或對照表,只有偶爾的關鍵字字卡。保留 2 張有字卡的截圖,AI 不需逐張讀圖。) · YouTube

預估 vs 實際耗時
階段預估實際
fetch 6s 2s
segment 52s –
shot 37s 12s
analyze 5m00s –
render 5s –

作者的推導從一個觀察出發:卡在前端系統設計面試的人,往往不是知識不足,而是知識夠多到看得見一堆合理選項,於是不敢下手。他先把這個現象重新定義成問題設定的錯誤——「找出正確答案」根本不是面試在測的東西,接著用真實工程當對照:真實專案永遠帶著既有程式碼、團隊、技術棧這些限制,所以本來就沒有脫離情境的最佳解,只有對這個產品合理的解。有了「解取決於情境」這個前提,他才敢舉兩個例子來證明它不是空話:分頁(搜尋結果 vs 動態牆)和即時協作(白板 vs 看板)。

兩個例子刻意同構——同樣的技術題目,因為產品體驗與使用者行為不同,答案就翻轉。證明完之後,他把「依情境決定」變成可執行的三步驟:Clarify(先問清楚要設計什麼)、Choose(用 steel thread 選最薄的端到端起點)、Explain(說明取捨與何時回頭修正)。最後收束回面試的意義:好題目測的不是你認不認得某個模式,而是你能不能在情境中套用它——這也正是資深工程師在真實專案裡每天做的事。

推理鏈:每段留給下一段的線索

每一列是一段,箭頭後的字是這段留給下一段的線索。點段落標題跳到該段。

  1. 卡住的不是知識,是選擇 → 留下一個還沒被證明的斷言:面試官要的不是完美答案。但憑什麼?如果真的存在正確架構,猶豫反而是謹慎。下一步必須先說明為什麼「正確答案」在真實工程裡根本不存在。
  2. 真實工程不是選擇題 → 留下一個具體的挑戰:如果解真的取決於產品情境,那就必須拿得出「同一個技術題目、因情境不同而答案相反」的實例,否則這只是漂亮話。下一步需要第一個對照實驗。
  3. 例一:分頁 — 搜尋結果 vs 動態牆 → 留下一個尚未確認的推論:這套「看產品體驗決定技術」的方法,會不會只在分頁這種簡單題目上成立?下一步需要一個更複雜、更容易讓人相信有標準答案的題目來檢驗。
  4. 例二:即時協作 — 白板 vs 看板 → 留下一個已經成熟的空缺:兩個例子都證明了答案取決於情境,但「取決於情境」對正在面試、正在冒汗的人來說仍然不可執行。下一步必須把它變成當場能照著做的步驟。
  5. 解法三步驟:釐清、選擇、解釋 → 留下一個接著要填的空:需求釐清完了,資訊還是不會完整,你終究得在不確定中選一個方案。下一步要回答「該選哪一個」,而且必須給出可操作的選法。
  6. 選一個合理起點:steel thread → 留下一個沒被說完的部分:選了一個刻意簡單的起點,你要怎麼讓對方相信這是判斷而不是能力不足?下一步必須處理如何把這個選擇講出來。
  7. 把取捨講清楚 → 留下最後一個要收束的問題:既然這三步就是資深工程師的日常,那系統設計面試這種看起來人工的形式,究竟在測什麼、又為什麼值得?
  8. 總結:把模式用在情境裡

3. 逐段說明

How Senior Frontend Engineers Think in System Design Interviews

1. 卡住的不是知識,是選擇 0:00–2:13

作者指出很多前端工程師在系統設計面試卡住,不是因為懂得太少,而是因為看得到太多合理選項:cursor 還是 offset 分頁?WebSocket 還是輪詢?他們相信有一個「正確架構」藏在某處,只要念夠多理論就能找到。但面試官多半不是在找完美答案,而是看你能不能理解問題、做出合理決定、講清楚取捨、然後繼續往前推進。

承上 前情提要裡假設你已經會做功能:熟一個框架、串過 API、處理過狀態管理、路由、表單,甚至做過效能優化。這一段就是從「會做功能」跨到「設計系統」時斷掉的那一步。

推理作者從讀者的實際體感切入:一被問到「設計一個系統」,腦中冒出的不是空白,而是一串二選一——cursor 還是 offset 分頁?WebSocket 還是輪詢?資料要正規化還是保持巢狀?要不要加快取?該從簡單方案開始,還是那樣顯得太資淺?他接著點出一個反直覺的因果:懂得越多越難受,因為你看得見越多可行選項。所以卡住的原因不是知識不足,而是有好幾個都說得通的選項,卻不知道怎麼選一個、講清楚、然後往前走。這些人心裡假設有一個「正確架構」藏在某處,只要理論念夠多、題目練夠多、想得夠久就會找到——而作者說,那通常不是系統設計面試在測的東西。面試官多半想看的是四件事:能不能理解問題、做出合理決定、解釋取捨、並持續推進。

AI 補充值得注意的是作者在這裡偷偷做了一次「問題重寫」,這是全片最關鍵的一步。原本的問題是「我要怎麼背下某類題目的正確設計」,被改寫成「需求不完整時,我要怎麼做出合理決定並清楚解釋取捨」。這兩個問法的差別在於可行性:第一個問題沒有終點,因為題型無限;第二個問題有明確的可練習動作。另外作者列出的那串二選一並非隨機——它們全都是「沒有絕對優劣、只有適用情境」的成對選項。會讓人癱瘓的正是這種題目:如果有一個選項客觀更好,你根本不會猶豫。

術語:offset-based paginationcursor-based pagination

system design interview

系統設計面試

面試官給一個開放式的產品需求,請你當場設計出系統架構並解釋決策的面試型態。

跟考演算法題最大的差別是沒有標準輸出:題目本身是刻意含糊的(「設計一個 Google Docs」),釐清需求就是答題的一部分。前端版本的系統設計聚焦在資料抓取與快取、狀態管理、渲染策略、即時同步、離線與錯誤處理,而不是資料庫分片或負載平衡。評分通常看四個面向:需求釐清、方案取捨、溝通清晰度、以及能不能在資訊不足時繼續推進。

相關術語: trade-off (核心評分項)

出處:第 1 段「卡住的不是知識,是選擇」

trade-off

取捨

選擇一個方案時,必然要放棄另一個方案的某項好處——沒有全贏的選項。

取捨之所以是系統設計的核心,是因為架構決策幾乎都在互斥的維度之間分配資源:一致性 vs 可用性、開發速度 vs 未來彈性、簡單 vs 通用。能講出取捨,代表你知道自己「付出了什麼」換到「什麼」;只講好處不講代價的回答,通常代表還沒真正比較過。要注意「討論取捨」和「困在取捨裡」是兩回事,前者是推進,後者是停滯。

相關術語: system design interview (被評分於)

出處:第 1 段「卡住的不是知識,是選擇」

offset-based pagination

偏移量分頁

用「跳過幾筆、取幾筆」(如 LIMIT 20 OFFSET 40)來取得列表的某一段,前端表現成第 1 頁、第 2 頁。

優點是直覺、好實作、可以直接跳到任意頁,也容易做出頁碼列與「共 N 頁」。代價有兩個:一是資料在你翻頁期間被新增或刪除時,會漏看或重複看到項目,因為 offset 是相對於當下快照的位置;二是 offset 很大時資料庫仍須掃過前面所有列,深頁效能會退化。因此它適合資料相對穩定、使用者需要位置感的列表。

相關術語: cursor-based pagination (對照組)

出處:第 1 段「卡住的不是知識,是選擇」

cursor-based pagination

游標分頁

用「從這個標記之後再給我 N 筆」的游標(通常是排序鍵或編碼過的位置)來取下一批資料,而不是用頁碼。

因為游標指的是資料本身的位置而不是序號,即使中途有新資料插入也不會漏抓或重複,深度翻頁的效能也穩定(查詢變成 WHERE key < cursor LIMIT n)。代價是不能跳到任意頁、難做頁碼列,也較難顯示總頁數。它天然適合只往下走、且資料會持續長出來的列表。實作上常見的等價說法是 keyset pagination。

相關術語: offset-based pagination (對照組)

出處:第 1 段「卡住的不是知識,是選擇」

WebSocket

網頁通訊協定(全雙工長連線)

在瀏覽器與伺服器之間建立一條持續開著的雙向連線,兩邊都能隨時主動送訊息。

它解決的是 HTTP 的單向性:伺服器沒辦法主動通知瀏覽器。代價是需要維持連線狀態(重連、心跳、驗證續期),伺服器端的水平擴展也變複雜,因為連線是黏在某台機器上的。並非所有「即時」都需要它——只要伺服器單向推送就夠時,Server-Sent Events 更簡單;更新頻率低時,定時輪詢往往更划算。

相關術語: polling (對照組)

出處:第 1 段「卡住的不是知識,是選擇」

polling

輪詢

前端每隔一段固定時間就主動去問伺服器「有沒有新資料」。

最大的好處是無狀態、好實作、跟既有的 HTTP 快取與重試機制完全相容,出錯時只是下一次再問一遍。代價是延遲取決於間隔,而且沒有新資料時的請求全是浪費。折衷做法是 long polling:請求先掛著不回,等有新資料才回應,兼具低延遲與 HTTP 的簡單性。判斷準則是「可容忍的延遲」與「更新頻率」,而不是「哪個技術比較先進」。

相關術語: WebSocket (對照組)

出處:第 1 段「卡住的不是知識,是選擇」

留給下一段 留下一個還沒被證明的斷言:面試官要的不是完美答案。但憑什麼?如果真的存在正確架構,猶豫反而是謹慎。下一步必須先說明為什麼「正確答案」在真實工程裡根本不存在。

2. 真實工程不是選擇題 2:13–3:31

真實專案永遠帶著限制:既有 codebase、團隊結構、成員經驗落差、公司已選的技術棧。紙上看起來漂亮的方案,導入成本可能太高。所以真實世界沒有完美答案,只有「對這個產品、這個團隊、這些限制而言合理」的方案。這也解釋了為什麼有能力的工程師反而卡住:他們看得到太多取捨,於是不斷列選項、不斷比較,等待對方確認。討論取捨是好事,被困在取捨裡不是。

承上 承上:上一段斷言面試官要的不是完美答案,但還沒說明理由。這一段就從真實工程長什麼樣子,來證明「完美答案」本身就是個不存在的東西。

推理因為上一段把問題重寫成「資訊不完整時怎麼決定」,作者接著要證明資訊不完整才是常態。他的論證方式是把真實專案的起點攤開:開始一個專案時,你面對的是一個真實問題——產品問題、使用者痛點、或必須解決的商業需求——而且一進入真實工作,限制就一定在:既有的 codebase、團隊結構、成員經驗落差、公司已經在用的技術棧、資料庫或平台。有時方案紙上很漂亮,但導入成本太高。結論因此成立:真實軟體裡通常沒有完美答案,只有「對這個產品、這個團隊、這些限制而言說得通」的方案。而這正好解釋了上一段那個反直覺現象——有能力的工程師之所以卡住,是因為他們懂得多到不敢隨便下手,看得見很多選項與取捨,於是不斷列、不斷比,本該往前推的設計就停在原地等一個確認。作者下了明確的界線:討論取捨是好事,困在取捨裡不是。

AI 補充作者這裡的論證是「取消前提」而不是「回答問題」:他沒有教你怎麼找到正確答案,而是拆掉「有正確答案」這個假設。這一步值得留意,因為它同時解釋了為什麼練更多題目沒有用——如果解取決於情境,那麼可背誦的解就不存在。另外,作者把限制列成清單但沒有明說它們的共同性質:這些限制全都不在技術本身,而在技術之外(人、既有系統、時間、成本)。這帶出一個實務上的判準:當兩個方案技術上難分高下時,決定勝負的通常是團隊會不會維護它,而不是它跑得多快。還有一件作者只點到的事——他說「導入成本太高」,這個成本不只是寫程式的時間,而是往後每一次上線、除錯、招人、交接都要付的持有成本。

術語:constraintanalysis paralysistotal cost of ownership

constraint

限制條件

決策時不能改變、只能接受的既有條件:既有程式碼、團隊能力、公司技術棧、時程與預算。

限制在系統設計裡的地位跟需求同等重要,但常被忽略,因為它們不會寫在題目上。實務上限制往往比需求更能決定架構:同一個功能,在已有 GraphQL 的公司和只有 REST 的公司會長成不同樣子。面試時主動問限制(「團隊多大?」「現有技術棧是什麼?」「多久要上線?」)通常會被視為資深訊號,因為它顯示你知道方案是要活在某個環境裡的。

相關術語: total cost of ownership (常見來源)

出處:第 2 段「真實工程不是選擇題」

analysis paralysis

分析癱瘓

因為看得見太多可行選項與取捨,反覆比較卻遲遲不做決定,導致完全沒有進展的狀態。

它是知識帶來的副作用,不是無知的結果——這也是為什麼中高階工程師比新手更容易中招。在面試裡的典型表現是:把五個方案都講一遍、每個都給優缺點、然後停下來等面試官表態。破解方式不是少想,而是替自己設一個決策規則,例如「先選最簡單能動的那個,並說清楚什麼情況會讓我改變主意」——把決定變成可撤回的,決定就不那麼可怕了。

相關術語: trade-off (困在其中)

出處:第 2 段「真實工程不是選擇題」

total cost of ownership

總持有成本

一個技術方案從導入到汰換之間的全部成本,不只是寫出來的時間,還有維運、除錯、升級、教學與交接。

作者說「紙上漂亮但導入成本太高」,指的就是這件事。開發成本是一次性的,持有成本卻是持續的:多一個需要專人照顧的元件,就多一份長期負債。這解釋了為什麼團隊常常選擇「較差但熟悉」的技術——熟悉度直接降低持有成本。評估時可以問自己:半年後半夜出事,誰能修它?

相關術語: constraint (轉化為)

出處:第 2 段「真實工程不是選擇題」

留給下一段 留下一個具體的挑戰:如果解真的取決於產品情境,那就必須拿得出「同一個技術題目、因情境不同而答案相反」的實例,否則這只是漂亮話。下一步需要第一個對照實驗。

3. 例一:分頁 — 搜尋結果 vs 動態牆 3:31–5:39

第一個例子是分頁。「該用哪種分頁策略」聽起來有標準答案,其實取決於產品。搜尋結果頁的使用者需要位置感:想翻下一頁、回上一頁、比較列表不同段落,page-based 分頁符合他們的心智模型。動態牆(feed)則相反:使用者不會想「跳到第七頁」,只是持續往下看,新內容還會不斷長出來,所以 cursor-based/無限捲動是比較好的起點。同樣是長列表,產品體驗、使用者行為、資料出現方式都不同,分頁策略自然不同。關鍵句是「我會從這裡開始」,而不是「這是唯一解」。

承上 承上:上一段要求拿出「同一題目、答案因情境翻轉」的實例。作者接下來用兩個例子回應,第一個是分頁——正好就是第 1 段那串二選一裡的頭一個。

推理因為上一段確立了「解取決於情境」,作者接著要示範情境怎麼決定解。他刻意挑一個聽起來有標準答案的問題——「我們該用哪種分頁策略?」——然後把它拆成兩個產品來看。搜尋結果頁:使用者搜尋、拿到一串結果,通常想要清楚的位置感,想翻下一頁、回上一頁、比較列表不同部分的結果;在這種體驗裡 page-based 分頁說得通,因為「頁」這個概念符合使用者的心智模型,給他位置感,也讓他容易回到結果集的特定位置。動態牆(feed)則完全相反:使用者不會想「我要去第七頁」,他只是持續消費內容,新內容還會隨時間冒出來、列表不斷長大,所以持續往下捲才自然,cursor-based 載入或無限捲動是比較好的起點。作者把對照的結構點明:兩邊都是長列表資料,但產品體驗不同、使用者行為不同、新資料出現的方式也不同,所以分頁策略可以不同。最後他要讀者注意一個措辭——「我會從這個方向開始(start with)」,而不是「這是唯一可能的設計」;意思是依目前需求,這是合理的基準線,需求變了就回頭重新檢視。

AI 補充這個例子之所以有說服力,是因為兩種分頁的技術代價剛好對上兩種產品的使用方式,而作者沒有把這層講滿。搜尋結果通常是一次查詢的靜態快照,資料在你翻頁時不太會變,所以 offset 分頁「翻頁期間資料位移」的弱點在這裡幾乎不發生;而它能跳到任意頁的能力,正好是使用者要的。動態牆恰恰相反:新貼文隨時插到最前面,用 offset 的話你往下捲時會重複看到同一則貼文——這是真實可觀察的 bug,不是理論疑慮;cursor 因為指向資料本身的位置,天生免疫。所以「取決於產品」不是含糊其詞,而是可以推導的:先看資料變動頻率與使用者的移動方式,技術選擇會自己浮現。另外「start with」這個措辭比它看起來重要得多——它把一個決定從「宣稱最佳」降級成「可修正的起點」,同時免除了你必須正確的壓力,這正是第 2 段那種分析癱瘓的解藥。

術語:page-based pagination

pagination

分頁

把一個大列表切成小批次逐次取得與顯示,而不是一次載入全部。

分頁同時解決三個問題:伺服器一次查詢的負擔、傳輸量、以及瀏覽器要渲染的節點數。它的設計選擇不只在後端 API,還牽動前端的快取結構(要不要保留看過的頁)、網址狀態(能不能分享第 3 頁的連結)、以及回上一頁時的捲動位置還原。因此它常被當作前端系統設計的入門題——小題目,但每一層都碰得到。

相關術語: offset-based pagination (一種)、cursor-based pagination (一種)

出處:第 3 段「例一:分頁 — 搜尋結果 vs 動態牆」

page-based pagination

頁碼分頁

以「第幾頁」為單位取資料的分頁方式,介面上呈現為頁碼列,使用者可直接跳到任一頁。

它通常就是偏移量分頁(見第 1 段)的介面呈現:頁碼乘上每頁筆數就是 offset。之所以值得跟底層實作分開講,是因為它真正的價值在使用者端而非資料端——頁碼提供了「我在哪裡」「還有多少」的感覺,也讓「第 3 頁那筆結果」變成可溝通、可分享、可回訪的位置。當產品需要讓使用者比較或回到列表的特定部分時,這個介面語彙本身就是需求。

相關術語: offset-based pagination (常見實作)、mental model (訴諸)

出處:第 3 段「例一:分頁 — 搜尋結果 vs 動態牆」

infinite scroll

無限捲動

使用者捲到接近底部時自動載入下一批內容,不需要點「下一頁」。

它是游標分頁(見第 1 段)最常見的介面樣貌,適合持續消費型的內容。代價值得知道:頁尾(footer)幾乎變得無法點到、瀏覽器的返回鍵會失去捲動位置、列表越長 DOM 節點越多而拖慢頁面(因此常需搭配虛擬化只渲染可視區),而且使用者無法感知「還有多少」。這些代價在動態牆可以接受,在需要比較與回訪的列表則不行。

相關術語: cursor-based pagination (常見介面)、page-based pagination (相反)

出處:第 3 段「例一:分頁 — 搜尋結果 vs 動態牆」

mental model

心智模型

使用者心中對「這個系統怎麼運作」的想像;介面若符合它就覺得直覺,違背它就覺得難用。

作者說「頁的概念符合使用者的心智模型」,指的就是使用者已經從書本、搜尋引擎累積了「一頁一頁翻」的既有經驗。心智模型是技術決策的隱藏需求:同樣一份資料,選頁碼還是無限捲動,實際上是在選使用者要用哪一套既有直覺來理解它。在系統設計面試裡引用它,能把技術選擇接回產品層次,而不是停在效能比較。

相關術語: page-based pagination (支持)

出處:第 3 段「例一:分頁 — 搜尋結果 vs 動態牆」

留給下一段 留下一個尚未確認的推論:這套「看產品體驗決定技術」的方法,會不會只在分頁這種簡單題目上成立?下一步需要一個更複雜、更容易讓人相信有標準答案的題目來檢驗。

4. 例二:即時協作 — 白板 vs 看板 5:39–7:41

第二個例子是即時協作。該用 WebSocket 嗎?需要衝突解決嗎?CRDT 還是 OT?答案一樣看產品。白板類應用裡使用者同時畫、拖、改、移動物件,更新非常頻繁且細粒度,常常動到同一塊區域,因此同步要求高、衝突處理與順序都很重要。Trello/Jira 這種看板則是搬卡片、改標題、留言、指派,同樣是協作、同樣需要即時更新,但互動沒那麼連續、衝突好推理,簡單模型往往就夠。可能還是用 WebSocket,但不需要白板那種等級的衝突解決複雜度。

承上 承上:上一段留下的疑問是這套方法會不會只在分頁這種簡單題目上成立。作者因此換上即時協作——一個大家更相信有標準答案、也更容易掉進技術名詞堆的題目。

推理因為分頁的對照已經成立,作者接著用同一個結構檢驗更難的題目:即時協作也是大家常常在找「最佳解」的領域——該用 WebSocket 嗎?需要衝突解決嗎?要 CRDT 還是 operational transformation?他說這些都值得懂,但答案仍然取決於產品,然後擺出第二組對照。白板類應用(如繪圖、設計工具):使用者同時畫、拖、編輯、移動物件,更新非常頻繁且細粒度,人們可能幾乎持續地互動在同一塊區域;這種產品的同步要求高得多,衝突處理很重要、順序也很重要,系統必須讓協作既順暢又正確。看板類應用(Trello、Jira):使用者把卡片在欄位間搬動、改標題、加留言、指派某人、更新狀態;一樣是協作、一樣需要即時更新,但互動模式很不一樣——更新通常沒那麼連續、衝突也比較好推理,很多情況下簡單模型就夠了。你可能還是會用 WebSocket、還是需要即時同步,但不需要跟白板或設計工具同一等級的衝突解決複雜度。作者由此下結論:即時協作沒有普世答案,取決於是哪一種協作、更新多頻繁、使用者對產品的期待是什麼。所以把系統設計面試當成面試官在偷偷等一個魔法答案,是危險的;更強的做法是展示你怎麼想、怎麼做取捨、怎麼依情境調整設計。

AI 補充這一組對照的關鍵變數,作者提到了但沒有命名:兩人同時動到「同一個東西」的機率。白板上兩個人同時改同一個形狀的位置與大小是常態,所以你需要一套能把兩筆並發修改合併成一個合理結果的機制(這正是 CRDT 與 OT 在做的事);看板上兩個人同時改同一張卡片的同一個欄位則罕見,所以「後到的覆蓋先到的」這種最簡單的規則,出錯機率低到可以接受。判準因此可以量化成一句話:衝突的機率與衝突的代價,共同決定你需要多複雜的衝突解決。這也補上了作者跳過的一步——他說看板「衝突比較好推理」,理由其實是看板的操作大多是彼此獨立的離散動作(搬一張卡、改一個欄位),而白板的操作是連續且互相依賴的(一連串座標變化)。另外值得指出:作者把 WebSocket 與衝突解決拆成兩個獨立決定,這件事本身很有價值——很多人以為選了即時同步就得整套上,其實「怎麼傳」和「衝突怎麼解」是可以分開決定的兩個維度。

術語:last-write-wins

real-time collaboration

即時協作

多位使用者同時編輯同一份資料,且彼此的變更會即時出現在對方畫面上。

它至少包含三個可以分開決定的子問題:變更怎麼傳輸(WebSocket、SSE、輪詢)、變更怎麼合併(後寫覆蓋、OT、CRDT)、以及使用者怎麼感知彼此(游標、選取範圍、頭像)。把它們當成一整包會讓設計失去彈性;分開看則能依產品挑選各自的複雜度等級。作者這一段的整個論證,就是建立在這種可拆解性上。

相關術語: conflict resolution (子問題)、WebSocket (常見傳輸)

出處:第 4 段「例二:即時協作 — 白板 vs 看板」

conflict resolution

衝突解決

當兩位使用者幾乎同時修改同一份資料時,決定最終結果該長什麼樣的規則或演算法。

它的難度不是由技術決定,而是由產品的並發模式決定:衝突多不多、撞到時使用者會不會發現、發現了損失有多大。同樣是協作產品,可接受的答案從最簡單的「後寫覆蓋」、到欄位層級的合併、到完整的 OT/CRDT 都有。設計時的正確問法不是「要不要做衝突解決」,而是「這個產品的衝突長什麼樣、代價多大」。

相關術語: last-write-wins (最簡實作)、CRDT (進階實作)

出處:第 4 段「例二:即時協作 — 白板 vs 看板」

CRDT

無衝突複製資料型別(Conflict-free Replicated Data Type)

一種資料結構設計,讓各方各自套用收到的變更後,最終必然收斂到相同結果,不需要中央伺服器仲裁。

它的作法是把資料操作設計成可交換、可重複套用的形式,因此變更以任何順序抵達都不影響最終狀態,也天然支援離線編輯後再同步。代價是額外的中繼資料(每個元素可能都要帶識別碼與時間資訊),文件越編越大、記憶體與傳輸成本升高,實作與除錯也不容易。常見於白板、筆記與離線優先的協作工具。

相關術語: operational transformation (對照組)、conflict resolution (一種)

出處:第 4 段「例二:即時協作 — 白板 vs 看板」

operational transformation

操作轉換(OT)

把每個編輯記成一個操作,當並發操作抵達時依先後關係轉換它的參數,讓所有人套用後得到一致結果。

例如兩人同時在同一行插入文字,後到的插入位置會被「轉換」成考慮前者之後的正確位置。它比 CRDT 省空間,資料本身不需要額外中繼資料,但通常需要一台中央伺服器決定操作的權威順序,而且轉換函式的正確性很難證明——這是它出名難實作的原因。Google Docs 屬於這一路線。

相關術語: CRDT (對照組)

出處:第 4 段「例二:即時協作 — 白板 vs 看板」

last-write-wins

後寫覆蓋

最簡單的衝突處理規則:以最後抵達(或時間戳最新)的那筆寫入為準,覆蓋掉先前的值。

作者說看板類產品「簡單模型往往就夠」,指的通常就是這個。它幾乎零成本,代價是先寫的人的修改會靜默消失。之所以在看板上可以接受,是因為兩人同時改同一張卡的同一個欄位極少發生,而且真的撞到時損失小、使用者馬上看得見也能重打一次。同樣的規則放到白板或文件編輯就會災難性地丟資料。

相關術語: conflict resolution (一種)

出處:第 4 段「例二:即時協作 — 白板 vs 看板」

留給下一段 留下一個已經成熟的空缺:兩個例子都證明了答案取決於情境,但「取決於情境」對正在面試、正在冒汗的人來說仍然不可執行。下一步必須把它變成當場能照著做的步驟。

5. 解法三步驟:釐清、選擇、解釋 7:41–8:22

作者給出替代做法:Clarify、Choose、Explain 三步。第一步是釐清需求——先別急著解,花點時間搞懂這是什麼系統、要設計的使用者體驗是什麼、規模/一致性/交付速度各有多重要、真正的限制是什麼。很多虛弱的系統設計回答,都是因為太早開始解題。

字卡「1. Clarify 2. Choose 3. Explain」——全片方法論的骨架,一眼記住三步驟
7:47 · 字卡「1. Clarify 2. Choose 3. Explain」——全片方法論的骨架,一眼記住三步驟
承上 承上:兩個對照實驗都證明了答案取決於情境,但也留下「那我當場該做什麼」這個空缺。作者在這裡把方法變成三個可執行的動作。

推理因為前兩個例子已經把「依情境決定」證明完畢,作者接著回答那個實作問題:那該怎麼做?他給出三步——Clarify、Choose、Explain。這一段先講第一步:釐清需求。在跳去解法之前,花點時間搞懂這是什麼樣的系統:我們要設計的使用者體驗是什麼?規模、一致性、交付速度各有多重要?我們真正有哪些限制?他下了一個直接的診斷:很多虛弱的系統設計回答,都是因為太早開始解題。

AI 補充把作者列的三個問題對回前面的例子,就會看出它們不是泛泛的清單:「要設計的使用者體驗是什麼」正是分頁例子裡分辨搜尋結果與動態牆的那個問題;「規模、一致性、交付速度哪個重要」正是即時協作例子裡決定要不要上 CRDT 的那個問題;「有哪些限制」則是第 2 段整段的內容。也就是說,釐清階段問的東西,就是前面被證明會翻轉答案的那些變數——所以這一步不是禮貌性暖身,而是在蒐集決策真正需要的輸入。實務上有個好用的補充:把需求分成功能性(系統要做什麼)與非功能性(要做得多快、多可靠、多能擴展),後者才是架構的真正驅動力,也最常在題目裡被省略、需要你主動去問。另外「太早開始解題」在面試裡有個明顯症狀——三十秒內就開始講技術名詞。

術語:non-functional requirementspremature optimization

non-functional requirements

非功能性需求

不描述系統做什麼、而描述它要做得多好的需求:效能、規模、一致性、可用性、可維護性、交付時程。

作者問的「規模、一致性、交付速度有多重要」全都屬於這一類。它們之所以關鍵,是因為功能需求通常只決定要寫哪些畫面,非功能需求才決定架構長什麼樣:同一個聊天功能,要撐十人和要撐十萬人是兩套設計。面試裡它們幾乎不會主動給你,必須自己問——這也是為什麼釐清階段能明顯拉開回答的層級。

相關術語: constraint (常一起釐清)

出處:第 5 段「解法三步驟:釐清、選擇、解釋」

premature optimization

過早優化

在還不知道瓶頸或需求會不會出現之前,就先為了效能或未來擴展而增加複雜度。

作者說的「太早開始解題」是它的近親:兩者都是在資訊不足時就付出無法退回的複雜度成本。過早優化的代價不只是白工,而是這些複雜度會留在程式碼裡,讓之後每一次修改都變慢,且往往猜錯地方。解法不是永不優化,而是先量測、先讓需求出現,再決定投資在哪裡。

相關術語: YAGNI (對應原則)

出處:第 5 段「解法三步驟:釐清、選擇、解釋」

留給下一段 留下一個接著要填的空:需求釐清完了,資訊還是不會完整,你終究得在不確定中選一個方案。下一步要回答「該選哪一個」,而且必須給出可操作的選法。

6. 選一個合理起點:steel thread 8:22–9:04

第二步是選一個合理的基準線,不是最進階、最炫的方案,而是依目前所知說得通的起點。這裡用得上 steel thread:先做出最薄的端到端可運作方案,等需求明確把你推過去,才加複雜度。例如搜尋結果先用 offset 分頁(好實作、好理解),動態牆先用 cursor 載入,先用一般 request-response API,等即時需求明確到足以justify 才引入 WebSocket。這種回答顯示成熟度:不是為了聽起來聰明而加複雜度,而是讓方案match問題。

字卡「…nd-To-End Solution」——steel thread 的定義:最薄的端到端方案
8:27 · 字卡「…nd-To-End Solution」——steel thread 的定義:最薄的端到端方案
承上 承上:釐清完需求後,資訊仍然不完整,還是得選一個方案。作者接著給出選法——不是選最好的,而是選最薄的。

推理因為上一段確立了「先釐清再解題」,作者接著處理第二步:選一個合理的基準線。他特別強調不是最先進、也不是最令人印象深刻的方案,只是一個依目前所知說得通的起點。這裡他搬出 steel thread 的概念:先做出最薄的端到端可運作方案,之後只有在需求明確把你推過去時才加複雜度。然後他把這個原則套回前面兩個例子:搜尋結果也許先用 offset 分頁,因為好實作、好理解;動態牆也許先用 cursor 載入;即時性的部分也許先用一般的 request-response API,等到即時需求明確到足以正當化它時,才引入 WebSocket。作者說這種回答顯示成熟度:你不是為了聽起來聰明而加複雜度,而是讓方案配合問題。

AI 補充steel thread 之所以比「先做個簡單版本」更有力,在於「端到端」這三個字:它要求你的第一版必須貫穿整條路徑(介面 → API → 資料 → 回到畫面),哪怕每一段都很粗糙。這帶來一個具體好處——整條鏈上的未知數會在最便宜的時候先暴露出來,而不是等到你把某一層做得很精緻之後,才發現另一層根本行不通。這也讓它在面試裡特別好用:先把最薄的一條線講完,你就有了一個完整可討論的設計,接下來每一次加複雜度都能綁在一個具體理由上(「因為要支援離線編輯,所以這裡要換掉」)。要注意作者措辭裡的方向性——「等需求把你推過去」意味著複雜度需要被觸發,而不是被預測;這正是第 5 段那個過早優化的反面。從第 3 段的角度看,這裡也隱含著一個溫和的取捨:offset 分頁在資料會變動時有其弱點,但「好實作、好理解」在起步階段是真實的價值,且之後換成 cursor 的成本並不高——這正是可撤回決定的典型樣貌。

術語:walking skeletonYAGNI

steel thread

鋼線(最薄的端到端方案)

先建出一條貫穿整個系統、每一層都極簡但確實能跑通的完整路徑,之後再逐段加厚。

名稱的意象是先拉一條細鋼索橫跨峽谷,再沿著它建橋。它跟「先做一個模組」的差別在於方向:steel thread 是垂直切一片(每層都薄),而不是水平做完一層(某層很完整、其他層還不存在)。好處是整合風險最早暴露、隨時都有可展示的東西、也讓後續每次擴充都有既有基準可比。在面試裡它同時是一種敘事順序:先講通一條路徑,再回頭深化。

相關術語: walking skeleton (同義概念)、YAGNI (共同前提)

出處:第 6 段「選一個合理起點:steel thread」

walking skeleton

會走路的骨架

一個功能極少但架構完整、且真的能端到端執行並部署的系統初版。

它跟 steel thread 幾乎講同一件事,差別在強調重點:walking skeleton 額外要求這個初版是可建置、可部署、可測試的,也就是把交付流程本身也一併拉通。實務價值在於 CI/部署/環境設定這些最容易拖時程的東西會在第一天就被解決,而不是等到功能寫完才發現上不了線。

相關術語: steel thread (同義概念)

出處:第 6 段「選一個合理起點:steel thread」

YAGNI

你不會需要它(You Aren't Gonna Need It)

極限編程的原則:在真正需要之前不要先實作某個功能或抽象。

它針對的是「我猜之後會用到」這種預測式設計。之所以成立,是因為預測的命中率低,而錯誤的抽象比重複的程式碼更難拆除——你不只要寫它,還要繞著它寫。它不是反對設計,而是主張把決定延後到資訊最多的時刻。作者說「等需求明確把你推過去才加複雜度」,講的就是同一件事。

相關術語: premature optimization (對應原則)、steel thread (實作策略)

出處:第 6 段「選一個合理起點:steel thread」

request-response

請求/回應模型

前端主動送出一次請求、伺服器回一次結果就結束的通訊模式,也就是一般 HTTP API 的樣子。

它是預設值,也是最便宜的選項:無狀態、可快取、失敗就重試、除錯只要看一次請求。作者建議先用它、等即時需求明確才換成長連線,理由正是持有成本——長連線帶來重連、狀態同步與擴展上的複雜度。判斷是否該升級的問題很具體:使用者能容忍多久才看到別人的更新?

相關術語: WebSocket (升級選項)、polling (中間選項)

出處:第 6 段「選一個合理起點:steel thread」

見仁見智 8:35
「maybe you start with offset-based pagination for search results」
作為「先簡單再說」的示範沒問題,但把 offset 分頁說成搜尋結果的安全起點稍嫌樂觀。搜尋結果只要底層資料會變動(新內容持續索引、或依即時分數排序),翻頁時就會出現漏看與重複;資料量大時 OFFSET 也需掃過前面所有列,深頁會明顯變慢。實務上不少搜尋系統即使有頁碼介面,底層仍用 search_after 或游標實作。作者本人在第 3 段其實已經給出了正確判準(資料變動頻率),只是這裡沒把它套用回來。
依據: Elasticsearch 官方文件對 from/size 深度分頁設有 index.max_result_window 上限(預設 10000),並建議改用 search_after
留給下一段 留下一個沒被說完的部分:選了一個刻意簡單的起點,你要怎麼讓對方相信這是判斷而不是能力不足?下一步必須處理如何把這個選擇講出來。

7. 把取捨講清楚 9:04–10:06

第三步是清楚說明取捨,這是強回答的核心。你不必假裝自己的選擇完美,通常不假裝更好。可以說:這是我會開始的方案、為什麼它符合目前需求、我接受哪些取捨、什麼情況下我會回頭重新檢視這個決定。這比列出五個方案然後等面試官告訴你哪個對強得多,因為你聽起來像個能做決定的人。資深工程師在真實專案裡也是這樣:拿不到完整資訊,就釐清狀況、選方向、溝通取捨、有新資訊再調整。

承上 承上:上一段選了一個刻意簡單的起點,留下「怎麼讓對方相信這是判斷而不是能力不足」的問題。第三步就是回答這件事。

推理因為選了簡單起點會有被當成資淺的風險,作者接著說第三步——清楚解釋取捨,並稱這是強回答的核心。他給的關鍵鬆綁是:你不需要假裝自己的選擇是完美的,事實上不假裝通常更好。他甚至把句型直接寫出來:這是我會開始的方案、我認為它為什麼符合目前的需求、我接受哪些取捨、以及我在什麼情況下會回頭重新檢視這個設計。作者比較這個回答與另一種——列出五個可能方案然後等面試官告訴你哪個對——並說前者強得多,因為你聽起來像個能做決定的人。他在這裡把面試接回真實工作:那正是資深工程師在真實專案裡需要做的事,他們也拿不到完整資訊,必須釐清狀況、選一個方向、溝通取捨、在新資訊出現時調整。

AI 補充值得指出作者那個句型的第四句「什麼情況下我會回頭重新檢視」為什麼特別關鍵:它把一個決定變成有觸發條件的決定,於是「我可能選錯」不再是弱點,而是已經被納入計畫的一部分。這正好解掉第 2 段那個分析癱瘓——你之所以不敢選,是因為把決定當成不可撤回的;一旦附上撤回條件,決定的心理成本就大幅下降。實務上這也是決策紀錄(ADR)在做的事:寫下當時的情境、選了什麼、放棄了什麼、以及什麼會讓我們改變主意。另外可以補一個判準幫你判斷該花多少時間在一個決定上:這個決定是可逆的(換分頁策略、換狀態管理函式庫)還是幾乎不可逆的(資料模型、跨團隊 API 契約)?可逆的就快速選、先做再說;不可逆的才值得慢下來仔細比較。作者說的「先選一個合理起點」隱含的正是——大部分前端架構決定其實是可逆的。

術語:Architecture Decision Recordtwo-way door decision

Architecture Decision Record

架構決策紀錄(ADR)

一份簡短文件,記下一個架構決定的當時情境、選了什麼方案、放棄了什麼、以及預期的後果。

格式通常只有幾段:背景、決定、考慮過的替代方案、後果。它的價值在半年後——人們往往記得結論卻忘了理由,於是要嘛不敢動它,要嘛推翻後重踩同一個坑。作者建議的那個回答句型(這是我的選擇、為什麼、我接受什麼取捨、何時重新檢視)幾乎就是一份口說版 ADR,這也是為什麼它在面試裡聽起來很資深。

相關術語: trade-off (記錄對象)

出處:第 7 段「把取捨講清楚」

two-way door decision

雙向門決定

可以低成本回頭撤銷的決定;相對於一旦通過就很難回頭的「單向門」決定。

這個分類法的用處是決定你該花多少時間思考:雙向門就快速決定、邊做邊學,因為錯了改回來很便宜;單向門(資料模型、對外 API 契約、跨團隊依賴)才值得投入大量分析。系統設計面試裡的多數選擇——分頁策略、狀態管理方式、要不要快取——其實都是雙向門,這正是「先選一個合理起點」之所以安全的原因。

相關術語: analysis paralysis (解藥)、Architecture Decision Record (常記錄於)

出處:第 7 段「把取捨講清楚」

留給下一段 留下最後一個要收束的問題:既然這三步就是資深工程師的日常,那系統設計面試這種看起來人工的形式,究竟在測什麼、又為什麼值得?

8. 總結:把模式用在情境裡 10:06–11:07

所以前端系統設計面試即使有點人工,仍然有用:好的題目測的不是你知不知道某個模式,而是你能不能在情境中套用它。分頁不只是 offset 對 cursor,而是產品體驗與使用者如何在資料中移動;即時協作不只是 WebSocket 或 CRDT,而是互動模式、衝突模型,以及這個產品真正需要多少複雜度。最後作者宣傳頻道與他的前端系統設計課程。

承上 承上:上一段留下的問題是——既然這三步就是資深工程師的日常,那系統設計面試在測什麼、為什麼值得。這一段回答並收束全片。

推理因為前三步已經完整交代了做法,作者最後回頭替面試這個形式辯護:即使它有時候感覺很人工,仍然有用,因為好的題目測的不是你知不知道某個模式,而是你能不能在情境中套用它。他用兩個例子各回收一次來證明:分頁不只是 offset 對 cursor,而是關於產品體驗、以及使用者如何在資料中移動;即時協作不只是 WebSocket 或 CRDT,而是關於互動模式、衝突模型、以及這個產品實際上需要多少複雜度。最後他說明頻道之後會持續做前端系統設計、真實架構、以及如何像資深工程師那樣解釋決策的內容,並介紹他的前端系統設計課程。

AI 補充把整支影片倒過來看會發現它其實只講了一件事的兩面:「答案取決於情境」是診斷,「Clarify → Choose → Explain」是處方,而兩個例子是連接兩者的證據。真正可以帶走的,是那個把技術名詞翻譯成產品問題的習慣——遇到 offset 對 cursor,先問「資料會不會在使用者瀏覽期間變動、他需不需要回到特定位置」;遇到 WebSocket 對輪詢,先問「使用者能容忍多久的延遲」;遇到 CRDT 對後寫覆蓋,先問「兩個人多常撞到同一個東西、撞到的代價多大」。這些問題不需要記憶任何架構,卻能推出架構。最後值得補一句作者只暗示而沒有說破的話:這套方法之所以在面試裡有效,正是因為它在真實工作裡有效——面試官想確認的其實是明天把你放進專案,你會不會在資訊不足時把事情推動起來。

留給下一段 總結收束。

4. 總結

這支影片的推理鏈是一條直線:先指出卡住的原因不是知識不足,而是看得見太多合理選項卻不敢選(分析癱瘓);接著用真實工程的限制(既有程式碼、團隊、技術棧、導入成本)證明「脫離情境的最佳解」根本不存在,於是「找正確答案」這個問題設定本身就是錯的。為了讓這句話不只是漂亮話,作者做了兩個結構相同的對照實驗——分頁題(搜尋結果要位置感,適合頁碼分頁;動態牆持續長出新內容,適合游標分頁與無限捲動)與即時協作題(白板高頻細粒度、衝突處理吃重;看板互動離散、後寫覆蓋往往就夠)。兩題都證明:同一個技術問題,因產品體驗與使用者行為不同,答案會翻轉。證明完成後,他把「依情境決定」轉成三個可執行動作:Clarify(先問使用者體驗、規模/一致性/交付速度、真正的限制)、Choose(用 steel thread 拉出最薄的端到端方案,等需求推你才加複雜度)、Explain(說出這是起點、為什麼合理、我接受哪些取捨、什麼情況會回頭重看)。最後收束回面試的意義:好題目測的不是你認不認得某個模式,而是能不能在情境中套用它——而這正是資深工程師在真實專案裡每天做的事。

勘誤總整理

確定錯誤/已過時見仁見智(取決於版本或情境)

段落原話(transcript 逐字)說明
6. 選一個合理起點:steel thread
8:35
「maybe you start with offset-based pagination for search results」作為「先簡單再說」的示範沒問題,但把 offset 分頁說成搜尋結果的安全起點稍嫌樂觀。搜尋結果只要底層資料會變動(新內容持續索引、或依即時分數排序),翻頁時就會出現漏看與重複;資料量大時 OFFSET 也需掃過前面所有列,深頁會明顯變慢。實務上不少搜尋系統即使有頁碼介面,底層仍用 search_after 或游標實作。作者本人在第 3 段其實已經給出了正確判準(資料變動頻率),只是這裡沒把它套用回來。
依據: Elasticsearch 官方文件對 from/size 深度分頁設有 index.max_result_window 上限(預設 10000),並建議改用 search_after

5. 推薦三個下一步

1. 往下挖深:把即時協作的衝突模型真正搞懂

影片點名了 CRDT 與 operational transformation 卻刻意沒展開,只說「取決於產品」。要判斷什麼時候真的需要它們,得先知道兩者各自怎麼運作、代價落在哪裡。

YouTube 搜尋:CRDT explained conflict-free replicated data types operational transformation vs CRDT how Figma multiplayer works building a collaborative whiteboard architecture

2. 往旁邊對照:看一場完整的前端系統設計模擬面試

這支影片給的是思考框架,但沒有示範一場從釐清到收尾的完整答題節奏——時間怎麼分配、白板怎麼畫、面試官追問時怎麼調整設計。

YouTube 搜尋:frontend system design mock interview design a news feed frontend system design frontend system design interview walkthrough

3. 往上應用:把取捨敘事變成書面的架構決策紀錄

影片說的那個回答句型(這是起點、為什麼、接受什麼取捨、何時重看)其實就是口說版的 ADR。把它變成團隊裡的書面習慣,才是這套思考在真實專案裡發揮作用的地方。

YouTube 搜尋:architecture decision records ADR tutorial documenting architecture decisions Michael Nygard RFC process engineering team

📄 全部影片 · 主題區: 前端底層與系統設計