PRINCIPLE 1 / 4

編碼前思考

Think Before Coding
在動手之前先想清楚——不要默默假設,把困惑攤在桌上。
核心句:不要假設。不要隱藏困惑。呈現權衡取捨。

不要假設。不要隱藏困惑。呈現權衡取捨。

在實作之前:

檢驗標準:對不清楚的需求:先停下來、列舉多種解讀、提出疑問,再動手。
教學解說:為什麼 LLM 需要「先想清楚」?

LLM 的核心特性是傾向「完成任務」而非「釐清任務」。當你說「加入匯出功能」,模型會默默假設格式、欄位、範圍,然後直接寫出完整實作。這些假設往往是錯的,但模型不會主動告诉你。

這個原則的核心是把 LLM 從「執行者」變成「協作者」——在動手之前先跟你確認假設。這就像資深工程師收到需求後,不會馬上寫程式碼,而是先問清楚再動手。

關鍵心態:把「困惑」當作正常的開發狀態,而不是失敗。停下來問問題比默默做錯更專業。

Worked Example:匯出使用者資料
對應範例 1-1 — AI 直接假設 vs. 先釐清假設
AI 編碼前(❌ 常見錯誤模式)
def export_users(format='json'):
    """Export all users to a file."""
    users = User.query.all()
    # 直接假設:所有欄位、本地檔案、JSON/CSV 格式
    # 沒問過:範圍?隱私?欄位?資料量?
AI 編碼後(✅ 運用原則後)
在實作之前,我需要釐清:
1. **範圍**:匯出所有還是篩選後的子集?(隱私考量)
2. **格式**:瀏覽器下載?背景任務?API 端點?
3. **欄位**:哪些欄位?(可能涉及敏感資訊)
4. **資料量**:通常多少使用者?(影響做法)
最簡單的做法:回傳分頁 JSON 的 API 端點。
關鍵差異
  • 之前:假設了 4 個以上條件,沒有一個問過使用者
  • 之後:列出所有假設,把選擇權交還使用者
  • 核心改變:從「默默執行」變成「先確認再動手」
常見錯誤:AI 的隱藏假設模式
  • 欄位假設:不問就假設使用者要哪些欄位(尤其敏感欄位如 email、phone)
  • 範圍假設:不問就假設「全部」或「篩選」,沒考慮分頁與效能
  • 實作方式假設:不問就決定用檔案下載、API、還是背景任務
  • 資料結構假設:不確認資料庫 schema 就假設欄位名稱與型別
  • 隱藏困惑:遇到歧義時默默選一種解釋,而不是提出來討論
練習 / 檢核清單
  • 收到需求後:先停下來,列出所有你假設的條件
  • 假設清單:範圍?格式?欄位?實作方式?資料量?
  • 歧義檢測:這句話有沒有兩種以上解讀?
  • 簡單做法:有沒有更簡單的實作方式?提出來討論
  • 困惑時:明確指出「我不確定 X 是什麼意思」
  • 反向檢驗:如果你是使用者,你會滿意這個假設嗎?

對應範例

到互動範例頁看這個原則的 ❌/✅ 對照:

進階單元 · Round 1 Deepening
進階 Worked Example:大型重構 — 把訂單模組拆成獨立微服務
需求只有一句:「把訂單模組拆成獨立的服務,請開始做。」——這裡的每個決策都在考驗原則 1。
❌ 常見的 AI 直覺(默默拆下去)
「好的,我開始把訂單模組拆成微服務:」

1. 建立 orders-service/ 目錄(預設用 Go)
2. 把訂單相關的 model 複製過去(預設:直接複製)
3. 加入 REST API(預設:GET/POST /orders)
4. 設定 Dockerfile 與 CI(預設:與現有 CI 同格式)
5. 把 monolith 的 route 指向新服務(預設:直接切換)

—— 沒有一個預設問過使用者,五個預設只要錯一個就白做。
✅ 運用四原則的決策過程
「拆微服務」在動手前必須先回答四個問題,否則拆完也不知道拆對沒有:

