反模式速查

一眼看懂四個原則各自最常見的錯誤與修正方向
速查卡適合貼在旁邊;課程頁看細節,互動範例看長相
教學解說:反模式的本質

反模式不是「明顯的錯誤」——它們看起來都很「專業」。策略模式是好東西,型別提示是好東西,docstring 也是好東西。但當它們在不該出現的時機出現,就變成了反模式。

本頁的四張速查卡,對應四個原則各自最常見的反模式。把它們貼在旁邊,每次收到 AI 輸出時快速對照。

常見錯誤:AI 的四大反模式總覽
編碼前思考
Think Before Coding · 讀課程
反模式
默默假設檔案格式、欄位、範圍
修正方式
明確列出假設,請求釐清
簡潔優先
Simplicity First · 讀課程
反模式
為單一折扣計算使用策略模式
修正方式
一個函式就夠,直到實際需要複雜度
精準修改
Surgical Changes · 讀課程
反模式
修復錯誤時順便改引號、加型別提示
修正方式
只修改修正問題所需的行
目標驅動執行
Goal-Driven Execution · 讀課程
反模式
「我會檢視並改進程式碼」
修正方式
「為錯誤 X 撰寫測試 → 讓它通過 → 驗證無回歸」
反模式總結表
原則 反模式 修正方式
編碼前思考 默默假設檔案格式、欄位、範圍 明確列出假設,請求釐清
簡潔優先 為單一折扣計算使用策略模式 一個函式就夠,直到實際需要複雜度
精準修改 修復錯誤時順便改引號、加型別提示 只修改修正問題所需的行
目標驅動 「我會檢視並改進程式碼」 「為錯誤 X 撰寫測試 → 讓它通過 → 驗證無回歸」

「過度複雜」的範例並非明顯錯誤——它們遵循了設計模式和最佳實務。問題在於時機:它們在需要之前就增加了複雜度,這會讓程式碼更難理解、引入更多錯誤、需要更長的實作時間、更難測試。

好的程式碼是簡潔解決今日問題的程式碼,而不是過早解決明日問題的程式碼。

摘自 EXAMPLES.md 核心洞察
反模式檢核清單:每次收到 AI 輸出時快速對照
Worked Example:快速反模式偵測
拿到 AI 輸出後,用 30 秒快速檢查
快速檢查流程

步驟 1:看 diff 行數 — 如果改動超過 50 行,先問「這些都是必要的嗎?」

步驟 2:看新增的 import — 有沒有沒人要求的 import?(如 from abc import ABC)

步驟 3:看新增的類別/函式 — 有沒有沒人要求的抽象?(如 Strategy Pattern)

步驟 4:看註解與 docstring — 有沒有「改進」了現有的註解?

步驟 5:看引號與空白 — 有沒有改變了現有的風格?

步驟 6:問「資深工程師會說這太複雜嗎?」

進階單元 · Round 1 Deepening
進階 Worked Example:抓一個「看起來完美」的狡猾輸出
速查卡只能抓明顯的;真正難的是那些包裝得極度專業、所有反模式都藏起來的輸出。以下是一個實戰示範。
拿到這份輸出(使用者需求:加入檔案上傳功能)
class UploadService:
    """Handles file uploads with validation, chunking,
    progress reporting, and retry with backoff."""
    def __init__(self, storage, validator=None, reporter=None):
        self.storage = storage
        self.validator = validator or DefaultValidator()
        self.reporter = reporter or NullReporter()
    def upload(self, path, chunk_size=1MB, retries=3, backoff=1.5):
        for chunk in read_chunks(path, chunk_size):
            if not self.validator.validate(chunk): raise ...
            self.reporter.progress(len(chunk))
            for attempt in range(retries):
                try: self.storage.put(chunk); break
                except: time.sleep(backoff * attempt)
        return True
用速查表六步流程拆解
步驟 1 看行數:60+ 行,含 5 個方法、3 個可注入物件
  → 對照「簡潔優先」:需求只要「把檔案存起來」。
  → 質疑點:chunking、retry、progress、validator 誰要求的?

步驟 2 看 import:有抽象類別、預設實作、backoff 邏輯
  → 對照「精準修改」:這些是「額外元件」不是「必要元件」。

步驟 3 看新增類別:UploadService + DefaultValidator + NullReporter
  → 三個抽象只有一個是被需求的。

步驟 4 看註解/docstring:完整英文 docstring
  → 語氣正確、內容工整——但「專業的形狀」≠「必要的內容」。

