[![hackmd-github-sync-badge](https://hackmd.io/x_3WupbVTBi6qNjVmo0USg/badge)](https://hackmd.io/x_3WupbVTBi6qNjVmo0USg) ###### tags: `2023鐵人賽` `qiita` `agile` `產品開發` # [2023 15th鐵人賽] Day22 - 程式設計最難的部分我認為是「估算成本」 > 原文連結:[プログラミングで一番難しいのは「見積もり」だと思う - Qiita](https://qiita.com/yuno_miyako/items/8678cd542fbb7050e40e) 在進行程式開發之前,通常會需要經歷更重要的「工時評估」。實際在開發時,也經常會被 PM 問到「這功能需要多久時間?這個 BUG 多久可以修好?」等情況,一開始可能會不知道該如何做評估,或不小心給出太長或太短的工時。 然而,這項能力是必須練習的,一方面與「成本估算」有關,另一方面也是「自我保護」,透過動態的修正,使估算工時的過程更加準確。 以下正文開始。 --- [toc] ## 前言 在程式設計中,我認為最難的部分之一就是「**估算成本**」。每當收到程式設計的需求時,第一個問題總是「**大概要花多長時間完成?**」。在嚴格的情況下,可能會問「幾天能夠交付?」(不如說這或許是常態)。面對全新的案子,通常會藉由過去的所有經驗,來預測所需時間,盡可能將任務分解並估算時間,卻或許總是感到不安。應該有許多人對估算成本感到困難與不安,希望透過這篇文章,分享自己對估算相關的知識和經驗。 「估算」一詞具有多重含義,但本文中想表達的是「**估算從開始到產品發布所需的時間**」到「**估算完成特定功能所需的時間**」這個範疇的估算。 ## 為什麼需要估算? 之所以需要進行估算,理由有許多個。 其中一個是為了**投資判斷**。需要計算開發該產品或功能所需的金錢成本,並判斷是否能夠獲得相應的價值,因此必須估算時間。如果回答是「我不知道需要多長時間,直到完成為止」,那根本無法開始開發。 此外,如果能夠事先知道時間,也能確定該何時開始準備市場行銷活動,或是否應該增加人力資源。如果不知道需要多長時間和成本,則無法制定其他計劃。出於這些重要原因,我們必須能夠**對自己的工作進行估算**。 ## 為什麼估算很困難 為什麼估算如此困難呢?原因在於,有太多的**不確定性**。 - 對於從未嘗試過的工作,無法知道需要多少時間 - 可能會出現**意料之外的任務** - 不知道**學習**使用的框架或技術**需要多長時間** - 可能會遇到**困難點被卡住** - 不知道發現和修復**錯誤**需要多長時間 - 在團隊開發中,無法知道其他人的開發速度,也不知道**自己將負責什麼** 應該還有各種原因。事實上,**很少有人能在一開始就完全理解即將開發的目標**。估算是一個充滿不確定性的過程,因此讓人感到卻步,然而估算仍是必要的過程,不得不去執行。 ### 造成估算困難的因素 雖然上述提到,由於存在太多不確定性,使得估算變得困難。即使如此,透過將任務分解,動用過去的知識,建立現實性的假設,仍然能夠進行估算。然而,還有另一個使估算變得更困難的因素。 這個因素是「**估算的日期即為截止日期**」。 如果對上司說出「可能需要一個星期完成」,那即使到星期五晚上,也必須加班到深夜以確保完成。假如有截止日期,那麼無論如何都必須在該期限內完成。 基於這個原因,即使估算大約需要一個星期的時間,也不能輕易說出「可以在一個星期內完成」。 由於存在高度的不確定性,我們無法得出「**一個星期即可完成**」的結論。估算只能得出「**一個星期完成的可能性最高,但可能存在 50~200% 幅度的差異**」。 因此我認為,**實際估算的情況和追求的估算結果(截止日期)之間的差異**,是造成估算困難的原因。 ## 估算方法 估算的困難性,源自於不確定性和認知不一致,面對這些問題,該如何抱持誠實的心態來應對呢? 首先介紹應對不確定性的方法,這是在敏捷開發中使用的「故事點數和速度」估算方法。 ### 故事點數與速度 #### Story Point 故事點數 由於任務存在不確定性,很難做出絕對性的評估。因此,**使用相對評估來進行估算**,即為故事點數。 若將工作 A 估算為 5 點時,可能需要花兩倍時間的工作 B,則會被估算為 10 點。不到工作 B 的難度,但比工作 A 困難的工作 C,則可能被估算為 7 點。差不多是這樣的概念。 人們普遍認為,**相對評估比絕對評估更準確**。要估算遠處建築物的高度很困難,但如果是估算相對於隔壁的小建築物會大多少倍,則任何人都能做到。 透過分配點數給已識別的任務,最後總點數即為該產品或功能完成的估計值。 #### Velocity 速度 光是擁有故事點數這些數字,並不具有實際意義。估算的目的,是為了做出決策或用於其他計劃,因此必須將其轉換為「**時間**」。 速度是實現這一點的關鍵。 實際執行任務,並測量每一點所需的時間。 假設估算一個功能開發,需要的故事點數共 80 點,而完成一個 8 點的任務需要 1 天,即可推測功能開發需要 10 天的時間。 #### [Burn down chart 燒盡圖](https://zh.wikipedia.org/zh-tw/%E7%87%83%E5%B0%BD%E5%9B%BE) 將「總故事點數」、「已完成的故事點數」和「剩餘的故事點數」,按照時間順序繪製成折線圖,即稱為**燒盡圖**。 在順利進行的專案中,剩餘點數將形成一條向下的斜線,當該斜線延伸到 x 軸時,代表專案預計完成日期。 在確認或共享進度時,透過將資訊可視化,能夠一目瞭然的燒盡圖非常重要。 ### 兼顧不確定性的估算 上述提到估算變得困難的原因,是「估算結果」變成「截止日期」。 考慮到估算可能成為「截止日期」,為了自我保護,可能會犧牲估算的準確性,以提供過多的緩衝時間。即使認為一個工作需要 1 周完成,為了安全起見,可能會說需要 2 周,但這樣真的是誠實的回答嗎? 改變傳達方式也是一種方法。 與其說出「完成需要 2 周的時間」,不如傳達「估計整體完成需要 4 至 10 天。預計前 3 天可能完成這些進度。」並共享燒盡圖以確認當前進度。我認為這種方式,能更確實傳達確切的資訊,並承認估算的不確定性。更重要的是,**估算應該時常進行修正**。在專案初期,認知到估算充滿不確定性,並隨著知識的累積**重新進行估算**,即可與決策者共享更精確的估算結果。 #### 重新估算 當一個任務估計需要 2 天,最終卻耗時 3 天的情況,我們經常會思考「**為什麼沒有按照預期的進行?**」。接下來的任務,為了趕上進度表,我們會付出更多的「**努力**」。當進度不如時間表的預期時,為提升速度付出的「努力」,通常會付出更大的代價。因為時間緊迫,將導致產出不穩定的程式碼,即使發現錯誤也可能被忽略,或即使想出有價值的功能,也可能被忽視。 但我們並不想做這樣的「努力」。如此一來,我們反而應該思考「**為什麼把需要費時 2 天的任務錯估為 3 天?**」。修改當初的估算,根據這次花費比預計多 1.5 倍時間的任務,**將與其類似的任務的故事點數乘以 1.5 倍重新估算**。透過修正的步驟,能夠**使估算更加準確**。 ## 最後 在這次分享中,介紹對於估計的觀念,以及在敏捷開發中使用的故事點數估計方法。 當然,實際情況會因讀者所處環境而有所差異,本文提到的方法和思維方式,可能也不適用於所有情況,希望能提供作為參考。