1. 邊界:訂單模組的邊界到哪?出貨、庫存、發票算不算訂單?
   → 提出問題,不是默默選「只要 order table」。
2. 資料:訂單資料仍然共用同一個資料庫嗎?
   → 這是「拆分成本」的核心權衡,必須讓使用者決定。
3. 通訊:同步 REST 還是異步 event?
   → 影響一致性模型;先確認哪個符合業務,再談技術。
4. 成功標準:「拆完」如何衡量?哪個指標算達成?
   → 原則 4 的輸入在這裡就要問清楚。

我的提案(呈現權衡,讓使用者選):
- 最保守路徑:先拆「讀取」路徑,寫入路徑後置 → 回滾容易
- 最快速路徑:整體搬移 → 一次到位但回滾困難
- 我建議保守路徑,除非你告訴我必須在一週內上線。
為什麼選這條路徑
  • 因為「拆分」是不可逆的高成本決策:拆錯邊界的成本是數週的返工,一次提問換一次正確的開始,報酬率最高。
  • 因為假設有階層:邊界與成功標準是「第一階假設」,錯了後面全錯;Dockerfile 格式是「第三階假設」,錯了只影響一行。先問最貴的。
  • 因為四原則彼此餵養:現在問清楚(原則 1)→ 讓實作簡潔(原則 2)→ 讓 diff 精準(原則 3)→ 讓每一步可驗證(原則 4)。一步都不省的。
深入原理:LLM 為什麼傾向「執行」而不是「釐清」?

LLM 的本質是next-token prediction——它被訓練成「接續一段文字」。當你丟出「把訂單模組拆成服務」,模型最「順」的接續方式是把程式碼寫完:完成一個任務會產生一個完整的、令人滿意的輸出,而提問會中斷這個接續迴圈。這是訓練資料的統計事實:程式碼範例幾乎都是「需求 → 完整實作」,很少是「需求 → 反問十個問題」。

Token 經濟的推力:釐清需要多輪往返,每輪都消耗 token;RLHF(人類回饋強化學習)在評分時傾向獎勵「一次給出完整答案」的模型,因為那看起來更「有用」。於是「先問清楚再動手」對模型來說是反直覺的、成本更高的行為——你必須把「停下來問」變成明確指令,它才會做。

上下文崩潰(context collapse):在長對話中,模型對早期需求的記憶會淡化(研究稱之為 lost-in-the-middle:模型對上下文中間的內容記得最差)。當它遺忘初始需求,最省力的做法是重新詮釋需求來讓工作繼續——這正是「默默地越做越偏」的底層原因。對策:把關鍵需求寫在專案檔頂端、或每幾個步驟重述一次。

案例:大家以為遵守原則,其實違反了

Agent 收到需求後,輸出:「我需要釐清:① 格式?② 欄位?③ 範圍?」——看起來完美遵守原則 1。但同一則訊息的最後卻附上了 export_users(format='csv') 的完整實作,欄位與範圍都預設好了。問問題與實作並存,等於沒有問:模型把「釐清」當作聊天語氣,而不是控制流程的閘門。真正的遵守是「停在此處,等使用者確認才動手」——問題列表是煞車,不是裝飾。

