TTechSpecs

Receiving Code Review Skill

Receiving Code Review 是 Superpowers 中的重要協作型 skills,專注於有效地處理程式碼審查的回饋,透過建設性的對話來改善程式碼品質和促進個人成長。

何時使用

在以下情況中使用 Receiving Code Review skill:

必須使用的情境

  • 收到程式碼審查的回饋意見
  • 需要回應審查者的建議
  • 對審查意見有不同意見需要討論
  • 需要解釋技術決策的理由
  • 處理 conflicting 的回饋意見

不適合的情境

  • 還沒有收到回饋
  • 只是單純感謝審查者(不需要特殊 skill)
  • 審查意見非常明確且直接實作即可

接收回饋的心態

1. 成長心態

將審查視為學習機會:

❌ 固定型心態:
「他們在挑我毛病」
「我的程式碼不夠好」
「為什麼要這樣麻煩」

✅ 成長型心態:
「這是改進的機會」
「我可以從中學習」
「團隊知識在分享」

2. 專業態度

保持專業和客觀:

原則:
- 對事不對人
- 焦點在程式碼,不在個人
- 接受建設性批評
- 感激審查者的時間投入

3. 主動參與

主動參與審查討論:

做法:
- 主動詢問不清楚的地方
- 分享你的技術考量
- 提出替代方案
- 記錄學到的經驗

處理回饋的流程

第 1 步:閱讀和理解

仔細閱讀所有回饋:

閱讀策略:
✓ 先全部瀏覽一遍,了解整體回饋
✓ 標記需要回應的意見
✓ 分類回饋類型(必須修正/建議改進/可選)
✓ 識別 conflicting 的意見
✓ 記錄需要學習的部分

第 2 步:分類和優先級

將回饋分類處理:

## 回饋分類

**必須修正(阻礙合併)**
- [ ] 安全問題:SQL 注入風險
- [ ] 功能問題:邊界條件未處理
- [ ] 測試問題:關鍵案例未覆蓋

**建議改進(建議採納)**
- [ ] 效能:可以快取查詢結果
- [ ] 可讀性:函式可以拆分
- [ ] 最佳實踐:使用 TypeScript utility types

**可選改進(下次處理)**
- [ ] 命名:變數名可以更清楚
- [ ] 格式:可以調整空格
- [ ] 文件:可以補充註解

**需要討論**
- [ ] 設計決策:為何選用 A 而非 B
- [ ] 技術取捨:複雜度 vs 彈性

第 3 步:回應回饋

系統化地回應每個意見:

接受並實作

@reviewer 感謝建議!

我已經修正:
- 使用 parameterized query 避免 SQL 注入
- 加入邊界條件檢查(empty string、null)
- 補充相關測試案例

請再次審查,謝謝!

討論不同意見

@reviewer 關於使用 Redux 的建議:

我理解 Redux 的優勢,但這次選擇 Context API 是基於:

**考慮因素**
1. **簡單性**:狀態結構相對簡單,Context 已足夠
2. **學習曲線**:團隊對 Context 較熟悉
3. **依賴**:減少第三方依賴
4. **效能**:這個應用不需要高度優化

**未來考慮**
如果狀態變得更複雜,我們可以考慮遷移到 Zustand(比 Redux 更輕量)

你的看法如何?是否有我沒考慮到的因素?

解釋技術決策

@reviewer 為什麼使用 async/await 而非 Promise chains:

**選擇理由**
- 可讀性更佳:程式碼更像同步程式碼
- 錯誤處理更簡單:try-catch 比 .catch() 更直觀
- 除錯更容易:stack trace 更清楚

**對照範例**
```typescript
// Promise chains
fetchData()
  .then(data => processData(data))
  .then(result => saveResult(result))
  .catch(err => handleError(err));

// async/await
try {
  const data = await fetchData();
  const result = await processData(data);
  await saveResult(result);
} catch (err) {
  handleError(err);
}

這個選擇符合我們專案的最佳實踐指南。


#### 標記下次處理

```markdown
@reviewer 好建議!

