淺談軟體專案規模估計——怎麼估?
做事所花費的時間總是比你預期的要長,即使你的預期中考慮了侯世達定律。
—— 侯世達,哥德爾、埃舍爾、巴赫
週三的下午,我像平常一樣,寫著程式碼聽著歌,突然從天而降一份莫名其妙的故事列表,說讓我給個人天,用來投標用。作為一個技術異常牛逼的高階程式設計師,這對我來說豈不是 A Piece Of Shit…哦不,Cake。拿著列表,打眼一看就知道是做什麼 — 又是個審批流系統。註冊、登入、忘記密碼…這些也需要時間?!哦,還要做個SSO,可能要做點資料整合,給個15人天吧!又是一堆CRUD… CRUD 各給2人天一共8個。看起來有4個 Model,乘個4,32個人天差不多。前端還有些工作量,找前端估一下…還有些跟遺留系統整合的部分,這塊應該比較麻煩,給個30人天差不多…還要用微服務架構,估計需要一些基礎環境,每個元件給3個人天,一共8個元件,算24吧….總共算起來130個開發人天,差不多,再加點buffer,算150吧!差不多了吧…
這一幕是不是有點眼熟?不過,這樣的做法可能會帶來下面的幾個問題:
1. 估計者的估計點數是否能代表團隊的估計點數?
問題的答案顯而易見。那麼有同學會說,此時團隊的人員還沒完成配置,沒辦法讓真實團隊進行功能的估計。確實是這個樣子,所以我們只能力所能及的去模擬真實團隊進行估計。一般,交付專案的團隊肯定不會全上非常有經驗的同學,人員配比一定會有 leverage,也就是 Senior 人員和 Junior 人員的比例。所以,在估計的過程中,至少要引入 Junior 的同事,能夠從不同經驗的角度來看待同樣的問題,來使估計不會過分“樂觀”。
2. 是否有故事卡片之外的工作時間沒有考慮到呢?
上文中的估計看起來是採用的經典的“理想人天”估計法,如果使用這樣的估計方法,勢必要考慮一些雖然沒有在故事卡工作量中,但也一定會花費時間的事務,包括但不限於:
- 回覆電子郵件(溝通成本)
- 面試(內部耗損)
- 參加會議(包括內部會議,比如站會、Retro、Code Diff、技術研討會議、客戶溝通會議等)
- 為當前釋出提供支援(上線支援)
- 培訓?(內部的 Session)
- 任務之間切換/被人打斷(程式設計師出棧入棧的消耗…)
- 修復bug(一定會有 Bug,一定會花時間修…)
- 寫各種文件(對於對文件比較看重的客戶,這一部分會佔用不少的時間)
這些事務會伴隨整個交付過程中發生,基本上都是正常交付必不可少的工作內容,而且根據筆者的經驗,這些事情佔據的時間並不比完成故事卡的編碼工作要少。
3. 故事卡的需求是否清晰呢?
在專案啟動前拿到的故事列表,往往只有 Epic 級別的,也就是很粗粒度的故事卡。故事卡中的 AC(Acceptance Criteria,驗收條件)往往只考慮了最簡單的 Happy Path,然而大部分專案中(尤其是 ToB專案),Exception 才是相對複雜的,這些異常情況往往需要花費更多的時間完成。在這種情況下進行估計,可想而知,一些隱藏的需求點往往難以發現。
問題可能的答案
那麼想要解決上面的問題,或者說更好一點的緩解上述問題的方案是什麼呢?《敏捷估計與規劃》中介紹了一些基本的方法。
首先,要進行集體估計
集體估計可以緩解因為個人能力不同所引發的單點偏差,不同的開發成員對於某個需求在不同角度的闡述,也容易讓大家對需求有更全面的理解,也易於發現潛藏在需求中的風險。闡述的過程中,出現複雜問題時,可以及時聯絡相應的專家資源。對於一些規模較大的卡片,也可以綜合大家的意見,進行更合理的拆解。同時,需要由要做次工作的人來進行估計,這樣會產生更多的責任感,可以在一定程度上緩解樂觀估計的問題(Lederer and Prasad 1992)。
其次,是方法
《敏捷估計與規劃》介紹了2種基本的方法:理想人天法和故事點法。
1. 理想人天法
理想人天法就是直接把故事卡估計成理想人天。所謂理想人天,就是“在需求非常明確的情況下,進行編碼、測試工作所花費的時間”。就好像籃球比賽一樣,每節12分鐘,4節總共48分鐘,這是比賽的理想時間。但是誰都知道,一般NBA每場比賽都要2個半小時左右,比賽激烈的話三個小時都有可能,比賽真正持續的時間與理想時間是有較大差距的。相比於籃球比賽,軟體專案“場外”的工作就更多了,除了上面問題2列出的那些實務之外,像是方案變更引發的大量溝通、整合聯調、測試過程中的需求講解、專案的交接等等,這些工作也需要算到專案時間之內。同時,對於同一個專案,不同的人根據其能力、經驗的不同,會有不同的理想人天。
所以在估計完理想人天之後,如何進行實際人天的換算,在實際應用中,仍然是個大問題,所以…最好就不要用了。
2. 故事點法
故事點法就是按照故事卡的規模和難度,給予每張故事卡一個點數。注意,這裡的點數代表的不是所需的人天,而更多的是難度係數。
開發人員因為自己技能、經驗、能力的不同,解決同樣的問題,所花的時間差別是很大的,但對規模的估計卻是一樣的。就好比從北京到上海,坐飛機1個多小時,高鐵5個小時,步行要…一個月左右吧,距離是一樣的,根據不同的速度,會花費不同的時間。
同時,人們一般很難對一個規模進行準確的估計,比如從北京到上海的絕對距離是多少,估計沒幾個人知道。但是,人們能夠比較容易的比較兩件事物的差距或者說倍數關係,比如:北京到上海的距離跟從上海到香港的距離是差不多的,這個距離是北京到鄭州距離的兩倍。所以我們在做估計的時候,可以按照難度係數分成幾波,然後在內部在進行一些比較和排序,然後按照比較的差距分配一個規模點數,比如1、2、3、5、8、13。
大家可以看到,這個規模點數並不是連續的數字,而是採用了菲波那切這一個神奇的數列。這樣的數列有2個好處,一個是不會出現連續的倍數關係,比如4點的故事卡片是2點故事卡片的2倍;其次是表明出規模越大的卡片,其不確定性也承遞增趨勢,所以會給更高的點數。
有了故事點數,我們仍然無法判定專案什麼時間能夠交付,因為缺少一個“速度”,也就是團隊的開發速度。如果面對的是一個成熟的團隊,並且使用類似的技術棧,且與客戶的合作模式基本相同的話,那麼可以參考前一個專案的速度,來進行交付時間的計算。但如果面對的是全新的客戶、不同的技術棧,以及完全重新配置的團隊,那麼速度基本是不可估的。這時候,有時候會根據 Tech Lead 和 PM 的(Pai)經(Nao)驗(Dai),進行硬估:把每個點數轉化成N個人天。比如1個點數需要2個人天,那麼100個點數的專案就是200個人天。當然,這種方法…說多了會掉淚。
最後,給專案加些緩衝(Buffer)
一般來說,面對這種情況,本著對客戶和我們自己負責的態度,需要給專案加一些緩衝區(Buffer)。Buffer 分兩種,一種是功能Buffer,一種是進度 Buffer。
功能緩衝
增加功能 Buffer,簡單來說,就是把全部的故事列表進行估計,假設得到總點數是100點;然後按照優先順序進行排序,挑出其中的MVP,要少於總量的 70%,作為必須要做(Must Have)的部分。剩下的 30% 作為做了更好、不做也不影響主要功能(Nice To Have)的部分,通過這種方式來緩衝專案里程碑的風險。
進度緩衝
進度 Buffer,是用來緩衝估計之外的異常情況引發的專案時間的拉長。進度 Buffer 根據專案的不確定性的差異,計算的方法和結果會有較大差異,有興趣可以參考《敏捷規劃與估計》,這裡就不贅述了。不過根據 Leach(2000)準則提出的建議,至少要保持整個專案的20%以上,否則也許不能為整個專案提供足夠的保護。
不是總結的總結
上面的這些方法能一定程度的規避風險,給開發團隊帶來一定的空間,但過分的強調估計和交付計劃的準確性,會帶來更深層級的問題:
- output over outcome。客戶更關注功能列表的完成,而不是產生的業務價值。
- 開發團隊會傾向於裁剪使用者故事的功能,3個點的故事卡,儘量控制在規定時間內完成,即使可以花更多時間把事情做的更好。
- 控制需求變更。可以進行需求變更,但這個過程更像是一個異常的情況,而不是喜聞樂見的。
- 當我們發現了更好的業務點、idea時候,會傾向於隱瞞,以免額外的業務功能會增加工作量。需求變更往往會涉及客戶談判的事情,尤其是當客戶觀念是傳統的供應商管理策略:我來控制需求的全景,能多做點就多做點。
- 在客戶合作和談判的天平上,客戶關係會向談判的方向傾斜。
估計和計劃會使團隊和客戶更多的聚焦在工作量,而不是工作的價值上。如果能夠引導客戶從 output 導向的思維轉變到 outcome 導向上,那麼團隊就不用再疲於奔命的完成那些並不會用到的feature上,而是可以有更多的時間去提升產品質量,進一步提升業務價值。
文/ThoughtWorks張久坤