兩位開發者使用同一個AI工具。一位在30秒內得到可執行的程式碼。另一位得到一團亂碼,花了一個小時才修好它.
差異不在工具。而在提示.
為何大多數AI產生的程式碼都很糟糕
AI 編碼工具是具有巨大上下文窗口的模式匹配器。給它們一個清晰的模式,它們就能出色地完成它。給它們模糊性,它們就會創造假設——通常都是錯誤的假設.
常見的錯誤:
- 過於模糊:"為我的應用程式添加認證"——AI 不了解你的技術堆栈、你的數據庫模式,或你的慣例
- 過於龐大: "為我建立一個 SaaS 仪表板" — AI 為你發明了一個你沒有要求的架構,而你花了一個小時來解開它
- 沒有上下文: "修復這個錯誤" 而沒有周圍的程式碼 — AI 猜測系統
- 要求做決策: 使用 AI 來做產品或架構選擇,而不是執行你已經做出的決定
修復並非另一個 AI 工具。它是寫入提示的不同方式.
框架:背景資訊 → 限制條件 → 任務
每個有效的程式碼提示都有三個部分.
[CONTEXT] Given this [file/system/function],
[CONSTRAINT] following these [conventions/rules],
[TASK] do [specific, scoped thing].
不良提示:
"添加一個刪除按鈕"
良好提示:
"在
src/components/ProjectCard.tsx,新增一個刪除按鈕,該按鈕呼叫deleteProjectServer Action來自src/actions/projects.ts。點擊後,使用shadcn/ui現有的AlertDialog顯示確認對話框。刪除後,呼叫revalidatePath('/dashboard')。遵循現有的錯誤處理模式:捕捉錯誤並使用sonner顯示吐司,不要拋出。"
同樣請求。第二個需要額外40秒來寫入。輸出是可以直接生產使用的,而不是需要花一個小時來清理的起點。
設計提示的6種類型
1. 實現提示
用於建立新功能。最常見的——也是最容易出錯的。
範本:
Add [feature] to [file/component].
It should [behavior description].
Use [specific library/pattern] — not [what to avoid].
Follow the existing pattern in [example file or function].
The return/export should look like: [description].
範例:
Add pagination to `getUserProjects` in `src/lib/queries.ts`.
It should accept `{ page: number, limit: number }` and return
`{ data, total, hasMore }`.
Use Drizzle's `.offset()` and `.limit()` — not cursor-based pagination.
Follow the same select pattern as `getUserById`: select specific
columns, never `select *`.
Type the return with a `PaginatedResult<T>` generic.
2. 缺點修復提示
用於偵錯。錯誤在於沒有提供足夠的上下文來說明預期行為與實際行為的差異。
範本:
[function/component] in [file] is broken.
Expected: [what should happen]
Actual: [what is happening]
Error: [exact error message if any]
Relevant context: [the failing code + what it calls]
範例:
The `createProject` Server Action in `src/actions/projects.ts`
returns { error: "Unauthorized" } even when the user is logged in.
Expected: creates the project and returns { data: project }.
Actual: always hits the requireAuth() error branch.
Error: no error message, just the unauthorized return.
requireAuth() is in `src/lib/auth.ts` — pasting it below.
The user is definitely authenticated (visible in Clerk dashboard).
3. 改寫提示
為了在不破壞現有程式碼的情況下進行改進。關鍵限制:指定必須保持不變的內容.
範本:
Refactor [function/file] to [improvement goal].
Keep: [API, behavior, types that must stay identical]
Change: [what should change]
Don't: [specific things to avoid]
範例:
Refactor `UserTable.tsx` to extract the row actions into a
separate `UserTableActions` component.
Keep: the exact same props API on UserTable, same visual output,
same TypeScript types.
Change: move the action buttons and their handlers to
`UserTableActions.tsx`.
Don't: change how the parent passes data, don't add new dependencies.
4. 測試寫入提示
用於生成測試。明確說明函式庫、要涵蓋的內容,以及要模擬的部分.
範本:
Write [unit/integration] tests for [function/component] in [file].
Testing library: [Vitest/Playwright/etc.]
Cover: [list of specific scenarios]
Mock: [external dependencies to mock and why]
Don't test: [implementation details to avoid]
範例:
Write Vitest unit tests for the `createProject` Server Action
in `src/actions/projects.ts`.
Cover:
- success case (user authorized, valid input)
- validation failure (name exceeds 50 chars)
- unauthorized user (requireAuth throws)
- database error (insert fails)
Mock: `src/lib/db.ts` (mock insert to return a fake project),
`src/lib/auth.ts` (mock requireAuth).
Don't test the actual database or actual auth — only the action's logic.
5. 解釋提示
為了理解不熟悉的程式碼。錯誤:要求一個概括性的解釋.
不好:
"解釋這段程式碼"
好:
"解釋這個 Drizzle 查詢做了什麼。具體:
.$onConflictDoUpdate做什麼,以及為什麼是"target: [users.clerkId]是否需要?請給我一句總結整體對資料庫的影響的摘要。"
針對性問題獲得針對性答案。""解釋這段程式碼"會得到一牆文字,涵蓋了你已經知道的事實。
6. 迁移和升級提示
用於更新程式碼到新的 API 版本。
範本:
Migrate [file] from [old API] to [new API].
Breaking changes to handle: [list specific breaking changes]
Don't change: [function signatures your app uses]
Reference: [paste the relevant migration docs]
範例:
Migrate `src/lib/auth.ts` from Clerk v4 to Clerk v5.
Breaking changes: `auth()` is now async, `clerkMiddleware` replaces
`withClerkMiddleware`, user object shape changed.
Don't change the signatures my app uses: requireAuth() and getAuthUser().
Here are the relevant Clerk v5 migration notes:
[paste the breaking changes section from the docs]
背景是乘數
輸出品質的最大因素是背景。AI 工具只能使用你給它們的內容。
應該始終包含的內容
- 確切的檔案路徑
- 特定的函數或組件名稱 — 不是整個檔案
- 遵循此模式的現有範例
- 使用的函式庫 — 不要假設它知道你的堆疊
- "完成"的樣子(回傳類型、視覺輸出、行為)
不應包含的內容
- 整個程式碼庫(「這是我的整個專案」)
- 不相關的檔案(「這裡是
/lib裡的所有內容」) - 跨越多個系統的規格
最佳情境就是足夠消除歧義的最小需求
提示 (Claude Code): 使用 Claude Code,你不需要將程式碼貼到提示中。只需參照檔案路徑——"in
src/actions/projects.ts" 就夠了,Claude Code 會自動讀取它。將貼上保留給你想強調的特定片段。
CLAUDE.md: 永續性上下文,免費使用
撰寫良好提示的問題在於每次都重複您的慣例: "使用 cuid2 作為 ID,使用 Server Actions 而不是 API 路徑,返回 { data } 或 { error }..."
使用 Claude Code,您在根目錄的 CLAUDE.md 檔案中只寫一次:
# CLAUDE.md
## Stack
- Next.js 15 App Router, TypeScript strict mode
- Drizzle ORM + Neon (PostgreSQL)
- Clerk auth, Zod validation, shadcn/ui
- Biome for linting and formatting
## Conventions
- cuid2 for all IDs, never auto-increment integers
- Soft-delete users (deletedAt), never hard delete
- Server Actions for mutations, not API routes
- Import env from `@/lib/env`, never `process.env` directly
- `requireAuth()` at the top of every protected action
- Return `{ data }` or `{ error: string }`, never throw from actions
- Error messages lowercase, no periods
## File structure
- Server Actions: `src/actions/[feature].ts`
- DB queries: `src/lib/queries.ts`
- Shared types: `src/types/[domain].ts`
Claude Code 在啟動時讀取此內容,並自動將這些規則套用至每個提示。你再也不必說 "使用 cuid2" — 它會自動執行.
任務分解:真正的資深開發者技能
區分能取得優異成果的開發者與感到沮喪的開發者的單一技能:將任務分解至適當的規模.
不要:
"為我建立用戶認證,包含註冊、登入、社交認證、Google OAuth、密碼重設、電子郵件驗證、會話管理以及賬戶設置頁面。"
要:
- "在 Next.js 15 App Router 中設定 Clerk" → 已完成
- "在
requireAuth()中建立src/lib/auth.ts助手" → 已完成 - "將 Clerk 中介軟體添加到保護
/dashboard路徑" → 已完成 - "在
(dashboard)/settings/page.tsx建立帳戶設定頁面" → 完成
每個步驟都是一個30秒的提示,並有清晰、可驗證的輸出。結合的結果與大請求相同——但沒有任何虛構的架構,而且你理解每一行
規則:如果一個提示需要超過5分鐘讓人完全規劃出來,那麼就分成兩個提示。
你永遠不應該問AI的問題
架構決策:
"我應該使用微服務還是單體架構?"
AI會根據通用模式給你一個聽起來合理的答案。它不知道你的團隊規模、你的流量、你的發展空間。先自己做出決定,然後再請AI執行你的決策。
商業邏輯:
"當使用者取消其訂閱時,應該發生什麼?"
這是一個涉及收入的產品決策。請自行定義它,然後實施它.
安全性審計:
"這段程式碼安全嗎?"
AI可以在您要求時寫出安全的程式碼。它不會自發地發現現有程式碼中的每個漏洞。使用專用的工具進行審計。
任何你不去閱讀的內容:
如果你打算不閱讀就複製 AI 的輸出,請停止。你正在發布你不懂的程式碼。當它出現問題時——而且它一定會——你將不知道該從哪裡找原因。
之前 / 之後:真實案例
功能實現
之前(寫作 30 秒,修復 45 分鐘):
"在專案列表中添加搜尋功能"
之後(寫入需時 90 秒,首次運作成功):
"為
src/app/(dashboard)/projects/page.tsx添加搜尋功能。它應該使用 URL 搜尋參數 (?q=),以便搜尋狀態在頁面刷新時得以保持。從getUserProjects中篩選結果,其中name包含查詢內容(不區分大小寫)。使用防抖輸入——使用useDebounce從src/hooks/useDebounce.ts進行 300 毫秒的防抖處理。不要添加任何新的依賴項。"
修復錯誤
之前:
"我的表單無法提交"
之後:
"當提交時,
CreateProjectForm在src/components/CreateProjectForm.tsx中沒有呼叫伺服器動作。React Hook Form 的handleSubmit已經連接,但動作 (createProject来自)src/actions/projects.ts)從未觸發 — 在動作最上方的console.log中確認。沒有瀏覽器錯誤。下方貼上兩個檔案。"
重構
之前:
"整理這個檔案"
之後:
"這個
src/lib/db.ts檔案有三個內聯輔助函數 (withRetry,paginate,softDelete正被用於 6+ 處。將它們提取到src/lib/db-helpers.ts並更新所有匯入。不要改變函數簽名或行為 — 只改變位置。"
元技能
讓你變得更好於提示的最佳方法是在你得到壞結果時注意到並問為何.
- 輸出太模糊 → 你的任務不夠具體
- AI發明了建築→任務太大,將其拆分
- AI使用了錯誤的模式→缺少上下文,添加相關檔案
- AI做出了產品決策→你要求的是決策而不是實現
- 程式碼與你的技術堆疊不符→你的規範不在
CLAUDE.md
每個錯誤輸出都是對提示的回饋。修復提示,而不只是修復輸出。
使用 AI 工具獲得 10 倍效率的開發者並沒有使用不同的等級或不同的模型。他們在寫一個更好的提示上多花了 60 秒鐘。那就是全部的優勢——而且它每天都在累積。
包含 CLAUDE.md 模板和 Claude Code 工作流程的完整指南:
https://stacknotice.com/blog/ai-coding-prompts-senior-2026