我同意重構這個函式,但為了保持這個 PR 的範圍可控,我建議:
- 這次 PR:保持現有實作,確保功能正確
- 下次 PR:專注重構這個函式

已經建立追蹤 issue #456,會在下個 sprint 處理。

這樣安排可以嗎?

第 4 步:實作修改

系統化地實作修改:

實作策略:
1. 從「必須修正」開始
2. 處理「建議改進」中有價值的部分
3. 記錄「可選改進」供未來參考
4. 在實作中學習和成長

實際範例

範例 1:處理安全性回饋

審查者意見

@user 第 85 行有 SQL 注入風險:

\`\`\`typescript
const query = `SELECT * FROM users WHERE id = ${userId}`;
\`\`\`

建議使用 parameterized query。

好的回應

@reviewer 感謝發現!這是個重要的安全性問題。

我已經修正:

\`\`\`typescript
// 修正前(有風險)
const query = `SELECT * FROM users WHERE id = ${userId}`;

// 修正後(安全)
const query = `SELECT * FROM users WHERE id = $1`;
await db.query(query, [userId]);
\`\`\`

並且已經:
- ✓ 更新所有類似的查詢
- ✓ 加入安全查詢的測試案例
- ✓ 更新開發指南提醒團隊

請再次審查,謝謝指出這個問題!🙏

範例 2:處理設計分歧

審查者意見

關於這個錯誤處理設計,我認為應該 throw error 而非 return error object。

Throw error 讓錯誤處理更一致,也符合函式語言的 best practice。

回應並討論

@reviewer 這是個好觀點!讓我分享我的考量:

**Return error object 的理由**
1. **明確性**:函式簽章清楚表明可能失敗
   \`\`\`typescript
   function fetchData(): Promise<Result<Data, Error>>
   \`\`\`

2. **型別安全**:強制處理錯誤情況
   \`\`\`typescript
   const result = await fetchData();
   if (result.isErr()) {
     // 型別系統會強制處理
   }
   \`\`\`

3. **Go 風格**:團隊比較熟悉這個模式

**Throw error 的優勢**
- ✓ 更符合 JavaScript/TypeScript 慣例
- ✓ 與生態系統的 try-catch 整合更好
- ✓ 程式碼更簡潔

**我的建議**
這個模組我們可以嘗試 throw error,看看實際使用體驗如何?
如果效果好,我們可以在團隊中推廣這個模式。

你想看看兩種方式的完整對照範例嗎?

範例 3:處理多個審查者意見

情境:兩個審查者給出不同的建議

審查者 A

建議使用 Redux 來管理狀態

審查者 B

建議使用 MobX,更簡單易用

回應

@reviewer-a @reviewer-b 感謝兩位的建議!

我收到關於狀態管理的不同建議:
- Reviewer A:建議 Redux
- Reviewer B:建議 MobX

讓我先分享當前的需求和約束:

**需求**
- 管理使用者 session 和設定
- 狀態結構相對簡單(2-3 層)
- 團隊需要快速上手的方案

**約束**
- 時間:本週內需要完成
- 學習曲線:團隊對這兩個都不熟悉
- 專案大小:中小型應用

**我的提議**
考慮使用 Context API + useReducer:
- ✓ 無需額外依賴
- ✓ 團隊比較熟悉
- ✓ 對我們的使用案例已經足夠
- ✓ 未來可遷移到 Redux(如果需要)

**如果需要更強大的解決方案**
我們可以安排一個技術討論會,比較 Redux 和 MobX 的 pros/cons,
然後決定哪個更適合我們的長期需求。

你們覺得這個方案如何?

常見回饋類型

1. 命名相關

回饋:「變數名稱不清楚」

回應方式:
- 接受:「同意,已改名為更清楚的名稱」
- 討論:「我選擇這個名稱是因為...你覺得如何?」
- 解釋:「這是專案的命名慣例,參考其他檔案...」

2. 結構相關

回饋:「函式太長,應該拆分」

回應方式:
- 接受:「同意,已拆分為三個小函式」
- 討論:「我考慮過拆分,但因為...這次保持原樣」
- 提問:「你建議如何拆分?可以給個範例嗎?」

3. 效能相關

回饋:「這個查詢可以優化」

回應方式:
- 接受:「好建議!已經加上索引和優化」
- 討論:「我測試過,目前效能已足夠,但未來可以優化」
- 請求:「可以分享你測試的效能數據嗎?我想學習」

4. 測試相關

回饋:「缺少錯誤情況的測試」

回應方式:
- 接受:「補充了錯誤情況的測試」
- 討論:「我認為這個案例不需要測試,因為...」
- 提問:「你認為應該測試哪些錯誤情況?」

建設性對話技巧

1. 肯定和感謝

✓ 好的回應:
「感謝詳細的審查!」
「這個建議很有幫助!」
「我從中學到很多!」

✗ 避免的回應:
「我知道這樣」(防衛性)
「這只是一個小問題」(輕視)
「你不懂」(攻擊性)

2. 具體回應

✓ 好的回應:
「第 45 行已經修正,現在檢查 null 情況」

✗ 不夠具體:
「已修正」(沒說明修正了什麼)

3. 解釋理由

✓ 好的回應:
「我選擇這個方式是因為...(理由),你覺得如何?」

✗ 不夠說明:
「這樣就可以」(沒有解釋為什麼)

4. 主動請教

✓ 好的回應:
「你有這方面的經驗嗎?我想學習你的做法」

✗ 錯過機會:
「好的,我會改」(沒有深入討論)

回饋處理最佳實踐

1. 及時回應

建議回應時間:
- 收到回饋後 24 小時內
- 如果需要時間:預估並告知
- 如果延遲:說明原因和新的時間表

2. 系統化追蹤

使用專案管理工具追蹤:

待處理:
- [ ] 修正安全性問題(高優先)
- [ ] 重構函式 A(中優先)
- [ ] 補充測試(中優先)
- [ ] 改進命名(低優先)

已處理:
- [x] 修正 SQL 注入風險
- [x] 加入錯誤處理
- [x] 更新文件

3. 記錄學習

將學到的經驗記錄下來:

## 從這次 PR 學到的經驗

1. **安全性**:永遠使用 parameterized query
2. **可讀性**:複雜邏輯應該拆分為小函式
3. **測試**:不要忘記測試錯誤情況
4. **文件**:複雜邏輯需要註解說明

未來注意:
- ✅ 寫程式碼時就考慮這些點
- ✅ 在自審時檢查這些項目

4. 建立關係

與審查者建立良好關係:

做法:
- 真誠感謝他們的時間
- 主動分享你學到的
- 提供幫助作為回報
- 建立互相學習的文化

與其他 Skills 組合

推薦組合

Requesting + Receiving Code Review

requesting-code-review → receiving-code-review

完整的程式碼審查流程

Receiving Code Review + Verification

receiving-code-review → verification-before-completion

處理回饋後再次驗證

常見問題

Q1:不同意審查意見怎麼辦?

A

  1. 先理解對方的觀點和理由
  2. 分享你的技術考量
  3. 提供具體的利弊分析
  4. 保持開放態度,準備好被說服
  5. 如果仍有分歧,可以請第三者意見

Q2:回饋太多怎麼辦?

A

  1. 分類並優先處理
  2. 與審查者討論優先級
  3. 考慮拆分為多個小的 PR
  4. 標記「下次處理」的項目
  5. 保持溝通,管理期望

Q3:審查者不友善怎麼辦?

A

  1. 保持專業態度
  2. 專注在程式碼,不在個人
  3. 私下溝通解誤會
  4. 如果持續不友善,尋求管理者協助

Receiving Code Review 是成長的機會,以開放的心態接受回饋,你會持續進步!