# 從需求定義者到程式碼實作者:一個 PM 轉職工程師的 TDD 與 EDD 領悟 ![開發者困惑於AI測試](https://hackmd.io/_uploads/Hk9XEbOpgl.jpg) 三年前的我,坐在 Sprint Planning 會議上,看著工程師 Kevin 說他需要兩天時間來「重構購物車邏輯並補完測試案例」。 我當時心裡 OS:「這功能不是上個月才做好嗎?為什麼要重構?而且補測試要兩天?直接改程式碼不就好了?」 Kevin 看出我的疑惑,解釋說:「沒有測試的程式碼就像沒有地基的房子,改一個地方可能整棟垮掉。」 我點點頭,但心裡還是覺得工程師太龜毛。 直到那個專案出包的那天。 ## 那個讓我決定轉職的 Bug 那是一個看似簡單的需求:把折扣計算邏輯從「滿千折百」改成「滿五百折五十」。 我寫了清楚的需求文件,開了 Jira ticket,設定優先級為 P1。工程師說「這很簡單,一個下午就好」。 結果上線當天,客服電話被打爆。 不是因為新的折扣邏輯有問題,而是修改折扣計算的時候,不小心動到了會員等級判斷的部分。結果所有 VIP 會員都無法享受專屬折扣,系統把他們當成一般會員處理。 我看著工程師 debug 到凌晨三點,突然想起 Kevin 說的那句話:「沒有測試的程式碼就像沒有地基的房子。」 那個晚上,我做了一個決定:我要學寫程式。 不是要轉職當工程師,只是想理解「為什麼改一個邏輯會影響到其他功能」、「為什麼測試這麼重要」。 結果越學越深,半年後,我真的遞出了轉職申請。 ## 從 PRD 到 Test Case:我的第一次頓悟 轉職後的第一個月,技術主管丟給我一本書:《Test Driven Development: By Example》。 「先從 TDD 開始學,」他說,「這會幫你建立正確的思維模式。」 我翻開書,看到第一個範例是寫一個計算器。作者說要「先寫測試,再寫程式碼」。 我心想:這不就是我以前寫需求文件的邏輯嗎? **以前當 PM 寫的 User Story**: ``` As a 使用者 I want to 輸入兩個數字並選擇加法 So that 系統能顯示正確的計算結果 Acceptance Criteria: - Given 使用者輸入 2 和 3 - When 選擇加法 - Then 系統顯示 5 ``` **現在當工程師寫的 Test Case**: ```python def test_addition(): calculator = Calculator() result = calculator.add(2, 3) assert result == 5 ``` 欸,這根本是同一件事啊! 只是 PM 用自然語言寫,工程師用程式碼寫而已。 那個瞬間我突然理解了 TDD 的精髓:**先定義「完成」的標準,再去實作功能**。這不就是我做了三年的產品管理嗎? 我開始瘋狂練習 TDD。每次寫功能前,我都會先想:「如果我是 PM,我會怎麼寫這個驗收標準?」然後把它轉成測試案例。 **Red(紅燈)** = 需求還沒實現 **Green(綠燈)** = 功能符合驗收標準 **Refactor(重構)** = 在不改變需求的前提下優化實作 這個循環跟敏捷開發的節奏完美契合。 我甚至開始覺得,PM 轉工程師搞不好是優勢。因為我太習慣「先定義完成標準」這件事了,TDD 對我來說根本是直覺反應。 直到我接到第一個 AI 相關的需求。 ## 無法定義的「驗收標準」 公司決定在客服系統加入 AI 問答功能。技術主管知道我以前是 PM,就把需求分析的工作也交給我。 我打開熟悉的 Notion,開始寫需求文件: ```markdown ## User Story As a 客戶 I want to 向 AI 客服詢問退貨流程 So that 我能快速了解如何退貨 ## Acceptance Criteria - Given 使用者輸入「如何退貨?」 - When 系統呼叫 AI 模型 - Then 系統回答「請在收到商品 7 天內...」 ``` 寫到這裡,我卡住了。 AI 的回答每次都不一樣。有時候它會說「收貨後七日內」,有時候說「7 天內」,有時候還會加上「記得保持商品完整喔」這種額外資訊。 我該怎麼寫 Acceptance Criteria? 以前當 PM 的時候,如果規格不明確,我會跟設計師或工程師討論,直到我們對「完成」有共識為止。但現在,我面對的是一個 LLM,它的輸出本質上就是不確定的。 我試著寫測試: ```python def test_ai_customer_service(): bot = AICustomerService() response = bot.answer("如何退貨?") assert response == "請在收到商品 7 天內,保持商品完整,透過官網申請退貨。" ``` 執行測試。紅燈。 我調整提示詞,再執行。還是紅燈。 但 AI 的回答明明是對的啊!只是用字不同而已。 我突然理解為什麼有些工程師會說「AI 應用很難測試」了。這不是技術問題,是**我們無法用傳統的『二元判斷』來評估 AI 的輸出**。 作為 PM,我最怕的就是「需求不明確」。但現在,我遇到的是「無法明確定義驗收標準」的情況。 這比需求不明確還要慘。 ## PM 思維的反擊:從 KPI 到評估指標 那天晚上,我翻出以前當 PM 時做的 OKR 文件。 我記得當時公司要衡量「客服品質」,我設計了一套評估指標: - 首次回應時間 < 30 秒 - 問題解決率 > 85% - 客戶滿意度 > 4.0/5.0 - 平均對話輪數 < 5 等等,這不就是多維度評估嗎? 我沒有說「客服必須說『您好,我是客服專員 Alice,很高興為您服務』這句話」,而是定義了**好的客服應該符合的標準**。 這跟 AI 的情況很像啊! 我不需要規定 AI 一定要回答什麼,我只需要定義「好的回答應該符合哪些標準」。 我開始重新設計測試策略: ```python class AIResponseEvaluator: """用 PM 思維設計的 AI 評估器""" def evaluate(self, question, answer, reference_answer): """ 多維度評估 AI 回答品質 就像評估 KPI 一樣 """ scores = {} # KPI 1: 資訊準確性(類似業務指標) scores['accuracy'] = self._check_key_points( answer, required_keywords=["7 天", "完整", "申請"] ) # KPI 2: 資訊完整性(類似覆蓋率指標) scores['completeness'] = self._compare_with_reference( answer, reference_answer ) # KPI 3: 用戶體驗(類似滿意度指標) scores['user_experience'] = self._evaluate_tone( answer, expected_tone="friendly_and_professional" ) # KPI 4: 效率指標(類似回應時間) scores['conciseness'] = self._check_word_count( answer, max_words=80 ) # 加權計算(就像 OKR 的權重設計) total_score = ( scores['accuracy'] * 0.4 + scores['completeness'] * 0.3 + scores['user_experience'] * 0.2 + scores['conciseness'] * 0.1 ) return { 'total_score': total_score, 'breakdown': scores, 'passed': total_score >= 0.8 # 80 分門檻 } ``` 這個設計讓我想起以前在 Google Analytics 設定轉換目標的邏輯。 你不會說「使用者一定要點擊這個按鈕」,而是定義「成功的使用者旅程應該包含哪些關鍵步驟」。 我開始用這套邏輯設計測試: ```python def test_ai_response_quality(): """不測試確切內容,而是測試品質指標""" bot = AICustomerService() evaluator = AIResponseEvaluator() # 測試案例 1:退貨政策 response = bot.answer("如何退貨?") result = evaluator.evaluate( question="如何退貨?", answer=response, reference_answer="請在收到商品 7 天內,保持商品完整,透過官網申請退貨。" ) assert result['passed'], f"品質評分 {result['total_score']:.2f} 低於門檻" assert result['breakdown']['accuracy'] > 0.7, "關鍵資訊缺失" # 測試案例 2:運費計算 response = bot.answer("運費怎麼算?") result = evaluator.evaluate( question="運費怎麼算?", answer=response, reference_answer="單筆訂單滿 1000 元免運,未滿收取 80 元運費。" ) assert result['passed'], f"品質評分 {result['total_score']:.2f} 低於門檻" ``` 第一次執行,平均分數 72 分。不及格。 我分析了低分案例,發現 AI 常常: 1. 回答太冗長(沒有遵守簡潔性原則) 2. 缺少具體數字(準確性不足) 3. 語氣太正式或太口語化(用戶體驗不穩定) 這就跟我以前做 PM 時分析產品指標一樣。找出問題,優化,再測試。 我調整了提示詞: ```python system_prompt_v2 = """你是電商客服 AI,請遵循以下規範: 【資訊要求】 - 必須包含具體數字(天數、金額、百分比) - 必須包含操作步驟 【語氣要求】 - 友善但專業 - 使用「您」而非「你」 - 適度使用表情符號增加親和力 【格式要求】 - 控制在 50 字以內 - 重點使用條列式 - 先講結論再講細節 """ ``` 重新評估,平均分數跳到 89 分。 那個瞬間,我突然意識到:**我不是在寫測試,我是在設計產品的品質標準**。這跟我以前制定 PRD 裡的 Success Metrics 根本是同一件事。 後來我才知道,這套方法有個名字:**Evaluation-Driven Development(評估驅動開發)**,簡稱 EDD。 ![TDD與EDD對比](https://hackmd.io/_uploads/SyuVN-uaxe.jpg) ## 兩個世界的融合 現在回想起來,我的 PM 背景反而成了優勢。 **傳統工程師學 TDD** → 要改變「先寫程式碼再測試」的習慣 **PM 轉職工程師學 TDD** → 只是把「寫驗收標準」換成「寫測試案例」 **傳統工程師遇到 AI** → 困惑於無法寫確定性測試 **PM 轉職工程師遇到 AI** → 直覺套用「多維度評估指標」的思維 我開始理解為什麼 IBM 和 Microsoft 的研究顯示,採用 TDD 的專案缺陷率能降低 40-90%。因為 TDD 的本質就是**強迫你在寫程式前先想清楚「完成」的定義**。 這不就是 PM 每天在做的事嗎? 而 EDD 則是**把評估標準從二元判斷擴展到多維度量化**。這也是 PM 在設計 OKR 和 KPI 時的日常。 現在我的專案裡,TDD 和 EDD 和平共存: **TDD 部分**(確定性邏輯): ```python def test_calculate_shipping_fee(): """測試運費計算邏輯(確定性)""" order = Order(total=800) assert order.calculate_shipping() == 80 order = Order(total=1200) assert order.calculate_shipping() == 0 ``` **EDD 部分**(AI 生成內容): ```python def test_ai_recommendation_quality(): """測試 AI 推薦品質(多維度評估)""" recommender = AIRecommender() evaluator = RecommendationEvaluator() products = recommender.suggest_for_user(user_id=123) score = evaluator.evaluate( recommendations=products, metrics=['relevance', 'diversity', 'novelty'] ) assert score['overall'] >= 0.85 assert score['relevance'] >= 0.9 # 相關性要特別高 ``` 這兩種方法不是對立的,而是互補的。就像 PM 和工程師不是對立的,而是互補的一樣。 ## PM 轉 Coder 的獨特優勢 這一年多的轉職經驗,讓我發現 PM 背景帶來的幾個優勢: ### 1. 對「為什麼」的執著 工程師容易陷入「怎麼做」的細節,但 PM 訓練讓我總是先問「為什麼要做」。 寫測試時,我不會機械性地覆蓋所有分支,而是先問: - 這個功能的核心價值是什麼? - 用戶最在意的是哪個部分? - 什麼情況下的失敗會造成最大損失? 這讓我的測試更聚焦在關鍵路徑上。 ### 2. 對用戶體驗的敏感度 設計 AI 評估指標時,很多工程師會糾結於技術指標(如 BLEU score、ROUGE score)。 但我會問:「用戶真的在乎這個嗎?」 所以我設計的評估指標通常包含: - 回答是否解決了用戶的問題(任務完成率) - 用戶是否需要追問(對話效率) - 用戶是否感到被尊重(情感體驗) 這些都是從產品角度出發的指標。 ### 3. 對 Trade-off 的理解 PM 最常做的就是優先級排序和取捨。 這讓我在設計評估指標時,不會追求「完美」,而是追求「適合當前階段的好」。 例如,MVP 階段我可能只測試核心功能的準確性;產品成熟後才加入語氣、簡潔度等細緻指標。 ### 4. 文檔化的習慣 PM 出身的我,註解和 README 寫得特別詳細。 這在團隊協作時特別有用,新人看我的測試案例,就能理解這個功能要達成什麼目的。 ```python def test_refund_eligibility(): """ 測試退款資格判斷邏輯 Business Context: - 根據 2024 Q1 客訴分析,退款糾紛主要來自「收貨時間」認定 - 此測試確保系統正確計算 7 天鑑賞期 Edge Cases: - 假日不計入鑑賞期 - 預購商品從實際收貨日起算 Related: - Jira: PROD-1234 - Policy Doc: https://... """ # 測試程式碼... ``` ## 給其他想轉職的 PM 的建議 如果你也在考慮從 PM 轉工程師,我想分享幾個心得: ### 你的 PM 經驗不會白費 很多人轉職時會擔心「過去的經驗都用不上」。其實不是。 你學過的需求分析、用戶研究、指標設計,都能在工程實踐中派上用場。特別是在設計測試策略和評估指標時,PM 思維是巨大優勢。 ### 從 TDD 開始學比較容易 因為 TDD 的思維模式跟寫 User Story 很像,PM 轉職者通常能很快上手。 這會給你信心,讓你覺得「我可以做好工程師的工作」。 ### 不要丟掉產品思維 有些轉職者會矯枉過正,刻意壓抑產品思維,只想「當個純粹的工程師」。 但其實,懂產品的工程師在團隊裡非常稀缺。保留你的產品敏感度,這會讓你成為「能獨立思考的工程師」而不只是「執行需求的碼農」。 ### AI 時代對 PM 背景更友善 隨著 AI 應用越來越多,「如何評估 AI 的品質」成為新的挑戰。 這正是 PM 最擅長的:**定義成功標準、設計評估指標、量化產品價值**。 所以如果你正在猶豫,這可能是最好的轉職時機。 ## 工具推薦(實戰驗證過的) ### TDD 工具 **Python 生態**: ```bash pip install pytest pytest-cov pytest-mock faker ``` - `pytest`:測試框架,語法簡潔 - `pytest-cov`:程式碼覆蓋率報告 - `pytest-mock`:Mock 外部依賴 - `faker`:生成測試資料(省得自己想) **學習資源**: - 《Test Driven Development: By Example》- Kent Beck(TDD 之父) - 線上課程:Test-Driven Development 101 (Udemy) ### EDD 工具 **Promptfoo**(我目前主力): ```bash npm install -g promptfoo ``` 簡單的配置檔案就能跑批次評估: ```yaml prompts: - file://prompts/customer_service_v1.txt - file://prompts/customer_service_v2.txt providers: - openai:gpt-4 tests: - vars: question: "如何退貨?" assert: - type: contains value: "7 天" - type: javascript value: output.length < 200 # 簡潔性 - type: llm-rubric value: "回答是否友善且專業" ``` 執行評估: ```bash promptfoo eval ``` **其他值得關注的工具**: - **LangSmith**:適合 LangChain 生態系統 - **DeepEval**:輕量級,適合快速驗證 - **Weights & Biases**:如果你需要追蹤模型訓練過程 ## 寫在最後:從定義需求到定義品質 轉職這一年多,我最大的收穫不是學會了 Python 或 JavaScript,而是理解了**開發方法論的本質**。 TDD 教我:**在動手之前先想清楚目標**。 EDD 教我:**用多維度的標準取代二元的判斷**。 但其實,這些都是我當 PM 時就在做的事。 當 PM 時,我定義「什麼是成功的產品」。 當工程師時,我定義「什麼是合格的程式碼」。 形式不同,本質相同。 所以如果你也是 PM,正在考慮轉職,不用太擔心。你已經具備了很多工程思維,只是用不同的語言表達而已。 而如果你是工程師,我建議你花點時間理解 PM 的思維方式。特別是在 AI 時代,「如何定義品質」這件事,產品經理的經驗可能比傳統工程師更有幫助。 兩個世界的融合,或許能創造出更好的開發方法。 就像 TDD 和 EDD 的融合一樣。 --- ## 延伸資源 **關於 TDD**: - IBM/Microsoft 研究:TDD 降低 40-90% 缺陷率 - Martin Fowler 的 TDD 實踐文章 - Uncle Bob 的 Clean Code 系列 **關於 EDD**: - arXiv 論文:《Challenges in Testing Large Language Model Based Applications》 - Medium 系列:《Evaluation-Driven Development for Agentic Applications》 - Promptfoo 官方文件:https://promptfoo.dev/ **關於 PM 轉職**: - 《The Pragmatic Programmer》(實用主義程式設計師) - 《Refactoring》(重構:改善既有程式的設計) - Coding Interview University (GitHub) **社群資源**: - r/cscareerquestions(Reddit) - Blind(匿名職場社群) - TDD Practitioners(LinkedIn Group) --- **關於作者** 一個從產品經理轉職工程師的學習者。曾經以為寫程式和寫需求文件是兩回事,後來發現它們都在回答同一個問題:「什麼是好的?」 現在的我,白天用 Python 寫程式,晚上用 Notion 整理筆記,周末會懷念開 Sprint Planning 的日子。 如果你也在轉職路上,歡迎留言交流。我們都是路上的同伴。 --- **留言討論** 你是 PM 轉職工程師嗎?或是工程師想轉 PM? 你覺得兩種角色最大的差異是什麼? 在 AI 開發上,你遇到了哪些挑戰? 歡迎在下方留言分享你的經驗。 --- **標籤**:#PM轉職 #工程師 #TDD #EDD #測試驅動開發 #評估驅動開發 #AI開發 #職涯轉換 #產品經理