cover

接續 需求到開發準備,現在進入寫 code 的階段。

先講結論

開發階段最容易出的問題不是「寫不出來」,而是寫到一半才發現需求沒對齊、測試沒寫、commit 亂七八糟。Phase 4(開發)和 Phase 5(Code Review)是品質的最後防線。

Phase 4:開發——最長也最危險的階段

有了 API Spec,前後端可以平行開發。平行開發的前提是:雙方都信任 Spec,Spec 變了要同步通知

寫測試,不是選修

不管你信不信 TDD,至少要寫 unit test。以 Google 登入為例:

describe('GoogleAuthService', () => {
  it('should create new user when email not found', async () => {
    const mockGoogleUser = { email: 'new@gmail.com', name: 'New User' };
    googleApiMock.getUserInfo.mockResolvedValue(mockGoogleUser);
    userRepo.findByEmail.mockResolvedValue(null);
 
    const result = await service.authenticateWithGoogle('auth-code-123');
 
    expect(userRepo.create).toHaveBeenCalledWith(
      expect.objectContaining({ email: 'new@gmail.com' })
    );
    expect(result.isNewUser).toBe(true);
  });
 
  it('should link to existing user when email matches', async () => {
    const existingUser = { id: 'user-1', email: 'exists@gmail.com' };
    userRepo.findByEmail.mockResolvedValue(existingUser);
    const result = await service.authenticateWithGoogle('auth-code-456');
    expect(result.isNewUser).toBe(false);
  });
 
  it('should throw when Google returns no email', async () => {
    googleApiMock.getUserInfo.mockResolvedValue({ email: null });
    await expect(service.authenticateWithGoogle('code'))
      .rejects.toThrow(AuthenticationError);
  });
 
  it('should handle Google API timeout gracefully', async () => {
    googleApiMock.getUserInfo.mockRejectedValue(new TimeoutError());
    await expect(service.authenticateWithGoogle('code'))
      .rejects.toThrow(ExternalServiceError);
  });
});

注意看:不只測 happy path,還測了 email 不存在、Google API timeout。你不測的邊界,使用者會幫你「測」——在 production 上。

測試策略見 測試策略。記住 Test Pyramid:unit 多、integration 適量、E2E 少但關鍵路徑必須覆蓋。

Commit 規範不是潔癖

feat(auth): add Google OAuth login endpoint
feat(auth): implement account linking by email match
test(auth): add unit tests for Google OAuth flow
fix(auth): handle edge case when Google returns no email

好的 commit 紀錄是未來 debug 和 review 的線索。Conventional Commits 規範見 CommitLint

Phase 5:Code Review——PR 不是寫完丟上去就好

一個好的 PR 不是把 code 丟上去寫 please review

PR 該有的結構

## Summary
Google OAuth 2.0 登入:後端 API + 前端元件 + 帳號自動綁定。
 
## 設計決策
- Token 放 HttpOnly Cookie(防 XSS)
- 帳號綁定用 email match,衝突時要求手動確認
- OAuth state 用 crypto.randomUUID(),防 CSRF
 
## 測試
- [x] Unit: 12 tests passing
- [x] Integration: 3 tests passing (mock Google)
- [x] Manual: 截圖如下

Reviewer 該看什麼

你以為 review 就是看有沒有 bug?不夠。好的 reviewer 看三層:

架構層:方向對嗎?有沒有更好的設計?新 dependency 合理嗎?

邏輯層:邊界條件有沒有處理?錯誤處理完整嗎?商業邏輯對嗎?

細節層:命名清不清楚、格式一不一致。但老實說這層應該交給 ESLint

關鍵問題:

  • OAuth state parameter 有做 CSRF 防護嗎?
  • Google API 掛了怎麼辦?Token 過期怎麼辦?
  • 同一個 Google 帳號綁定兩個系統帳號怎麼處理?
  • 未來加 Apple / GitHub 登入時,現在的架構好擴展嗎?

Code Review 的完整方法論見 Code Review 方法論


下一篇:CD 部署到上線後營運——按下 Deploy 之後才是真正的開始。