
一個功能從需求到上線:完整走讀
流程概覽
flowchart LR A[需求釐清] --> B[技術設計] B --> C[開發準備] C --> D[開發] D --> E[Code Review] E --> F[CI/CD 部署] F --> G[上線後營運] style A fill:#4CAF50,color:#fff style B fill:#2196F3,color:#fff style C fill:#FF9800,color:#fff style D fill:#9C27B0,color:#fff style E fill:#F44336,color:#fff style F fill:#009688,color:#fff style G fill:#607D8B,color:#fff
文章概覽
在本篇文章中,您將學習到:
- 一個功能從 PM 提出到上線 Production,到底經歷了哪些階段
- 每個階段的輸入、輸出、負責角色是什麼
- 如何把這個系列(方法論、Infra、DevOps、Git)的文章串起來使用
- 一張完整的 Mermaid 流程圖,視覺化整個生命週期
- 功能上線前的最終 Checklist
我們會用一個具體的功能——「使用者可以用 Google 帳號登入」——作為貫穿全文的案例。每個階段都會拿這個功能來示範,讓你看到理論是怎麼落地的。
引言:為什麼需要這篇文章?
這個方法論系列已經寫了十篇,涵蓋系統規劃、API 設計、測試策略、事故管理、Proto 規劃、Release 流程等等。但這些文章各自獨立,讀者可能會問:這些東西到底在什麼時間點、以什麼順序被使用?
這篇文章的目的,就是把所有環節串成一條線。你可以把它想成是這個系列的「導覽地圖」——跟著一個功能走一遍,你就知道每篇文章在整個開發流程中的位置。
我們的主角功能:
作為一個使用者,我想要用 Google 帳號登入,以便不用記另一組帳號密碼。
看起來很簡單對吧?但從 PM 腦中的一句話,到使用者真的能在 Production 上按下那個「Sign in with Google」按鈕,中間要經歷的事情比你想像的多。
讓我們開始走讀。
Phase 1:需求釐清
在這個階段,你要做的事:確認「我們到底要做什麼」,交付一份需求文件(PRD)。
PM 在某次會議上說:「我們要讓使用者可以用 Google 帳號登入。」
工程師聽到這句話,第一反應不應該是打開 IDE 開始寫 code。而是要問一系列問題:
1.1 工程師該問的問題
| 問題 | 為什麼要問 |
|---|---|
| 只支援 Google 嗎?還是未來要加 Apple、GitHub? | 影響架構設計。如果未來要擴展,現在就該用通用的 OAuth 抽象層 |
| 已有帳號的使用者用 Google 登入,要自動綁定嗎? | 帳號合併邏輯是個大坑,不先釐清會爆炸 |
| Google 登入失敗時,使用者看到什麼? | UX 層面必須定義 |
| 有沒有時程壓力? | 決定是先做 MVP 還是一次到位 |
| 需要支援哪些平台?Web only?還是 App 也要? | 技術實作完全不同 |
這些問題不是在刁難 PM,而是在幫整個團隊省下後續的重工時間。
1.2 需求文件(PRD)長什麼樣
一份最小可用的 PRD 應該包含:背景說明、User Story、範圍定義、驗收標準(Acceptance Criteria)。以我們的 Google 登入為例:
## PRD: Google 帳號登入
### 背景
目前系統只支援 Email + 密碼登入。用戶研究顯示 40% 的使用者
在註冊流程中放棄,主因是「不想再記一組帳密」。
### User Story
- 作為新使用者,我想用 Google 帳號一鍵註冊 + 登入
- 作為舊使用者,我想綁定 Google 帳號,下次直接用 Google 登入
- 作為管理員,我要能在後台看到哪些使用者用 Google 登入
### 範圍定義
- In Scope: Google OAuth 2.0 登入、帳號自動綁定(以 email 比對)、解除綁定
- Out of Scope: Apple / GitHub 登入(Phase 2)、變更 Google 帳號的 email
### Acceptance Criteria
1. 使用者點擊「Sign in with Google」按鈕,完成授權後自動登入系統
2. 如果系統已有相同 email 的帳號,自動綁定,不建新帳號
3. 使用者可以在設定頁解除 Google 綁定
4. Google API 不可用時,顯示友善的錯誤訊息,不影響其他登入方式
5. 登入流程全程 < 3 秒(不含 Google 授權頁面)想了解更完整的需求收集方法,請參考 好產品的定義。一個好的需求文件,就是在強迫所有人對「做什麼」和「不做什麼」達成共識。
Phase 2:技術設計
在這個階段,你要做的事:決定「怎麼做」,交付一份技術設計文件(Technical Spec)。
需求確認了,接下來是工程師的主場。
2.1 架構決策
Google 登入的技術選項其實不多,核心是 OAuth 2.0 Authorization Code Flow。
先看完整的 OAuth 2.0 Authorization Code Flow:
sequenceDiagram participant U as 使用者 participant F as Frontend participant B as Backend participant G as Google U->>F: 點擊 Sign in with Google F->>G: 導向 Google OAuth Consent G->>U: 顯示授權頁面 U->>G: 同意授權 G->>F: Redirect + Authorization Code F->>B: POST /api/auth/google {code} B->>G: 用 code 換 access_token G->>B: 回傳 access_token + user info B->>B: 查找/建立使用者、簽發 JWT B->>F: Set-Cookie: token (HttpOnly) F->>U: 登入成功,跳轉首頁
幾個關鍵決策點:
| 決策 | 選擇 | 理由 |
|---|---|---|
| Token 格式 | JWT(Access Token + Refresh Token) | Stateless,適合分散式架構 |
| Token 存放位置 | HttpOnly Cookie | 防 XSS |
| OAuth Library | 後端用 Google 官方 SDK | 不自己造輪子 |
| 帳號綁定策略 | Email match 自動綁定 | PRD 要求,需要處理衝突情境 |
2.2 API 設計
根據 RESTful 最佳實踐(詳見 API 設計與認證機制),我們需要以下 endpoint:
POST /api/auth/google # 用 authorization code 換 JWT
POST /api/auth/google/link # 已登入使用者綁定 Google 帳號
DELETE /api/auth/google/link # 解除 Google 帳號綁定
GET /api/auth/me # 取得當前使用者資訊(含綁定狀態)
API Spec 要寫進 OpenAPI 文件,前後端依此對齊。這不是可選的,這是必須的——前後端同時開發的前提,就是有一份雙方都同意的合約。
關於系統規劃的更完整方法論,請參考 系統規劃方法論。
Phase 3:開發準備
在這個階段,你要做的事:準備好開發環境和分支,確保團隊可以平行開發。
3.1 專案初始化
如果這是一個全新專案,你應該從 Proto clone 出來,而不是從零開始(詳見 Proto 規劃)。Proto 已經幫你處理好:
- 專案結構與資料夾規範
- ESLint / Prettier / EditorConfig
- Docker + docker-compose
- CI/CD Pipeline 骨架
- 環境變數管理(
.env.example) - 錯誤處理與 Log 格式
- 測試框架設定
如果是既有專案加新功能(我們的 Google 登入案例更可能是這種),那就跳到分支策略。
3.2 分支策略
根據團隊的 Git Flow 規範(詳見 Git Flow),開一個 feature branch:
git checkout develop
git pull origin develop
git checkout -b feature/google-oauth分支命名規範:feature/<功能名稱>。不要用 feat-1234 這種只有你自己看得懂的名字。
3.3 環境變數
Google OAuth 需要的環境變數,先加到 .env.example:
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
GOOGLE_REDIRECT_URI=http://localhost:3000/auth/google/callback注意:.env.example 只放 key,不放 value。實際的 secret 透過安全的方式(如 Vault、雲端 Secret Manager)分發,絕對不進 Git。
Phase 4:開發
在這個階段,你要做的事:寫 code、寫測試、保持好的 commit 紀律。
這是整個流程中最長的階段,也是最容易失控的階段。
4.1 前後端分工
有了 Phase 2 的 API Spec,前後端可以平行開發。平行開發的關鍵在於:雙方都信任 API Spec。如果 Spec 變了,要同步通知。
4.2 寫測試
不管你是不是 TDD 的信徒,至少要寫 unit test。
以我們的 Google 登入為例,後端至少要測這些:
// auth.service.spec.ts
describe('GoogleAuthService', () => {
describe('authenticateWithGoogle', () => {
it('should create new user when email not found', async () => {
// Arrange: mock Google API 回傳新 email
const mockGoogleUser = { email: 'new@gmail.com', name: 'New User' };
googleApiMock.getUserInfo.mockResolvedValue(mockGoogleUser);
userRepo.findByEmail.mockResolvedValue(null);
// Act
const result = await service.authenticateWithGoogle('auth-code-123');
// Assert
expect(userRepo.create).toHaveBeenCalledWith(
expect.objectContaining({ email: 'new@gmail.com' })
);
expect(result.token).toBeDefined();
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(userRepo.create).not.toHaveBeenCalled();
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);
});
});
});測試策略的完整方法論,請參考 測試策略。記住 Test Pyramid:unit test 多、integration test 適量、E2E test 少但關鍵路徑必須覆蓋。
4.3 Commit 規範
每個 commit 都應該遵循 Conventional Commits 規範(詳見 CommitLint):
feat(auth): add Google OAuth login endpoint
feat(auth): implement account linking by email match
feat(ui): add Google Sign-In button component
test(auth): add unit tests for Google OAuth flow
fix(auth): handle edge case when Google returns no email
好的 commit 紀錄不只是好看——它是未來 debug 和 code review 的重要線索。
Phase 5:Code Review
在這個階段,你要做的事:開 PR、接受 review、merge 進主線。
5.1 怎麼寫 PR
一個好的 PR 不是把所有 code 丟上去然後寫「please review」。它應該有明確的結構:
## Summary
實作 Google OAuth 2.0 登入功能,包含後端 API、前端元件、帳號自動綁定邏輯。
## 設計決策
- Token 存放在 HttpOnly Cookie(而不是 localStorage)以防止 XSS
- 帳號綁定採用 email match,當衝突時要求使用者手動確認
- OAuth state parameter 用 crypto.randomUUID() 生成,防 CSRF
## 測試清單
- [x] Unit Test: 12 tests passing (auth service + button component)
- [x] Integration Test: 3 tests passing (full OAuth flow with mock Google)
- [x] Manual Test: 截圖如下
## 相關連結
- PRD: [link]
- Tech Spec: [link]
- Figma: [link]5.2 Reviewer 看什麼
好的 reviewer 不只看 code 有沒有 bug,還會看:
| 面向 | 具體檢查項目 |
|---|---|
| 安全性 | OAuth state parameter 有沒有做 CSRF 防護?Token 有沒有設 expiry?Secret 有沒有 hardcode? |
| 錯誤處理 | Google API 掛了怎麼辦?Token 過期怎麼辦?網路 timeout 怎麼辦? |
| 邊界情境 | 同一個 Google 帳號綁定兩個系統帳號?Google 不回傳 email 的情境? |
| 效能 | JWT 有沒有放太多東西?每次 request 都打 Google API 驗證嗎? |
| 可維護性 | 未來加 Apple / GitHub 登入時,現在的架構好擴展嗎? |
| 測試覆蓋 | 關鍵路徑都有測到嗎?有沒有只測 happy path? |
Code Review 的完整方法論,未來會寫在 Code Review 方法論。
Phase 6:CI/CD 與部署
在這個階段,你要做的事:確保 Pipeline 全綠,部署到各環境。
6.1 Pipeline 跑什麼
PR merge 之後(或甚至在 PR 階段),CI/CD Pipeline 會自動執行:
flowchart LR L[Lint] --> UT[Unit Test] UT --> IT[Integration Test] IT --> B[Build] B --> DD[Deploy Dev] DD --> E2E[E2E Test] E2E --> DS[Deploy Staging] DS --> QA[Manual QA] QA --> DP[Deploy Production] style L fill:#FFD54F,color:#333 style UT fill:#81C784,color:#333 style IT fill:#64B5F6,color:#333 style B fill:#BA68C8,color:#fff style DD fill:#FF8A65,color:#333 style E2E fill:#4DB6AC,color:#333 style DS fill:#9575CD,color:#fff style QA fill:#F06292,color:#fff style DP fill:#E53935,color:#fff
每個步驟的具體內容:
| 步驟 | 做什麼 | 失敗的後果 |
|---|---|---|
| Lint | ESLint + Prettier 檢查 | 格式不一致、潛在錯誤 |
| Unit Test | 跑所有 unit test | 邏輯錯誤 |
| Integration Test | API 層級測試(含 DB) | 元件整合問題 |
| Build | 編譯 + 打包 | 編譯錯誤、依賴問題 |
| E2E Test | Playwright / Cypress 跑 | 使用者流程斷裂 |
| Deploy to Staging | 部署到預發環境 | 環境差異問題 |
| Manual QA | PM / QA 手動驗收 | UX 不符預期 |
CI/CD 的完整設計,請參考 CD。
6.2 環境分離
對 Google 登入來說,不同環境要用不同的 Google OAuth credentials:
| 環境 | Google Client ID | Redirect URI | 用途 |
|---|---|---|---|
| Dev | dev-client-id | http://localhost:3000/callback | 本地開發 |
| Staging | staging-client-id | https://staging.example.com/callback | QA 驗收 |
| Production | prod-client-id | https://example.com/callback | 正式環境 |
環境分離的完整策略,請參考 環境分離。
重點:絕對不要用 Production 的 Google credentials 來跑測試。
Phase 7:上線後
在這個階段,你要做的事:確認功能正常運作,準備好出事時的應對方案。
功能上線了,但工作還沒結束。上線才是真正的開始。
7.1 監控與告警
| 指標 | 正常值 | 告警閾值 | 說明 |
|---|---|---|---|
| Google OAuth 成功率 | > 95% | < 90% | 低於這個值代表 Google API 或我們的 callback 有問題 |
| 登入 API 回應時間(p99) | < 500ms | > 1000ms | OAuth flow 本身有網路延遲,但不應該太慢 |
| JWT 簽發失敗率 | 0% | > 0.1% | 任何簽發失敗都是嚴重問題 |
監控的完整建置方法,請參考 監控。
7.2 Log 追蹤
每一次 Google 登入,都應該留下可追蹤的 log。關鍵:每個 request 都要有 traceId,這樣當使用者回報問題時,你可以用這個 ID 把前端、後端、Google API 的整條路徑串起來。
一個好的登入 log 應該長這樣:
{
"timestamp": "2025-02-09T10:23:45.123Z",
"level": "info",
"traceId": "abc-123-def-456",
"event": "google_oauth_login",
"userId": "user_789",
"action": "account_linked",
"googleEmail": "user@gmail.com",
"isNewUser": false,
"latencyMs": 342,
"metadata": {
"provider": "google",
"clientVersion": "1.2.0",
"userAgent": "Mozilla/5.0..."
}
}這種 structured log 讓你可以輕鬆查詢:「過去一小時有多少登入失敗?」「這個使用者的登入路徑是什麼?」而不是在茫茫多的文字 log 裡撈針。
Log 管理的完整策略,請參考 Log 管理。
7.3 如果出事了
上線第二天,告警響了:Google 登入成功率從 97% 掉到 60%。
這時候就是事故管理流程登場的時候(詳見 事故管理):
- 確認影響範圍:只有 Google 登入受影響,還是整個登入系統都掛了?
- 檢查 Log:用 traceId 追蹤失敗的 request
- 快速判斷:是我們的 code 有 bug?是 Google API 在維護?是 SSL 憑證過期了?
- 應急處理:如果是我們的問題,考慮 rollback 到上一個版本
- Post-mortem:事後寫檢討報告,確保同樣的問題不會再發生
如果你有完善的 Debug 方法論,步驟 2 和 3 會快很多。系統化的除錯流程,讓你不會在恐慌中亂試。
完整流程圖
把上面七個階段串在一起:
flowchart TD subgraph Phase1["Phase 1:需求釐清"] A1[PM 提出需求] --> A2[工程師提問釐清] A2 --> A3[撰寫 PRD] A3 --> A4[團隊 Review PRD] end subgraph Phase2["Phase 2:技術設計"] B1[架構決策] --> B2[API Spec 設計] B2 --> B3[撰寫 Technical Spec] B3 --> B4[Tech Lead Review] end subgraph Phase3["Phase 3:開發準備"] C1[建立 Feature Branch] --> C2[設定環境變數] C2 --> C3[前後端確認 API 合約] end subgraph Phase4["Phase 4:開發"] D1[前後端平行開發] --> D2[撰寫 Unit Test] D2 --> D3[遵守 Commit 規範] end subgraph Phase5["Phase 5:Code Review"] E1[開 Pull Request] --> E2[Reviewer 檢查] E2 --> E3[修改 and Approve] E3 --> E4[Merge] end subgraph Phase6["Phase 6:CI/CD 部署"] F1[Pipeline 自動執行] --> F2[Deploy to Dev] F2 --> F3[Deploy to Staging] F3 --> F4[QA 驗收] F4 --> F5[Deploy to Production] end subgraph Phase7["Phase 7:上線後營運"] G1[監控指標] --> G2[Log 追蹤] G2 --> G3[告警機制] G3 --> G4[事故處理] end Phase1 --> Phase2 Phase2 --> Phase3 Phase3 --> Phase4 Phase4 --> Phase5 Phase5 --> Phase6 Phase6 --> Phase7
Checklist:功能上線前的最後確認
在你按下「Deploy to Production」之前,過一遍這個清單:
需求與設計
- PRD 已經過 PM 和工程師共同 review
- 所有 acceptance criteria 都有對應的測試
- Technical Spec 已經過 Tech Lead review
- API Spec 前後端已對齊,沒有歧義
程式碼品質
- 所有 unit test 通過
- Integration test 通過
- E2E test 覆蓋關鍵路徑(登入成功、登入失敗、取消授權)
- Code Review 已通過,無 blocker 等級的 comment
- 沒有 hardcoded secret 或 credential
- 錯誤處理覆蓋所有已知的邊界情境
CI/CD 與部署
- CI Pipeline 全綠(lint + test + build)
- Staging 環境已部署且 QA 通過
- 環境變數在 Production 已正確設定
- 資料庫 migration 已準備好(如果有的話)
- Rollback 計畫已確認(知道怎麼退版)
監控與運維
- 監控 Dashboard 已建好,關鍵指標有圖表
- 告警規則已設定(成功率、回應時間、錯誤率)
- Log 格式正確,包含 traceId
- Runbook 已更新
- On-call 工程師知道這個功能即將上線
溝通與文件
- Release Note 已撰寫
- 相關的內部文件已更新(API 文件、架構圖)
- PM / stakeholder 已通知上線時程
- 如果是 breaking change,下游團隊已同步
回顧:每個階段對應的文章
| Phase | 對應文章 | 核心觀念 |
|---|---|---|
| 需求釐清 | 好產品的定義 | 需求不只是功能列表,要定義「好」的標準 |
| 技術設計 | 系統規劃 | 結構化的設計流程,避免「邊做邊想」 |
| 技術設計 | API 設計 | RESTful 最佳實踐、OAuth、JWT |
| 開發準備 | Proto 規劃 | 不從零開始,用 Proto 加速 |
| 開發準備 | Git Flow | 分支策略決定團隊協作效率 |
| 開發 | 測試策略 | Test Pyramid,至少寫 unit test |
| 開發 | CommitLint | Commit 規範不是潔癖,是溝通工具 |
| Code Review | Code Review 方法論(即將推出) | Review 不只找 bug,更看設計與可維護性 |
| CI/CD 部署 | CD | 自動化是品質的保證 |
| CI/CD 部署 | 環境分離 | Dev / Staging / Production 各司其職 |
| 上線後 | 監控 | 沒有監控 = 瞎子開車 |
| 上線後 | Log 管理 | 出事時,Log 是你唯一的線索 |
| 上線後 | 事故管理 | 出事不可怕,沒有流程才可怕 |
| 上線後 | Debug 方法論 | 系統化除錯,不怕線上事故 |
| Release 流程 | Release 方法論 | Feature Freeze / QA / Staging / Production |
延伸閱讀
方法論系列
Infra 系列
DevOps 系列
Git 系列
結語
一個「使用者可以用 Google 帳號登入」的功能,從 PM 腦中的一個念頭,到使用者真的能在 Production 上按下那個按鈕,中間經歷了七個階段、牽涉到至少十幾篇文章中的知識。
這不是在說每個功能都要搞這麼大的陣仗。小功能可以壓縮流程,但每個階段的思考不能省略——需求要釐清、設計要思考、測試要寫、review 要做、部署要自動化、監控要到位。
差別只在於:小功能可能每個階段花五分鐘思考,大功能每個階段花一週。但流程是一樣的。
方法論不是枷鎖,是護欄。 它不會讓你走得更慢,它會讓你走得更穩。