診斷式疑難排解:原則 1 常見故障
症狀可能原因解決方案
AI 直接開始寫程式碼,完全沒列假設模型把需求視為明確指令,自動補齊預設明確要求「先列出所有假設,再開始」,把這句話寫進指令開頭
列了假設,但同則訊息就附上實作假設清單淪為形式,流程沒有真的停下要求「停在此處,等我確認」,並把實作移出該訊息
問的問題答案它其實都知道「假問題」填充——模型在表演合作,不是真在收集資訊追問「這些問題的答案會改變你的做法嗎?」把沒有資訊量的問題刪掉
列出的選項不完整或刻意傾斜模型傾向引導到它擅長或最省力的路徑要求「列出所有可行解與各自的權衡」,再讓使用者選
長對話後需求被「重新詮釋」上下文崩潰,模型遺忘初始需求把關鍵需求固定寫在檔頭/重複聲明,作為不可漂移的錨點
進階挑戰題
  1. 假設盤點:需求是「把登入改成 OAuth 2.0」。列出你認為模型會默默假設的 5 個條件,並為每一個寫出一句「必須問使用者」的問題。
    提示:範圍、資料、流程、相容性、回滾——想想哪些假設錯了成本最高。
  2. 問題排序:PM 說「讓 app 更快」。寫出你要問的前三個問題,並說明為什麼這三個優先於其他所有問題。
    提示:先區分「哪種快」再談「怎麼快」——回應時間、吞吐量、感知速度是完全不同的問題。
  3. 陷阱題:你問「要 JSON 還是 CSV?」使用者回「JSON」,但其實他根本不在乎、也搞不清楚差異。這算遵守原則 1 嗎?說明你的判斷。
    提示:問題有沒有幫使用者做決策?如果問題只是把技術負擔丟回去,那就是「假釐清」。
進階單元 · Round 2 Deepening
專案級端到端 Worked Example:從零開發「付款結帳」模組
需求:「我們需要一個付款結帳功能,使用者可以選商品、填地址、刷卡付款。」——跨四原則的完整開發流程。
階段 1 → 原則 1(編碼前思考):釐清所有假設
收到需求後,先列假設清單:

1. **付款閘道**:Stripe?信用卡直接收?還是要支援第三方支付?
   → 成本與合規要求完全不同。
2. **幣別**:單一幣別?多幣別需要匯率轉換?
3. **地址**:帳單地址 vs. 寄送地址?是否需要地址驗證?
4. **訂單暫存**:使用者中途離開怎麼辦?購物車要不要持久化?
5. **安全性**:PCI DSS 合規?卡號能進我們的資料庫嗎?

→ 先停在這裡,把這 5 個問題與權衡列給使用者確認。
確認:用 Stripe Checkout(PCI 合規由 Stripe 處理)、單一幣別、
帳單地址、購物車存 Redis。
階段 2 → 原則 2(簡潔優先):最小可運作版本
第一版只做:選商品 → 填地址 → 送 Stripe Checkout → 回調確認。

先不做:購物車持久化(使用者說不急)、多幣別、優惠券、發票。

# 最小實作 ≈ 80 行
@app.route('/checkout', methods=['POST'])
def checkout():
    items = request.json['items']          # 原則 1 確認過的欄位
    session = stripe.checkout.Session.create(
        payment_method_types=['card'],
        line_items=[{'price': item['price_id'], 'quantity': item['qty']}
                    for item in items],
        mode='payment',
        success_url=url_for('success', _external=True),
        cancel_url=url_for('cancel', _external=True),
    )
    return redirect(session.url)

# 沒有 Strategy 模式、沒有抽象類別、沒有配置物件。
# 三個月後要加第二種付款方式時,再提重構。
階段 3 → 原則 3(精準修改):只動結帳相關檔案
新增的檔案:checkout.py, templates/checkout.html
修改的檔案:app.py(加一行 route 掛載)

刻意沒動的:
- app.py 裡的既有 routes — 格式不一致?不關我的事。
- templates/layout.html 的 CSS — 看到變數名不夠好?不改。
- utils.py 裡「看起來沒用」的舊函式 — 不刪。
階段 4 → 原則 4(目標驅動執行):逐步驗證
計畫與驗證:
1. 建立 Stripe 測試帳號 → 驗證:能用測試卡完成一筆 $1 付款
2. 實作 /checkout 路由 → 驗證:POST 請求回傳 Stripe Checkout URL
3. 實作 /success 回調 → 驗證:付款後跳轉到成功頁、訂單記錄建立
4. 手動端到端測試 → 驗證:選商品 → 填地址 → 刷卡 → 成功頁 → DB 有紀錄
5. 既有測試 → 驗證:全部仍然全綠