步驟 5 看風格:class 風格與專案其他檔案一致嗎?
  → 這份專案是 module-level function 風格——class 本身就是風格偏差。

步驟 6 資深工程師測試:他會說太複雜嗎?→ 會,100%。

最終判定:四項反模式全中(過度工程、範圍蔓延、風格偏差、
模糊需求)。但因為它「長得專業」,60% 的 review 會放行。
為什麼這份輸出特別危險
  • 它的反模式都是「隱形的」:沒有明顯 bug、命名工整、有完整錯誤處理——所有錯誤都被包裝在「專業」的外殼裡。
  • 它利用了 review 的注意力稀缺:審計 60 行的注意力只能分給「有沒有 bug」,分不出「是不是需求」。
  • 教訓:對「長得漂亮」的輸出,檢查的標準要從「有沒有 bug」升級成「每一行能不能追溯到需求」。
深入原理:反模式為什麼「看起來都那麼專業」?

這是速查頁最核心、也最反直覺的一課:反模式不是「寫得差」的程式碼,而是「寫得太好」的程式碼。策略模式是教科書級好設計、型別提示是現代最佳實務、docstring 是工程紀律——這些東西單獨出現都是加分項。問題永遠在時機與必要性,不在品質。

模型的訓練資料讓它極度擅長「複製權威的外觀」:開源專案裡,設計模式密集、註解齊全、錯誤處理完整的程式碼往往被標記為高品質(因為 review 過、被 merge 了)。模型學到的是「長成這樣 = 高品質」,於是它在高風險、高要求的需求上,會優先複製這種形狀——不是因為需求需要,而是因為訓練資料獎勵它。

自我強化的迴圈:過度設計的程式碼因為「看起來穩健」而更容易通過 review → 更多「看起來穩健」的程式碼被 merge → 模型下次更確信「這是對的」。這就是為什麼速查表的存在很重要:它是唯一能打破這個迴圈的、來自需求側的檢查。

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

開發者(或模型)宣稱「我遵守了簡潔優先:只寫了被要求的兩個函式」。但仔細看——這兩個函式各自接收一個 options dict,裡面有 6 個從未使用的鍵;還有一個 module 層級的 DEFAULT_OPTIONS 常數。表面上沒有「多餘的 class」,但「多餘的參數化」就是被縮小尺寸的過度工程。反模式的關鍵不是形式(class 或 dict),而是猜測性內容的總量——它只是換了一個比較不顯眼的外殼。

診斷式疑難排解:反模式偵測失敗的症狀
症狀可能原因解決方案
review 只檢查「有沒有 bug」,忽略「是不是需求」注意力稀缺,專業外殼誘導審計方向把審計第一題改成「每一行能否追溯到需求?」
「看起來穩定」的輸出被快速放行以「外觀品質」取代「需求匹配」作為通過標準用速查表六步流程,而非整體印象做判斷
團隊對「何謂過度設計」沒有共識缺少共享的簡潔定義訂一個可操作的標準:資深工程師 30 秒內講得出每個物件的用途
反模式換成小包裝(options dict、預設參數)就躲過檢查速查表只看「形式」不看「猜測性內容的總量」檢查改為:數一下「未被需求的決策」有幾個,而不是數 class 有幾個
幾次放行後,團隊對反模式的警覺降低基準偏移——看慣了過度設計,見怪不怪每週挑一份合規的最小 diff 當基準,重新校準眼力
進階挑戰題
  1. 換殼偵測:設計一個「反模式的小包裝」,讓它躲過只看 class 數量的檢查,然後寫出你用來抓它的檢查問題。
    提示:想想 options dict、裝飾器、設定檔、template method——哪種外殼最容易藏猜測性內容?
  2. 校準基準:拿你最近一份真實的 PR,用「每行可追溯」的標準檢查。寫出你找到的 2-3 個「當時覺得合理、現在覺得是反模式」的地方。
    提示:重點不是自責,是找出「當時是什麼因素騙過了你」——是時間壓力?外觀專業?還是基準偏移?
  3. 把速查卡升級成「反模式偵測器」:設計一套能自動標記可疑輸出的規則(例如:新增 class 數 > 需求關鍵字數、docstring 長度 > 函式體長度、參數數 > 3 且全帶預設值)。列出你的 5 條規則。
    提示:這是可以在 CI 或 code review 外掛上實現的檢查——想想哪一條最容易被自動化。