軟體專案為什麼總是超出預期#
每個軟體工程師都有這樣的經驗:一個看起來很簡單的功能,實際做起來卻花了原本預估時間的三倍甚至十倍。Joel 在這篇文章中解釋了為什麼軟體開發的複雜度幾乎總是被低估。
隱藏的複雜度#
一個功能在被提出時,通常只描述了「正常路徑」(happy path)。但真正的工作量藏在所有你一開始沒想到的地方:
邊界情況(Edge Cases)#
- 使用者輸入了空白?輸入了超長的字串?輸入了特殊字元?
- 網路突然斷線怎麼辦?磁碟空間滿了怎麼辦?
- 兩個使用者同時修改同一筆資料會發生什麼事?
- 時區轉換、日光節約時間、閏年——每一個都是潛在的陷阱
錯誤處理#
正常路徑的程式碼可能只佔整體的 20%,剩下的 80% 都是在處理各種可能出錯的情況。每一個錯誤情境都需要被妥善處理:顯示有意義的錯誤訊息、記錄日誌、嘗試恢復、或者優雅地失敗。
使用者介面的細節#
- 按鈕在不同狀態下的外觀和行為
- 載入中的指示器
- 操作成功或失敗的回饋
- 鍵盤快捷鍵、無障礙設計(accessibility)
- 不同螢幕尺寸和解析度的適配
「這個功能很簡單,大概一天就能做完」——這句話幾乎是軟體工程中最危險的一句話。它忽略了所有隱藏的複雜度,為專案埋下了延遲的種子。
「完成 90%」的陷阱#
軟體開發中有一個著名的現象:前 90% 的工作佔了 90% 的時間,剩下的 10% 又佔了另一個 90% 的時間。
這不是笑話,而是真實的體驗。當你覺得一個功能「基本完成了」,你通常只做完了正常路徑。接下來還有:
- 測試和修復 bug
- 處理邊界情況
- 效能優化
- 文件撰寫
- 與其他功能的整合測試
- 使用者回饋後的調整
這些「收尾」工作往往和「主要開發」花一樣多的時間。
所謂「完成 90%」的功能,在實際可交付的意義上,可能只完成了 50% 甚至更少。這就是為什麼軟體專案的進度報告經常讓人產生錯覺。
如何做出更準確的估算#
Joel 提出的解決方案是:將工作拆解成非常小的任務。
- 粒度要夠細:每個任務不超過幾個小時。如果一個任務的估算超過一天,就代表你還沒有想清楚它包含了什麼
- 列出所有子任務:不只是「實作功能 X」,而是把它拆成「設計 UI」、「實作 API」、「處理錯誤情況」、「撰寫測試」、「整合測試」等多個獨立的子項目
- 加上緩衝時間:即使你把所有能想到的任務都列出來了,仍然會有你沒想到的事情。為意外預留時間不是悲觀,而是務實
估算的實務技巧
Joel 在 Fog Creek 使用的 Evidence-Based Scheduling 方法的核心概念:
- 追蹤每個工程師的歷史估算準確度
- 用歷史數據來校正未來的估算
- 接受估算本質上是一個機率分佈,而不是一個確定的數字
- 最終產出的不是「這個專案會在 X 天完成」,而是「有 80% 的機率在 X 到 Y 天之間完成」
下次有人說「這個功能很簡單」的時候,試著花十分鐘把它拆解成細項。你會發現,光是列出所有需要考慮的邊界情況,就已經讓你對複雜度有了完全不同的認識。