軟體專案為什麼總是超出預期#

每個軟體工程師都有這樣的經驗:一個看起來很簡單的功能,實際做起來卻花了原本預估時間的三倍甚至十倍。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 天之間完成」

下次有人說「這個功能很簡單」的時候,試著花十分鐘把它拆解成細項。你會發現,光是列出所有需要考慮的邊界情況,就已經讓你對複雜度有了完全不同的認識。