使用 Claude Code 進行開發不僅僅是「問 AI 寫程式碼」那麼簡單。真正高效的開發需要建立系統化的工作流程,從需求分析到部署上線,每個階段都有最佳實踐。本文將深入探討如何在軟體開發生命週期的各個階段充分發揮 Claude Code 的潛力。
🎯 為什麼需要標準化工作流程?
無流程 vs 有流程的對比
❌ 無流程開發(混亂模式):
使用者: "幫我寫個登入功能"
Claude: [寫了一些程式碼]
使用者: "欸不對,我要用 OAuth"
Claude: [重寫]
使用者: "忘了說,還要雙因素驗證"
Claude: [再改]
使用者: "糟糕,沒考慮到資料庫設計..."
...反覆修改,浪費大量時間...
結果:
• 程式碼品質不一致
• 缺少測試和文檔
• 頻繁返工
• 技術債累積
✅ 有流程開發(系統化模式):
階段 1: 需求分析 (15 分鐘)
→ 明確功能範圍
→ 識別技術限制
→ 規劃整體架構
階段 2: 設計規劃 (20 分鐘)
→ 資料庫設計
→ API 設計
→ 前端架構
階段 3: 開發實作 (60 分鐘)
→ 後端開發
→ 前端開發
→ 整合測試
階段 4: 測試部署 (30 分鐘)
→ 單元測試
→ 整合測試
→ 部署檢查
結果:
• 高品質、可維護的程式碼
• 完整的測試覆蓋
• 清晰的文檔
• 減少技術債
📋 標準開發流程總覽
完整的開發生命週期
┌────────────────────────────────────────────────────┐
│ Claude Code 開發生命週期 │
│ │
│ 1️⃣ 需求分析階段 (Requirements Analysis) │
│ ├─ 理解需求 │
│ ├─ 識別限制條件 │
│ ├─ 評估可行性 │
│ └─ 定義驗收標準 │
│ │
│ 2️⃣ 設計規劃階段 (Design & Planning) │
│ ├─ 架構設計 │
│ ├─ 資料庫設計 │
│ ├─ API 設計 │
│ └─ 任務分解 │
│ │
│ 3️⃣ 開發實作階段 (Implementation) │
│ ├─ 後端開發 │
│ ├─ 前端開發 │
│ ├─ 整合開發 │
│ └─ 程式碼審查 │
│ │
│ 4️⃣ 測試驗證階段 (Testing & Validation) │
│ ├─ 單元測試 │
│ ├─ 整合測試 │
│ ├─ E2E 測試 │
│ └─ 效能測試 │
│ │
│ 5️⃣ 部署上線階段 (Deployment) │
│ ├─ 部署前檢查 │
│ ├─ 部署執行 │
│ ├─ 監控驗證 │
│ └─ 文檔更新 │
│ │
│ 6️⃣ 維護優化階段 (Maintenance) │
│ ├─ Bug 修復 │
│ ├─ 效能優化 │
│ ├─ 功能增強 │
│ └─ 重構優化 │
└────────────────────────────────────────────────────┘
1️⃣ 需求分析階段
目標:充分理解並明確化需求
與 Claude Code 的對話流程:
1步驟 1: 初步需求描述
2────────────────────────────────────────
3
4使用者:
5"我需要在電商網站加入購物車功能"
6
7Claude 回應(引導式提問):
8"我來幫你分析購物車功能的需求。請回答以下問題:
9
10【功能範圍】
111. 需要哪些核心功能?
12 - 新增商品到購物車
13 - 修改商品數量
14 - 移除商品
15 - 清空購物車
16 - 其他?
17
182. 需要支援哪些特殊情境?
19 - 未登入使用者的購物車(臨時儲存)
20 - 多裝置同步
21 - 購物車有效期限
22 - 庫存檢查
23
24【技術限制】
253. 現有技術棧?
26 - 前端框架(React, Vue, Angular?)
27 - 後端語言(Node.js, Python, Java?)
28 - 資料庫(PostgreSQL, MongoDB?)
29 - 狀態管理(Redux, Zustand?)
30
314. 整合需求?
32 - 需要整合哪些現有功能?
33 - 有哪些 API 要串接?
34
35【限制條件】
365. 效能要求?
37 - 預期使用者數量
38 - 回應時間要求
39 - 併發處理需求
40
416. 安全性要求?
42 - 需要什麼層級的資料保護?
43 - 是否需要防止惡意操作?"
需求文檔範本:
1步驟 2: 整理需求文檔
2────────────────────────────────────────
3
4使用者提供詳細資訊後:
5
6"請根據我的回答,整理一份完整的需求文檔,
7包含功能需求、技術需求、限制條件和驗收標準"
8
9Claude 產出:
10
11# 購物車功能需求文檔
12
13## 1. 功能需求
14
15### 1.1 核心功能
16- **新增商品**: 使用者可將商品加入購物車
17 - 支援指定數量
18 - 支援選擇商品規格(顏色、尺寸)
19 - 即時更新購物車數量顯示
20
21- **修改數量**: 使用者可調整購物車中的商品數量
22 - 支援直接輸入數量
23 - 支援 +/- 按鈕調整
24 - 數量限制:1-99
25
26- **移除商品**: 使用者可從購物車移除商品
27 - 提供確認對話框
28 - 支援一鍵清空功能
29
30- **購物車查看**: 顯示購物車內容
31 - 商品資訊(名稱、圖片、價格、規格)
32 - 小計和總計
33 - 優惠折扣顯示
34
35### 1.2 進階功能
36- **臨時購物車**: 未登入使用者的購物車
37 - 使用 localStorage 暫存
38 - 登入後自動合併
39
40- **庫存檢查**: 即時檢查商品庫存
41 - 庫存不足時提示
42 - 自動調整到最大可購買數量
43
44- **購物車同步**: 多裝置購物車同步
45 - 登入使用者的購物車存在伺服器
46 - 裝置間即時同步
47
48## 2. 技術需求
49
50### 2.1 技術棧
51- **前端**: React 18 + TypeScript
52- **狀態管理**: Zustand
53- **後端**: Node.js + Express
54- **資料庫**: PostgreSQL
55- **快取**: Redis(購物車資料)
56
57### 2.2 API 設計
58```typescript
59// 購物車 API endpoints
60POST /api/cart/items // 新增商品
61PUT /api/cart/items/:id // 更新數量
62DELETE /api/cart/items/:id // 移除商品
63GET /api/cart // 取得購物車
64DELETE /api/cart // 清空購物車
65POST /api/cart/merge // 合併臨時購物車
66```
67
68### 2.3 資料庫設計
69```sql
70-- 購物車資料表
71CREATE TABLE carts (
72 id UUID PRIMARY KEY,
73 user_id UUID REFERENCES users(id),
74 session_id VARCHAR(255), -- 未登入使用者
75 created_at TIMESTAMP,
76 updated_at TIMESTAMP
77);
78
79-- 購物車項目資料表
80CREATE TABLE cart_items (
81 id UUID PRIMARY KEY,
82 cart_id UUID REFERENCES carts(id),
83 product_id UUID REFERENCES products(id),
84 quantity INTEGER CHECK (quantity > 0 AND quantity <= 99),
85 variant_id UUID REFERENCES product_variants(id),
86 created_at TIMESTAMP,
87 updated_at TIMESTAMP,
88 UNIQUE(cart_id, product_id, variant_id)
89);
90```
91
92## 3. 限制條件
93
94### 3.1 效能要求
95- API 回應時間 < 200ms
96- 支援 1000 併發請求
97- 購物車最多 100 個商品
98
99### 3.2 安全性要求
100- API 需要認證(JWT)
101- 防止 CSRF 攻擊
102- 輸入驗證和淨化
103- Rate limiting(每分鐘 60 請求)
104
105### 3.3 相容性要求
106- 支援現代瀏覽器(Chrome, Firefox, Safari, Edge)
107- 移動裝置響應式設計
108- 無障礙設計(WCAG 2.1 AA)
109
110## 4. 驗收標準
111
112### 4.1 功能驗收
113- [ ] 使用者可以成功新增商品到購物車
114- [ ] 購物車數量顯示正確
115- [ ] 可以修改商品數量
116- [ ] 可以移除商品
117- [ ] 總金額計算正確
118- [ ] 未登入使用者的購物車在登入後正確合併
119- [ ] 庫存不足時正確提示
120
121### 4.2 效能驗收
122- [ ] 新增商品回應時間 < 200ms
123- [ ] 頁面載入時間 < 1s
124- [ ] 支援 1000 併發使用者
125
126### 4.3 安全性驗收
127- [ ] 未認證使用者無法存取他人購物車
128- [ ] 輸入驗證正常運作
129- [ ] XSS 和 CSRF 防護有效
130
131## 5. 開發時程估算
132
133- 資料庫設計與 API 開發: 2 天
134- 前端元件開發: 3 天
135- 整合與測試: 2 天
136- 部署與文檔: 1 天
137
138總計: 8 個工作天
需求確認檢查清單
1在進入設計階段前,確認以下項目:
2
3功能需求
4☐ 所有核心功能都已明確定義
5☐ 邊界情況和例外情境已考慮
6☐ 使用者體驗流程清晰
7☐ 與現有功能的整合點已識別
8
9技術需求
10☐ 技術棧已確定
11☐ 資料庫選擇已決定
12☐ API 設計原則已定義
13☐ 第三方服務整合需求明確
14
15限制條件
16☐ 效能要求已量化
17☐ 安全性需求已明確
18☐ 時間和資源限制已溝通
19☐ 相容性要求已定義
20
21驗收標準
22☐ 功能驗收標準可測試
23☐ 效能指標可量測
24☐ 成功標準明確無歧義
2️⃣ 設計規劃階段
目標:設計可擴展、可維護的架構
使用 Plan Mode 進行架構設計:
1// 啟動 Plan Mode(適合複雜功能)
2
3使用者:
4"根據購物車需求文檔(docs/cart-requirements.md),
5進入 Plan Mode 設計完整的實作計畫"
6
7Claude 回應:
8"我將進入 Plan Mode 為購物車功能設計實作計畫。
9讓我先探索專案結構..."
10
11[Claude 使用 Plan Agent]
12• Glob 掃描專案結構
13• Read 讀取相關檔案(現有的 API、資料庫設計)
14• Grep 搜尋類似功能的實作參考
Plan Agent 產出的實作計畫:
1# 購物車功能實作計畫
2
3## 階段 1: 資料庫設計 (2 小時)
4
5### 1.1 Schema 設計
6檔案: `prisma/schema.prisma`
7
8```prisma
9model Cart {
10 id String @id @default(uuid())
11 userId String? @map("user_id")
12 sessionId String? @map("session_id")
13 items CartItem[]
14 createdAt DateTime @default(now()) @map("created_at")
15 updatedAt DateTime @updatedAt @map("updated_at")
16
17 user User? @relation(fields: [userId], references: [id])
18
19 @@index([userId])
20 @@index([sessionId])
21 @@map("carts")
22}
23
24model CartItem {
25 id String @id @default(uuid())
26 cartId String @map("cart_id")
27 productId String @map("product_id")
28 variantId String? @map("variant_id")
29 quantity Int
30 createdAt DateTime @default(now()) @map("created_at")
31 updatedAt DateTime @updatedAt @map("updated_at")
32
33 cart Cart @relation(fields: [cartId], references: [id], onDelete: Cascade)
34 product Product @relation(fields: [productId], references: [id])
35 variant ProductVariant? @relation(fields: [variantId], references: [id])
36
37 @@unique([cartId, productId, variantId])
38 @@index([cartId])
39 @@map("cart_items")
40}
41```
42
43### 1.2 Migration
44```bash
45npx prisma migrate dev --name add_cart_tables
46```
47
48## 階段 2: 後端實作 (4 小時)
49
50### 2.1 服務層
51檔案: `src/services/cartService.ts`
52
53功能:
54- `getCart(userId, sessionId)`: 取得購物車
55- `addItem(cartId, productId, quantity, variantId)`: 新增商品
56- `updateItemQuantity(itemId, quantity)`: 更新數量
57- `removeItem(itemId)`: 移除商品
58- `clearCart(cartId)`: 清空購物車
59- `mergeCarts(userId, sessionId)`: 合併購物車
60- `validateStock(productId, quantity)`: 驗證庫存
61
62### 2.2 API 層
63檔案: `src/api/cart/cartController.ts`
64
65Endpoints:
66- `GET /api/cart` → getCart()
67- `POST /api/cart/items` → addItem()
68- `PUT /api/cart/items/:id` → updateItem()
69- `DELETE /api/cart/items/:id` → removeItem()
70- `DELETE /api/cart` → clearCart()
71- `POST /api/cart/merge` → mergeCarts()
72
73### 2.3 中介層
74檔案: `src/middleware/cartMiddleware.ts`
75
76功能:
77- `getOrCreateCart`: 取得或建立購物車
78- `validateCartAccess`: 驗證購物車存取權限
79- `checkStock`: 檢查庫存
80
81### 2.4 驗證層
82檔案: `src/validators/cartValidator.ts`
83
84驗證規則:
85- 商品 ID 格式
86- 數量範圍(1-99)
87- Variant ID(如有)
88
89## 階段 3: Redis 快取 (1 小時)
90
91### 3.1 快取策略
92檔案: `src/services/cacheService.ts`
93
94快取內容:
95- 購物車資料(TTL: 1 小時)
96- 商品庫存(TTL: 5 分鐘)
97
98快取 Key 設計:
99- `cart:{userId}` 或 `cart:session:{sessionId}`
100- `stock:{productId}`
101
102## 階段 4: 前端實作 (6 小時)
103
104### 4.1 狀態管理
105檔案: `src/stores/cartStore.ts`
106
107使用 Zustand:
108```typescript
109interface CartStore {
110 cart: Cart | null;
111 isLoading: boolean;
112 error: string | null;
113
114 // Actions
115 fetchCart: () => Promise<void>;
116 addItem: (productId, quantity, variantId?) => Promise<void>;
117 updateQuantity: (itemId, quantity) => Promise<void>;
118 removeItem: (itemId) => Promise<void>;
119 clearCart: () => Promise<void>;
120}
121```
122
123### 4.2 元件開發
124檔案結構:
125```
126src/components/Cart/
127├── CartButton.tsx # 購物車圖示按鈕
128├── CartDrawer.tsx # 購物車側邊欄
129├── CartItem.tsx # 購物車項目
130├── CartSummary.tsx # 購物車摘要
131├── AddToCartButton.tsx # 加入購物車按鈕
132└── EmptyCart.tsx # 空購物車狀態
133```
134
135### 4.3 API 整合
136檔案: `src/api/cartApi.ts`
137
138使用 axios:
139```typescript
140export const cartApi = {
141 getCart: () => api.get('/cart'),
142 addItem: (data) => api.post('/cart/items', data),
143 updateItem: (id, data) => api.put(`/cart/items/${id}`, data),
144 removeItem: (id) => api.delete(`/cart/items/${id}`),
145 clearCart: () => api.delete('/cart'),
146};
147```
148
149## 階段 5: 測試 (4 小時)
150
151### 5.1 單元測試
152- `cartService.test.ts`: 服務層邏輯測試
153- `cartController.test.ts`: API 層測試
154- `cartStore.test.ts`: 狀態管理測試
155
156### 5.2 整合測試
157- `cart.integration.test.ts`: API 整合測試
158- 測試完整的購物車流程
159
160### 5.3 E2E 測試
161- `cart.e2e.test.ts`: 使用者操作流程測試
162
163## 階段 6: 部署準備 (2 小時)
164
165### 6.1 環境變數
166```.env
167REDIS_URL=redis://localhost:6379
168DATABASE_URL=postgresql://...
169```
170
171### 6.2 部署檢查清單
172- [ ] Migration 已執行
173- [ ] Redis 連線正常
174- [ ] API endpoints 測試通過
175- [ ] 前端打包成功
176- [ ] 環境變數已設定
177
178### 6.3 文檔更新
179- API 文檔(OpenAPI/Swagger)
180- 使用者操作指南
181- 開發者文檔
182
183## 風險與注意事項
184
185⚠️ **潛在風險:**
1861. 併發購物車更新衝突
187 → 使用樂觀鎖定(Optimistic Locking)
188
1892. Redis 快取與資料庫不一致
190 → 實作 Cache-Aside Pattern,設定適當 TTL
191
1923. 庫存超賣問題
193 → 在 checkout 時再次驗證庫存
194
1954. 大量商品導致購物車載入慢
196 → 實作分頁或虛擬捲動
197
198## 總時程估算
199
200- 階段 1 (資料庫): 2 小時
201- 階段 2 (後端): 4 小時
202- 階段 3 (快取): 1 小時
203- 階段 4 (前端): 6 小時
204- 階段 5 (測試): 4 小時
205- 階段 6 (部署): 2 小時
206
207**總計: 19 小時 (約 2.5 個工作天)**
Plan Mode 的價值:
✅ 使用 Plan Mode 的好處:
1. 全面性規劃
• 考慮所有技術層面
• 識別潛在問題
• 規劃測試策略
2. 結構化執行
• 明確的階段劃分
• 清晰的檔案組織
• 可追蹤的進度
3. 團隊協作
• 可供審查的設計文檔
• 明確的任務分工
• 統一的實作標準
4. 風險管理
• 提前識別風險
• 規劃應對策略
• 預估時程
3️⃣ 開發實作階段
目標:按計畫高效實作功能
實作流程範例:後端開發
1═══════════════════════════════════════════════════════
2對話 1: 資料庫設計與 Migration
3═══════════════════════════════════════════════════════
4
5使用者:
6"根據實作計畫(docs/cart-implementation-plan.md),
7開始階段 1:資料庫設計。
8
9請:
101. 更新 prisma/schema.prisma 加入 Cart 和 CartItem models
112. 產生 migration
123. 執行 migration
134. 驗證 schema"
14
15Claude 執行:
16├─ Read prisma/schema.prisma
17├─ Edit 加入新的 models
18├─ Bash: npx prisma migrate dev --name add_cart_tables
19├─ Bash: npx prisma generate
20└─ 回報執行結果
21
22【使用 TodoWrite 追蹤進度】
23✓ 完成: 設計 Cart 和 CartItem schema
24✓ 完成: 建立 migration
25✓ 完成: 執行 migration
26⏳ 待處理: 實作 cartService
27⏳ 待處理: 實作 API endpoints
28...
29
30═══════════════════════════════════════════════════════
31對話 2: 服務層實作
32═══════════════════════════════════════════════════════
33
34使用者:
35"實作 src/services/cartService.ts,包含計畫中的所有功能。
36
37要求:
38- 使用 Prisma Client
39- 包含完整的錯誤處理
40- 加入 JSDoc 註解
41- 處理邊界情況(庫存不足、商品不存在等)"
42
43Claude 執行:
44├─ Read prisma/schema.prisma(了解 schema)
45├─ Read src/services/userService.ts(參考現有服務模式)
46├─ Write src/services/cartService.ts
47└─ 加入完整的型別定義和錯誤處理
48
49產出範例:
50
51```typescript
52// src/services/cartService.ts
53import { PrismaClient } from '@prisma/client';
54import { CartNotFoundError, InsufficientStockError } from '../errors';
55
56const prisma = new PrismaClient();
57
58export class CartService {
59 /**
60 * 取得購物車
61 * @param userId - 使用者 ID(已登入)
62 * @param sessionId - Session ID(未登入)
63 */
64 async getCart(userId?: string, sessionId?: string) {
65 if (!userId && !sessionId) {
66 throw new Error('userId or sessionId is required');
67 }
68
69 let cart = await prisma.cart.findFirst({
70 where: userId ? { userId } : { sessionId },
71 include: {
72 items: {
73 include: {
74 product: true,
75 variant: true,
76 },
77 },
78 },
79 });
80
81 // 如果購物車不存在,建立新的
82 if (!cart) {
83 cart = await prisma.cart.create({
84 data: {
85 userId,
86 sessionId,
87 },
88 include: {
89 items: {
90 include: {
91 product: true,
92 variant: true,
93 },
94 },
95 },
96 });
97 }
98
99 return cart;
100 }
101
102 /**
103 * 新增商品到購物車
104 */
105 async addItem(
106 cartId: string,
107 productId: string,
108 quantity: number,
109 variantId?: string
110 ) {
111 // 驗證庫存
112 await this.validateStock(productId, quantity, variantId);
113
114 // 檢查是否已存在
115 const existingItem = await prisma.cartItem.findFirst({
116 where: {
117 cartId,
118 productId,
119 variantId: variantId || null,
120 },
121 });
122
123 if (existingItem) {
124 // 更新數量
125 return await prisma.cartItem.update({
126 where: { id: existingItem.id },
127 data: {
128 quantity: existingItem.quantity + quantity,
129 },
130 include: {
131 product: true,
132 variant: true,
133 },
134 });
135 } else {
136 // 新增項目
137 return await prisma.cartItem.create({
138 data: {
139 cartId,
140 productId,
141 variantId,
142 quantity,
143 },
144 include: {
145 product: true,
146 variant: true,
147 },
148 });
149 }
150 }
151
152 /**
153 * 驗證庫存
154 */
155 private async validateStock(
156 productId: string,
157 quantity: number,
158 variantId?: string
159 ) {
160 const product = await prisma.product.findUnique({
161 where: { id: productId },
162 include: {
163 variants: variantId ? { where: { id: variantId } } : false,
164 },
165 });
166
167 if (!product) {
168 throw new ProductNotFoundError(productId);
169 }
170
171 const stock = variantId
172 ? product.variants[0]?.stock
173 : product.stock;
174
175 if (stock < quantity) {
176 throw new InsufficientStockError(
177 productId,
178 variantId,
179 stock,
180 quantity
181 );
182 }
183 }
184
185 // ... 其他方法
186}
187
188export const cartService = new CartService();
189```
190
191【Todo 更新】
192✓ 完成: 設計 Cart 和 CartItem schema
193✓ 完成: 建立 migration
194✓ 完成: 執行 migration
195✓ 完成: 實作 cartService ✓
196🔄 進行中: 實作 API endpoints
197⏳ 待處理: 實作測試
198...
199
200═══════════════════════════════════════════════════════
201對話 3: API Endpoints 實作
202═══════════════════════════════════════════════════════
203
204使用者:
205"實作 src/api/cart/cartController.ts 和路由設定。
206
207參考:
208- 現有的 API 模式: src/api/products/productController.ts
209- Express Router 設定: src/api/index.ts
210
211要求:
212- RESTful API 設計
213- 使用 async/await
214- 完整的錯誤處理
215- 輸入驗證(使用 express-validator)"
216
217Claude 執行:
218├─ Read src/api/products/productController.ts(學習模式)
219├─ Read src/api/index.ts(了解路由結構)
220├─ Write src/api/cart/cartController.ts
221├─ Write src/api/cart/cartRouter.ts
222├─ Edit src/api/index.ts(加入購物車路由)
223└─ Write src/validators/cartValidator.ts
224
225產出範例:
226
227```typescript
228// src/api/cart/cartController.ts
229import { Request, Response, NextFunction } from 'express';
230import { cartService } from '../../services/cartService';
231import { ApiError } from '../../errors';
232
233export class CartController {
234 /**
235 * GET /api/cart
236 * 取得使用者的購物車
237 */
238 async getCart(req: Request, res: Response, next: NextFunction) {
239 try {
240 const userId = req.user?.id;
241 const sessionId = req.session?.id;
242
243 const cart = await cartService.getCart(userId, sessionId);
244
245 res.json({
246 success: true,
247 data: cart,
248 });
249 } catch (error) {
250 next(error);
251 }
252 }
253
254 /**
255 * POST /api/cart/items
256 * 新增商品到購物車
257 */
258 async addItem(req: Request, res: Response, next: NextFunction) {
259 try {
260 const { productId, quantity, variantId } = req.body;
261 const userId = req.user?.id;
262 const sessionId = req.session?.id;
263
264 // 取得或建立購物車
265 const cart = await cartService.getCart(userId, sessionId);
266
267 // 新增商品
268 const item = await cartService.addItem(
269 cart.id,
270 productId,
271 quantity,
272 variantId
273 );
274
275 res.status(201).json({
276 success: true,
277 data: item,
278 });
279 } catch (error) {
280 next(error);
281 }
282 }
283
284 // ... 其他方法
285}
286
287export const cartController = new CartController();
288```
289
290```typescript
291// src/api/cart/cartRouter.ts
292import { Router } from 'express';
293import { cartController } from './cartController';
294import { validateAddItem } from '../../validators/cartValidator';
295import { authMiddleware } from '../../middleware/auth';
296
297const router = Router();
298
299// 所有路由都需要認證(或 session)
300router.use(authMiddleware.optionalAuth);
301
302router.get('/', cartController.getCart);
303router.post('/items', validateAddItem, cartController.addItem);
304router.put('/items/:id', cartController.updateItem);
305router.delete('/items/:id', cartController.removeItem);
306router.delete('/', cartController.clearCart);
307router.post('/merge', authMiddleware.requireAuth, cartController.mergeCarts);
308
309export default router;
310```
311
312【Todo 更新】
313✓ 完成: 實作 cartService
314✓ 完成: 實作 API endpoints ✓
315🔄 進行中: 撰寫測試
316⏳ 待處理: 實作前端
317...
318
319═══════════════════════════════════════════════════════
320對話 4: 測試撰寫
321═══════════════════════════════════════════════════════
322
323使用者:
324"為 cartService 撰寫完整的單元測試。
325
326測試框架: Jest
327測試檔案: src/services/__tests__/cartService.test.ts
328
329測試涵蓋:
330- 正常流程
331- 邊界情況
332- 錯誤處理
333- 併發情境
334
335期望覆蓋率 > 90%"
336
337Claude 執行:
338├─ Read src/services/cartService.ts
339├─ Read src/services/__tests__/userService.test.ts(參考測試模式)
340└─ Write src/services/__tests__/cartService.test.ts
341
342產出範例:
343
344```typescript
345// src/services/__tests__/cartService.test.ts
346import { cartService } from '../cartService';
347import { prisma } from '../../lib/prisma';
348import {
349 ProductNotFoundError,
350 InsufficientStockError,
351} from '../../errors';
352
353// Mock Prisma
354jest.mock('../../lib/prisma', () => ({
355 prisma: {
356 cart: {
357 findFirst: jest.fn(),
358 create: jest.fn(),
359 },
360 cartItem: {
361 findFirst: jest.fn(),
362 create: jest.fn(),
363 update: jest.fn(),
364 },
365 product: {
366 findUnique: jest.fn(),
367 },
368 },
369}));
370
371describe('CartService', () => {
372 beforeEach(() => {
373 jest.clearAllMocks();
374 });
375
376 describe('getCart', () => {
377 it('should return existing cart for user', async () => {
378 const mockCart = {
379 id: 'cart-1',
380 userId: 'user-1',
381 items: [],
382 };
383
384 (prisma.cart.findFirst as jest.Mock).mockResolvedValue(mockCart);
385
386 const result = await cartService.getCart('user-1');
387
388 expect(result).toEqual(mockCart);
389 expect(prisma.cart.findFirst).toHaveBeenCalledWith({
390 where: { userId: 'user-1' },
391 include: expect.any(Object),
392 });
393 });
394
395 it('should create new cart if not exists', async () => {
396 (prisma.cart.findFirst as jest.Mock).mockResolvedValue(null);
397 (prisma.cart.create as jest.Mock).mockResolvedValue({
398 id: 'cart-2',
399 userId: 'user-2',
400 items: [],
401 });
402
403 const result = await cartService.getCart('user-2');
404
405 expect(result.id).toBe('cart-2');
406 expect(prisma.cart.create).toHaveBeenCalled();
407 });
408
409 it('should throw error if no userId or sessionId', async () => {
410 await expect(cartService.getCart()).rejects.toThrow();
411 });
412 });
413
414 describe('addItem', () => {
415 it('should add new item to cart', async () => {
416 const mockProduct = {
417 id: 'product-1',
418 stock: 10,
419 };
420
421 (prisma.product.findUnique as jest.Mock).mockResolvedValue(mockProduct);
422 (prisma.cartItem.findFirst as jest.Mock).mockResolvedValue(null);
423 (prisma.cartItem.create as jest.Mock).mockResolvedValue({
424 id: 'item-1',
425 productId: 'product-1',
426 quantity: 2,
427 });
428
429 const result = await cartService.addItem('cart-1', 'product-1', 2);
430
431 expect(result.quantity).toBe(2);
432 expect(prisma.cartItem.create).toHaveBeenCalled();
433 });
434
435 it('should update quantity if item exists', async () => {
436 const mockProduct = { id: 'product-1', stock: 10 };
437 const existingItem = {
438 id: 'item-1',
439 quantity: 3,
440 };
441
442 (prisma.product.findUnique as jest.Mock).mockResolvedValue(mockProduct);
443 (prisma.cartItem.findFirst as jest.Mock).mockResolvedValue(existingItem);
444 (prisma.cartItem.update as jest.Mock).mockResolvedValue({
445 ...existingItem,
446 quantity: 5,
447 });
448
449 const result = await cartService.addItem('cart-1', 'product-1', 2);
450
451 expect(result.quantity).toBe(5);
452 expect(prisma.cartItem.update).toHaveBeenCalled();
453 });
454
455 it('should throw InsufficientStockError when stock is low', async () => {
456 const mockProduct = {
457 id: 'product-1',
458 stock: 2,
459 };
460
461 (prisma.product.findUnique as jest.Mock).mockResolvedValue(mockProduct);
462
463 await expect(
464 cartService.addItem('cart-1', 'product-1', 5)
465 ).rejects.toThrow(InsufficientStockError);
466 });
467
468 it('should throw ProductNotFoundError for invalid product', async () => {
469 (prisma.product.findUnique as jest.Mock).mockResolvedValue(null);
470
471 await expect(
472 cartService.addItem('cart-1', 'invalid-id', 1)
473 ).rejects.toThrow(ProductNotFoundError);
474 });
475 });
476
477 // ... 更多測試
478});
479```
480
481【Todo 更新】
482✓ 完成: 實作 cartService
483✓ 完成: 實作 API endpoints
484✓ 完成: 撰寫 cartService 單元測試 ✓
485🔄 進行中: 撰寫 API 整合測試
486⏳ 待處理: 實作前端
487...
前端開發流程
1═══════════════════════════════════════════════════════
2對話 5: Zustand Store 實作
3═══════════════════════════════════════════════════════
4
5使用者:
6"實作 src/stores/cartStore.ts,使用 Zustand 管理購物車狀態。
7
8參考現有的 Store 模式: src/stores/authStore.ts
9
10包含:
11- 購物車狀態
12- Loading 和 error 狀態
13- 所有 CRUD 操作
14- 樂觀更新(Optimistic Updates)"
15
16Claude 產出:
17
18```typescript
19// src/stores/cartStore.ts
20import { create } from 'zustand';
21import { devtools, persist } from 'zustand/middleware';
22import { cartApi } from '../api/cartApi';
23import type { Cart, CartItem } from '../types/cart';
24
25interface CartStore {
26 // State
27 cart: Cart | null;
28 isLoading: boolean;
29 error: string | null;
30
31 // Actions
32 fetchCart: () => Promise<void>;
33 addItem: (productId: string, quantity: number, variantId?: string) => Promise<void>;
34 updateQuantity: (itemId: string, quantity: number) => Promise<void>;
35 removeItem: (itemId: string) => Promise<void>;
36 clearCart: () => Promise<void>;
37 reset: () => void;
38}
39
40export const useCartStore = create<CartStore>()(
41 devtools(
42 persist(
43 (set, get) => ({
44 // Initial state
45 cart: null,
46 isLoading: false,
47 error: null,
48
49 // Fetch cart
50 fetchCart: async () => {
51 set({ isLoading: true, error: null });
52 try {
53 const response = await cartApi.getCart();
54 set({ cart: response.data, isLoading: false });
55 } catch (error) {
56 set({
57 error: error.message,
58 isLoading: false,
59 });
60 }
61 },
62
63 // Add item with optimistic update
64 addItem: async (productId, quantity, variantId) => {
65 const previousCart = get().cart;
66
67 // Optimistic update
68 set((state) => ({
69 cart: state.cart
70 ? {
71 ...state.cart,
72 items: [
73 ...state.cart.items,
74 {
75 id: 'temp-' + Date.now(),
76 productId,
77 quantity,
78 variantId,
79 product: null, // Will be filled by API
80 } as CartItem,
81 ],
82 }
83 : null,
84 }));
85
86 try {
87 const response = await cartApi.addItem({
88 productId,
89 quantity,
90 variantId,
91 });
92
93 // Update with real data
94 await get().fetchCart();
95 } catch (error) {
96 // Rollback on error
97 set({ cart: previousCart, error: error.message });
98 }
99 },
100
101 // Update quantity
102 updateQuantity: async (itemId, quantity) => {
103 const previousCart = get().cart;
104
105 // Optimistic update
106 set((state) => ({
107 cart: state.cart
108 ? {
109 ...state.cart,
110 items: state.cart.items.map((item) =>
111 item.id === itemId
112 ? { ...item, quantity }
113 : item
114 ),
115 }
116 : null,
117 }));
118
119 try {
120 await cartApi.updateItem(itemId, { quantity });
121 } catch (error) {
122 // Rollback on error
123 set({ cart: previousCart, error: error.message });
124 }
125 },
126
127 // Remove item
128 removeItem: async (itemId) => {
129 const previousCart = get().cart;
130
131 // Optimistic update
132 set((state) => ({
133 cart: state.cart
134 ? {
135 ...state.cart,
136 items: state.cart.items.filter(
137 (item) => item.id !== itemId
138 ),
139 }
140 : null,
141 }));
142
143 try {
144 await cartApi.removeItem(itemId);
145 } catch (error) {
146 // Rollback on error
147 set({ cart: previousCart, error: error.message });
148 }
149 },
150
151 // Clear cart
152 clearCart: async () => {
153 const previousCart = get().cart;
154
155 // Optimistic update
156 set((state) => ({
157 cart: state.cart ? { ...state.cart, items: [] } : null,
158 }));
159
160 try {
161 await cartApi.clearCart();
162 } catch (error) {
163 // Rollback on error
164 set({ cart: previousCart, error: error.message });
165 }
166 },
167
168 // Reset state
169 reset: () => {
170 set({ cart: null, isLoading: false, error: null });
171 },
172 }),
173 {
174 name: 'cart-storage',
175 partialize: (state) => ({ cart: state.cart }), // Only persist cart data
176 }
177 )
178 )
179);
180```
181
182═══════════════════════════════════════════════════════
183對話 6: React 元件實作
184═══════════════════════════════════════════════════════
185
186使用者:
187"實作購物車 UI 元件。
188
189參考設計: figma.com/design/cart-ui
190
191元件列表(按計畫):
1921. CartButton - 購物車按鈕(顯示數量)
1932. CartDrawer - 購物車側邊欄
1943. CartItem - 購物車項目
1954. AddToCartButton - 加入購物車按鈕
196
197使用:
198- Tailwind CSS
199- Radix UI (Drawer, Dialog)
200- React Icons
201
202先實作 CartButton"
203
204Claude 執行:
205├─ Read src/components/common/Button.tsx(學習元件模式)
206├─ Read src/stores/cartStore.ts(理解狀態管理)
207└─ Write src/components/Cart/CartButton.tsx
208
209產出範例:
210
211```typescript
212// src/components/Cart/CartButton.tsx
213import { ShoppingCart } from 'react-icons/ri';
214import { useCartStore } from '../../stores/cartStore';
215import { Button } from '../common/Button';
216
217interface CartButtonProps {
218 onClick: () => void;
219}
220
221export function CartButton({ onClick }: CartButtonProps) {
222 const cart = useCartStore((state) => state.cart);
223
224 // Calculate total items
225 const itemCount = cart?.items.reduce(
226 (sum, item) => sum + item.quantity,
227 0
228 ) || 0;
229
230 return (
231 <Button
232 variant="ghost"
233 size="md"
234 onClick={onClick}
235 className="relative"
236 aria-label={`購物車,${itemCount} 件商品`}
237 >
238 <ShoppingCart className="w-6 h-6" />
239
240 {/* Badge showing item count */}
241 {itemCount > 0 && (
242 <span
243 className="absolute -top-1 -right-1 bg-red-500 text-white
244 text-xs font-bold rounded-full w-5 h-5
245 flex items-center justify-center"
246 aria-label={`${itemCount} 件商品`}
247 >
248 {itemCount > 99 ? '99+' : itemCount}
249 </span>
250 )}
251 </Button>
252 );
253}
254```
255
256【逐步完成所有元件...】
257
258═══════════════════════════════════════════════════════
259對話 7: 整合與測試
260═══════════════════════════════════════════════════════
261
262使用者:
263"整合所有購物車元件到主應用程式,並執行測試。
264
265步驟:
2661. 在 Layout 加入 CartButton
2672. 在商品頁加入 AddToCartButton
2683. 實作 CartDrawer 的開啟/關閉邏輯
2694. 執行所有測試
2705. 手動測試完整流程"
271
272Claude 執行:
273├─ Edit src/components/Layout/Header.tsx
274├─ Edit src/pages/products/[id].tsx
275├─ Bash: npm test
276├─ 分析測試結果
277└─ 提供手動測試檢查清單
278
279【Todo 更新】
280✓ 完成: 所有後端開發
281✓ 完成: 所有前端開發
282✓ 完成: 整合測試
283🔄 進行中: 手動測試和 bug 修復
284⏳ 待處理: 部署準備
4️⃣ 測試驗證階段
目標:確保功能正確且穩定
完整測試策略:
1使用者:
2"執行完整的測試流程,確保購物車功能正常運作。
3
4【測試層級】
51. 單元測試
6 - 所有 service 函式
7 - 所有 React hooks
8 - 工具函式
9
102. 整合測試
11 - API endpoints
12 - 資料庫操作
13 - 前後端整合
14
153. E2E 測試
16 - 使用者完整流程
17 - 不同裝置和瀏覽器
18
194. 效能測試
20 - 回應時間
21 - 併發處理
22
23請逐一執行並回報結果"
24
25Claude 執行測試流程:
26
27【階段 1: 單元測試】
28```bash
29$ npm run test:unit
30
31執行結果:
32✓ cartService.test.ts (12 tests)
33✓ cartStore.test.ts (8 tests)
34✓ cartUtils.test.ts (5 tests)
35
36覆蓋率:
37Statements : 92.5% (148/160)
38Branches : 88.3% (53/60)
39Functions : 95.0% (38/40)
40Lines : 93.1% (135/145)
41
42⚠️ 低覆蓋率區域:
43- cartService.ts:156-162 (錯誤處理分支)
44→ 建議: 新增錯誤情境測試
45```
46
47【階段 2: 整合測試】
48```bash
49$ npm run test:integration
50
51執行結果:
52✓ POST /api/cart/items (4 tests)
53✓ PUT /api/cart/items/:id (3 tests)
54✓ DELETE /api/cart/items/:id (2 tests)
55✓ GET /api/cart (3 tests)
56
57所有 API endpoints 測試通過
58平均回應時間: 45ms (< 200ms 目標 ✓)
59```
60
61【階段 3: E2E 測試】
62```bash
63$ npm run test:e2e
64
65執行結果:
66✓ User can add items to cart
67✓ User can update item quantity
68✓ User can remove items
69✓ Cart persists across page reloads
70✓ Guest cart merges after login
71
72所有使用者流程測試通過
73```
74
75【階段 4: 效能測試】
76```bash
77$ npm run test:performance
78
79結果:
80平均回應時間:
81- GET /api/cart: 38ms ✓
82- POST /api/cart/items: 52ms ✓
83- PUT /api/cart/items/:id: 41ms ✓
84
85併發測試 (100 concurrent users):
86- 成功率: 100% ✓
87- P95 延遲: 125ms ✓
88- P99 延遲: 210ms ✓
89
90全部通過效能目標!
91```
92
93【測試摘要】
94所有測試通過 ✓
95- 單元測試: 25/25
96- 整合測試: 12/12
97- E2E 測試: 5/5
98- 效能測試: 通過
99
100建議修復:
1011. 提升錯誤處理測試覆蓋率
1022. 新增更多邊界情況測試
5️⃣ 部署上線階段
目標:安全、順利地部署到生產環境
部署檢查清單:
1使用者:
2"準備將購物車功能部署到生產環境。
3
4請協助完成部署前檢查清單,並生成部署文檔。"
5
6Claude 生成檢查清單:
7
8# 購物車功能部署檢查清單
9
10## 前置檢查
11
12### 1. 程式碼品質
13- [x] 所有測試通過(單元、整合、E2E)
14- [x] 程式碼已經過 Code Review
15- [x] ESLint/Prettier 檢查通過
16- [x] 無 TypeScript 錯誤
17- [x] 無安全性漏洞(npm audit)
18
19### 2. 資料庫
20- [ ] Migration 腳本已準備
21- [ ] Migration 已在 staging 環境測試
22- [ ] 備份計畫已就緒
23- [ ] Rollback 腳本已準備
24
25### 3. 環境變數
26- [ ] 生產環境變數已設定
27 - DATABASE_URL
28 - REDIS_URL
29 - SESSION_SECRET
30- [ ] API keys 已更新為生產版本
31- [ ] 環境變數已加密儲存
32
33### 4. 依賴套件
34- [ ] package.json 版本鎖定
35- [ ] node_modules 大小合理
36- [ ] 無未使用的依賴
37- [ ] 安全性更新已套用
38
39### 5. 效能
40- [ ] 前端打包已優化(code splitting)
41- [ ] 圖片已壓縮
42- [ ] API 回應時間符合目標(< 200ms)
43- [ ] Redis 快取策略已設定
44
45### 6. 監控
46- [ ] 錯誤追蹤已設定(Sentry)
47- [ ] 效能監控已設定(New Relic)
48- [ ] 日誌系統已配置
49- [ ] Alert 規則已設定
50
51### 7. 文檔
52- [ ] API 文檔已更新
53- [ ] 使用者指南已準備
54- [ ] 開發者文檔已更新
55- [ ] Changelog 已記錄
56
57## 部署步驟
58
59### Step 1: 資料庫 Migration
60```bash
61# 在生產環境執行
62npm run migrate:production
63
64# 驗證
65npm run migrate:status
66```
67
68### Step 2: 部署後端
69```bash
70# 打包
71npm run build
72
73# 部署到伺服器
74npm run deploy:api
75
76# 健康檢查
77curl https://api.example.com/health
78```
79
80### Step 3: 部署前端
81```bash
82# 打包
83npm run build:frontend
84
85# 部署到 CDN
86npm run deploy:frontend
87
88# 驗證
89curl https://example.com
90```
91
92### Step 4: 驗證部署
93- [ ] 前端頁面正常載入
94- [ ] API endpoints 正常回應
95- [ ] 購物車功能正常運作
96- [ ] 資料庫連線正常
97- [ ] Redis 快取正常
98
99### Step 5: 監控觀察
100```markdown
101部署後監控 (前 24 小時):
102- 每小時檢查錯誤率
103- 監控 API 回應時間
104- 檢查資料庫連線數
105- 觀察 Redis 記憶體使用
106
107正常指標:
108- 錯誤率 < 0.1%
109- API P95 延遲 < 200ms
110- 資料庫連線 < 80% pool size
111- Redis 記憶體使用 < 70%
112```
113
114## Rollback 計畫
115
116### 如果發生問題:
117
1181. **停止新流量**
119 ```bash
120 # 切換到舊版本
121 kubectl rollout undo deployment/api-server
122 ```
123
1242. **Rollback 資料庫**
125 ```bash
126 # 執行 rollback migration
127 npm run migrate:rollback
128 ```
129
1303. **通知團隊**
131 - Slack #incidents 頻道
132 - 記錄問題詳情
133 - 安排事後檢討
134
1354. **事後檢討**
136 - 分析失敗原因
137 - 更新部署流程
138 - 加強測試覆蓋
139
140## 成功標準
141
142部署被視為成功當:
143- [x] 所有健康檢查通過
144- [x] 24 小時內無重大錯誤
145- [x] 效能指標符合目標
146- [x] 使用者回饋正面
147- [x] 無需 Rollback
6️⃣ 維護優化階段
目標:持續改進和維護功能
常見維護情境:
情境 1: Bug 修復
1使用者:
2"生產環境回報:當購物車中有 50+ 商品時,
3載入速度很慢(> 5 秒)。
4
5錯誤追蹤 (Sentry):
6- URL: /api/cart
7- 回應時間: 5.2s (P95: 6.8s)
8- 使用者影響: 約 2% 使用者
9
10請協助診斷並修復"
11
12Claude 診斷流程:
13
14【步驟 1: 重現問題】
15"根據錯誤報告,讓我們先在開發環境重現問題。
16
17我需要:
181. 建立測試用購物車(50+ 商品)
192. 測量 API 回應時間
203. 分析效能瓶頸"
21
22【步驟 2: 分析問題】
23使用 Bash tool 執行分析:
24```bash
25# 使用效能分析工具
26npm run profile:api -- GET /api/cart
27
28結果分析:
29┌─────────────────────────┬──────────┐
30│ 操作 │ 時間 │
31├─────────────────────────┼──────────┤
32│ Prisma 查詢 │ 4.8s │ ← 瓶頸!
33│ 資料序列化 │ 0.3s │
34│ 網路傳輸 │ 0.1s │
35└─────────────────────────┴──────────┘
36
37【診斷】
38問題出在 Prisma 查詢,沒有使用 select 限制欄位,
39抓取了所有關聯資料(包含不需要的 product descriptions,
40reviews 等大量資料)
41```
42
43【步驟 3: 實作修復】
44```typescript
45// 修復前(慢)
46const cart = await prisma.cart.findFirst({
47 where: { userId },
48 include: {
49 items: {
50 include: {
51 product: true, // 抓取所有 product 欄位
52 variant: true, // 抓取所有 variant 欄位
53 },
54 },
55 },
56});
57
58// 修復後(快)
59const cart = await prisma.cart.findFirst({
60 where: { userId },
61 include: {
62 items: {
63 include: {
64 product: {
65 select: {
66 id: true,
67 name: true,
68 price: true,
69 imageUrl: true,
70 // 只選擇需要的欄位
71 },
72 },
73 variant: {
74 select: {
75 id: true,
76 name: true,
77 price: true,
78 },
79 },
80 },
81 },
82 },
83});
84```
85
86【步驟 4: 測試驗證】
87```bash
88# 測試修復後的效能
89npm run profile:api -- GET /api/cart
90
91新的結果:
92┌─────────────────────────┬──────────┐
93│ 操作 │ 時間 │
94├─────────────────────────┼──────────┤
95│ Prisma 查詢 │ 0.15s │ ✓ 改善 97%!
96│ 資料序列化 │ 0.08s │
97│ 網路傳輸 │ 0.05s │
98│ 總計 │ 0.28s │ ✓ 符合目標!
99└─────────────────────────┴──────────┘
100```
101
102【步驟 5: 部署修復】
103```bash
104# 建立 hotfix branch
105/commit -m "perf(cart): optimize cart query by selecting only required fields
106
107- Reduce query time from 4.8s to 0.15s (97% improvement)
108- Select only necessary product and variant fields
109- Fixes slow cart loading for users with 50+ items
110
111Closes #BUG-123"
112
113# 部署到生產環境
114npm run deploy:hotfix
115```
情境 2: 效能優化
1使用者:
2"想優化購物車的整體效能。請分析目前的效能瓶頸,
3並提供優化建議"
4
5Claude 分析流程:
6
7【階段 1: 效能基準測試】
8執行完整的效能分析:
9```bash
10npm run test:performance -- --detailed
11
12結果報告:
13━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
14購物車效能分析報告
15━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
16
17API 回應時間:
18├─ GET /api/cart
19│ ├─ P50: 145ms
20│ ├─ P95: 320ms ⚠️ 超過目標 (200ms)
21│ └─ P99: 580ms ⚠️
22│
23├─ POST /api/cart/items
24│ ├─ P50: 180ms
25│ ├─ P95: 380ms ⚠️
26│ └─ P99: 650ms ⚠️
27
28前端載入時間:
29├─ 初次載入: 2.8s ⚠️
30├─ React 渲染: 850ms ⚠️
31└─ API 呼叫: 320ms
32
33識別的瓶頸:
341. 資料庫查詢未使用索引
352. 無 Redis 快取
363. 前端過度渲染
374. API 回應未壓縮
38```
39
40【階段 2: 優化建議】
41Claude 提供完整優化計畫:
42
43````markdown
44# 購物車效能優化計畫
45
46## 優化 1: 資料庫索引 (預期改善 40%)
47
48### 分析
49目前 cart_items 表沒有在 cart_id 上建立索引,
50查詢 50+ 商品時需要全表掃描
51
52### 實作
53```sql
54CREATE INDEX idx_cart_items_cart_id ON cart_items(cart_id);
55CREATE INDEX idx_carts_user_id ON carts(user_id);
56CREATE INDEX idx_carts_session_id ON carts(session_id);
57```
58
59### 預期結果
60- 查詢時間: 150ms → 90ms
61- P95 延遲: 320ms → 200ms ✓
62
63## 優化 2: Redis 快取 (預期改善 60%)
64
65### 策略
66```typescript
67// 快取策略
68const CART_CACHE_TTL = 3600; // 1 hour
69
70async function getCachedCart(userId: string) {
71 // 1. 嘗試從 Redis 讀取
72 const cached = await redis.get(`cart:${userId}`);
73 if (cached) {
74 return JSON.parse(cached);
75 }
76
77 // 2. 從資料庫查詢
78 const cart = await prisma.cart.findFirst({
79 where: { userId },
80 include: { items: { include: { product: true } } },
81 });
82
83 // 3. 寫入 Redis
84 await redis.setex(
85 `cart:${userId}`,
86 CART_CACHE_TTL,
87 JSON.stringify(cart)
88 );
89
90 return cart;
91}
92```
93
94### 預期結果
95- 快取命中時: 90ms → 10ms
96- P95 延遲: 200ms → 50ms ✓
97
98## 優化 3: 前端優化 (預期改善 50%)
99
100### React.memo 和 useMemo
101```typescript
102// 優化前
103function CartItem({ item }) {
104 const formattedPrice = formatPrice(item.price); // 每次都重新計算
105 return <div>{formattedPrice}</div>;
106}
107
108// 優化後
109const CartItem = React.memo(({ item }) => {
110 const formattedPrice = useMemo(
111 () => formatPrice(item.price),
112 [item.price]
113 );
114 return <div>{formattedPrice}</div>;
115});
116```
117
118### 虛擬捲動(50+ 商品時)
119```typescript
120import { FixedSizeList } from 'react-window';
121
122function CartDrawer({ items }) {
123 if (items.length > 20) {
124 return (
125 <FixedSizeList
126 height={600}
127 itemCount={items.length}
128 itemSize={80}
129 >
130 {({ index, style }) => (
131 <CartItem style={style} item={items[index]} />
132 )}
133 </FixedSizeList>
134 );
135 }
136
137 return items.map(item => <CartItem key={item.id} item={item} />);
138}
139```
140
141### 預期結果
142- 渲染時間: 850ms → 250ms
143- 捲動 FPS: 30fps → 60fps ✓
144
145## 優化 4: API 回應壓縮 (預期改善 70% 傳輸)
146
147```typescript
148import compression from 'compression';
149
150app.use(compression({
151 level: 6,
152 threshold: 1024, // 只壓縮 > 1KB 的回應
153}));
154```
155
156### 預期結果
157- 回應大小: 150KB → 45KB
158- 傳輸時間: 200ms → 60ms (on 3G)
159
160## 總體預期改善
161
162| 指標 | 優化前 | 優化後 | 改善幅度 |
163|------|--------|--------|---------|
164| API P95 延遲 | 320ms | 50ms | 84% ↓ |
165| 前端載入時間 | 2.8s | 1.2s | 57% ↓ |
166| 資料傳輸量 | 150KB | 45KB | 70% ↓ |
167
168## 實作順序
169
1701. 資料庫索引(最快,影響最大)
1712. Redis 快取(中等工作量,效果顯著)
1723. API 壓縮(簡單,立即生效)
1734. 前端優化(需要較多測試)
174
175總時程估算: 2-3 天
176````
📋 工作流程最佳實踐總結
黃金原則
11. **先規劃,再實作**
2 • 使用 Plan Mode 設計架構
3 • 明確定義驗收標準
4 • 分階段執行
5
62. **持續測試和驗證**
7 • 每個階段都要測試
8 • 不要累積技術債
9 • 自動化測試流程
10
113. **文檔與程式碼同步更新**
12 • README 保持最新
13 • API 文檔即時更新
14 • 記錄重要決策
15
164. **監控和回饋循環**
17 • 部署後密切監控
18 • 收集使用者回饋
19 • 持續優化改進
20
215. **團隊協作**
22 • Code Review 機制
23 • 知識分享
24 • 統一的工作流程
檢查清單範本
1每個功能開發的標準流程:
2
3需求分析階段
4☐ 功能需求明確
5☐ 技術需求確定
6☐ 限制條件已識別
7☐ 驗收標準可測試
8
9設計規劃階段
10☐ 架構設計完成
11☐ 資料庫設計確認
12☐ API 設計審查
13☐ 任務分解清晰
14
15開發實作階段
16☐ 程式碼符合規範
17☐ 單元測試覆蓋
18☐ Code Review 通過
19☐ 文檔已更新
20
21測試驗證階段
22☐ 單元測試通過
23☐ 整合測試通過
24☐ E2E 測試通過
25☐ 效能測試達標
26
27部署上線階段
28☐ 部署檢查清單完成
29☐ Rollback 計畫就緒
30☐ 監控已設定
31☐ 團隊已通知
32
33維護優化階段
34☐ 監控指標正常
35☐ 問題及時修復
36☐ 效能持續優化
37☐ 使用者回饋收集
🚀 下一步行動
1立即行動
2☐ 為目前專案建立工作流程文檔
3☐ 設定 Claude Code 的專案模板
4☐ 建立常用的檢查清單
5☐ 與團隊分享工作流程
6
7持續改進
8☐ 定期回顧工作流程效率
9☐ 收集團隊回饋並調整
10☐ 記錄最佳實踐案例
11☐ 建立內部知識庫
延伸閱讀:
標籤: #claude-code #工作流程 #開發流程 #軟體開發 #最佳實踐 #敏捷開發