「完成」的定義:端到端手動測試通過 + 既有測試無回歸。
四原則如何串成一條鏈
  • 原則 1 省下的成本:如果直接動手,Stripe 帳號設定、PCI 合規、幣別——每一項錯了都是數天返工。
  • 原則 2 省下的時間:80 行 vs. 可能 500+ 行的「完整付款系統」。三个月後的需求是三个月後的事。
  • 原則 3 保護的審計性:付款模組是合規高風險區域——diff 裡每行都要能追溯到需求,審計時才能快速確認「沒動到不該動的」。
  • 原則 4 提供的確定性:每一步都有可執行的驗證——不是「看起來能用」,而是「測試證明能用」。
效能 × 品質 × 安全深度:假設管理在三面向的實務影響

效能:未釐清的假設直接轉化為效能問題。例如假設「匯出所有資料」而未確認範圍——資料量從 100 筆到 100 萬筆時,同一個實作從 0.1 秒變成 30 秒甚至 OOM。假設「同步處理」而未確認是否可用非同步——一個慢查詢阻塞整條 API。原則 1 的價值不只是「問對問題」,而是在效能問題被寫入程式碼之前攔截它。

品質:假設錯誤導致的品質問題通常在 code review 後才被發現——但那時修正成本已經升高。例如假設了 CSV 欄位順序與前端不一致,導致前端解析崩潰;假設了 API 回傳格式但下游消費者期待不同結構。品質的核心不是「寫對的程式碼」,而是「在動手之前確認什麼是對的」。

安全:安全假設是最致命的一類。例如假設「token 永遠有效」而未確認過期策略;假設「輸入已經被前端驗證過」而跳過後端校驗;假設「內部 API 不需要認證」——每一個都是 OWASP Top 10 的常見入口。原則 1 在安全場景的關鍵是:把「我假設它是安全的」變成「我確認它的安全機制是什麼」。

效能案例:假設「全表掃描沒問題」

Agent 收到「列出所有訂單」的需求,直接寫了 Order.query.all()。初期 500 筆訂單秒回,三個月後 50 萬筆——API 超時。根本原因:Agent 假設了資料量「永遠很小」,沒有問「預期多少筆?需要分頁嗎?」。修復:加上分頁 + 索引,但那已經是三天的緊急加班。

面向原則 1 · 編碼前思考相關原則差異說明
核心動作 停下來、列假設、問問題 原則 4(目標驅動) 原則 1 是「在動手前釐清方向」;原則 4 是「釐清之後把目標變成可驗證的數字」。前者管「問什麼」,後者管「怎麼衡量完成」。
時機 編碼之前的最早階段 原則 3(精準修改) 原則 1 在「什麼都沒寫」之前攔截問題;原則 3 在「已經在改」時防止蔓延。一個是入口閘門,一個是過程中的煞車。
對抗的偏誤 Completion bias(完成偏誤)——模型想直接動手 原則 2(簡潔優先) 兩者都反對「多做」,但方向不同:原則 1 反對的是「做錯的方向」(假設錯誤),原則 2 反對的是「做多的範圍」(過度工程)。
最大價值 避免「整週返工」的高成本錯誤 原則 4(目標驅動) 原則 1 防止方向錯;原則 4 確保方向對之後能可靠地完成。兩者搭配:先問對問題,再定義什麼叫「做對了」。
Round 2 互動式檢核清單
  • 收到需求後,我能列出至少 3 個模型可能默默假設的條件
  • 我能區分「第一階假設」(錯了全盤重來)與「第三階假設」(錯了只改一行)
  • 我會在安全相關場景中,把「我假設它是安全的」轉為「我確認它的安全機制是什麼」
  • 我能辨識「假問題」——那些答案不會改變做法的問題,並把它們刪掉
  • 在長對話中,我會把關鍵需求重述到檔頭或獨立聲明,防止上下文崩潰
  • 我會用「如果你是使用者,你會滿意這個假設嗎?」來反向檢驗