2018-10-04 難以估計(jì)的工作量

本篇,讓我們嘗試用科學(xué)的方法進(jìn)行一些討論,為什么工作量往往難以估計(jì),為一個(gè)Delay的項(xiàng)目加人通常是下策,為什么重構(gòu)有用,以及為什么好的設(shè)計(jì)至關(guān)重要。

定性分析

研發(fā)效率 R 隨著代碼量 C 的增長(zhǎng)而遞減
-- John Adhoc

定量分析

研發(fā)效率本身是難以度量的,但為了討論起見(jiàn),我們不妨定義幾個(gè)變量,并試著加以討論。

  • C 當(dāng)前的代碼總量,業(yè)界通常以行數(shù)計(jì)。
    注:此處不考慮不同編程語(yǔ)言的差異,假設(shè)有統(tǒng)一的語(yǔ)言(PHP除外)
  • Ce 當(dāng)前的有效代碼總量,指實(shí)際產(chǎn)生價(jià)值的有效代碼。

打個(gè)形象的比方,C 好比一袋薯片,包裝完好,膨脹十足。 Ce 好比打開(kāi)了包裝,瞬間泄氣,發(fā)現(xiàn)包裝里一半是空氣,其真正有效的薯片總量遠(yuǎn)遠(yuǎn)少于包裝給你的預(yù)期。之所以嚴(yán)格區(qū)分, CCe,本質(zhì)就在于通常人們直接見(jiàn)到的工作量由C 決定,那就像人月神話一文中提及的,碼農(nóng)的工作產(chǎn)出其實(shí)是非線性的,即真實(shí)的勞動(dòng)價(jià)值無(wú)法用直接觀測(cè)可得的C決定。

由此,我們可以定義研發(fā)效率函數(shù) R = d(Ce) / d(C) ,即假設(shè) Ce 是相對(duì)于 C 的函數(shù),則 R 對(duì)應(yīng)其導(dǎo)函數(shù),基于我們的定性假設(shè),R 是一個(gè) 減函數(shù),即隨著C的增加,研發(fā)效率是遞減的。

  • Rc 表示當(dāng)前代碼規(guī)模 C 下的生產(chǎn)效率,即在當(dāng)前規(guī)模下,每增長(zhǎng)單位代碼行數(shù),所能實(shí)際產(chǎn)生的有效代碼行數(shù)。

舉例來(lái)說(shuō),假設(shè)以10000行代碼為基本生產(chǎn)單位。下表是一個(gè)具體的例子(注意到研發(fā)效率隨代碼規(guī)模增加而遞減),假設(shè) R = 10000 / (10000 + C) 的情況(這是一個(gè)假設(shè),實(shí)際中,也較難衡量R函數(shù)的實(shí)際曲線,在此我們使用一個(gè)雙曲線函數(shù)來(lái)估計(jì),從筆者的經(jīng)驗(yàn)來(lái)看,這不妨是一種可能合理的近似):

C Ce 當(dāng)前研發(fā)效率:Rc 每再增加10000行代碼能獲得的有效代碼
0 0 10000 / (10000 + 0) = 1.0 10000 * 1.0 = 10000
10000 10000 10000 / (10000 + 10000) = 0.5 10000 * 0.5 = 5000
20000 15000 10000 / (10000 + 20000) = 0.33 10000 * 0.33 = 3300
30000 18300 10000 / (10000 + 30000) = 0.25 10000 * 0.25 = 2500
40000 20800 10000 / (10000 + 40000) = 0.2 10000 * 0.2 = 2000

提升研發(fā)效率的方法

我們換個(gè)思路,將上表的最后一列置換成:增加10000行 有效代碼 所需要的代碼量:

C Ce Rc 在當(dāng)前規(guī)模下,增加10000行 有效代碼 所需要新增的代碼量
0 0 1.0 10000
10000 10000 0.5 ~30000
40000 20800 0.25 ~70000

我們注意到一個(gè)算不上驚人的事實(shí),假設(shè)一個(gè)碼農(nóng)的生產(chǎn)力為 10000行代碼 / 月,注意到在項(xiàng)目初期,代碼規(guī)模較小的情況下,完成10000行有效代碼的工作時(shí)間為 10000 / 10000 = 1 人月。 之后再增加10000行有效代碼,工作時(shí)間為 30000 / 10000 = 3 人月。 突然暴增3倍。 進(jìn)一步,如果在此基礎(chǔ)上,再增加10000行有效代碼, 則需要工作時(shí)間為7人月,幾乎一定會(huì)導(dǎo)致項(xiàng)目Delay。

在現(xiàn)實(shí)生活中,我們把每10000行代碼視作產(chǎn)品的一個(gè)新增功能。 則對(duì)應(yīng)每增加一個(gè)新增功能,對(duì)應(yīng)的工作量遠(yuǎn)遠(yuǎn)超出直覺(jué)(項(xiàng)目經(jīng)理/項(xiàng)目經(jīng)理的預(yù)期)。 造成這一困擾的主要原因只有一個(gè),即 R 隨著 C 增長(zhǎng)而下降。

避免這一困境(項(xiàng)目要延期)的方案:

  1. Ce 不變的情況下,減少當(dāng)前的 C ,這相當(dāng)于間接提升 R
  2. 提升 R
  3. 提升 C 的增加速度

對(duì)應(yīng)現(xiàn)實(shí),方案1通常意味著功能回歸情況下,代碼重構(gòu),清除冗余。 方案2通常意味著架構(gòu)變更,模塊解耦,使得開(kāi)發(fā)能夠并行。方案3,意味著加人,但相對(duì)而言是性價(jià)比較低的策略。顯然,1,2是上策。 3是下策。如果非要選擇3,建議和1,2中的某一個(gè)選擇并行。

為什么重構(gòu)是必要的

勞動(dòng)人民在田間勞作,每年收獲農(nóng)作物。土地也需要恢復(fù),肥力會(huì)下降。所以有經(jīng)驗(yàn)的農(nóng)民往往會(huì)交叉種植不同的農(nóng)作物,并適當(dāng)修養(yǎng)土地,才能保證來(lái)年更好的收成。在業(yè)界,這一現(xiàn)象,叫做重構(gòu)。

C Ce 當(dāng)前研發(fā)效率:Rc 每再增加10000行代碼能獲得的有效代碼
0 0 10000 / (10000 + 0) = 1.0 10000 * 1.0 = 10000
10000 10000 10000 / (10000 + 10000) = 0.5 10000 * 0.5 = 5000
20000 15000 10000 / (10000 + 20000) = 0.33 10000 * 0.33 = 3300
30000 18300 10000 / (10000 + 30000) = 0.25 10000 * 0.25 = 2500
40000 20800 10000 / (10000 + 40000) = 0.2 10000 * 0.2 = 2000
40000 22800 0.20 此時(shí)選擇重構(gòu),縮小代碼規(guī)模至 23000,生產(chǎn)效率恢復(fù)到0.30
40000 22800 0.30 3000 (如果不重構(gòu),則為2000, 提升50%效率)

上表展示了重構(gòu)造成的差異,本質(zhì)上是通過(guò)減少代碼規(guī)模,使得研發(fā)效率函數(shù)右移(對(duì)應(yīng)的是效率回到了之前小規(guī)模代碼的程度)。 定量的計(jì)算,使得重構(gòu)的價(jià)值可以被衡量,注意,在日常工作中,經(jīng)理們往往不容易被碼農(nóng)的經(jīng)驗(yàn)直接說(shuō)服,通過(guò)一些看似“科學(xué)”的計(jì)算方式,可能更容易爭(zhēng)取到空間,這背后的動(dòng)機(jī)我們放到之后的章節(jié)中再討論。

由此表也可以看出,重構(gòu)的時(shí)間是非常關(guān)鍵的,在不同的 C 規(guī)模下,選擇重構(gòu),對(duì)應(yīng)的生產(chǎn)效率的提升百分比差異是相當(dāng)大的(有興趣的讀者可以自己計(jì)算,在表格不同行選擇重構(gòu)意味著什么)。

最后,請(qǐng)注意這里討論的假設(shè):

  • 重構(gòu)總是順利的(事實(shí)上總不是),將代碼規(guī)模下降其實(shí)是一件遠(yuǎn)比增加代碼困難得多的事情。
  • 重構(gòu)其實(shí)是需要代價(jià)的,這就是研發(fā)需要平衡的,即重構(gòu)需要的工作量和帶來(lái)的生產(chǎn)效率的比較,上表中,50%的效率提升,如果對(duì)應(yīng)重構(gòu)需要的工作量?jī)H為3人天,則顯然是劃算的,反之,如果對(duì)應(yīng)重構(gòu)的工作量就需要1人月,則不如將這1人月繼續(xù)投入到水深火熱的勞作中去,帶來(lái)的收益更大(即重構(gòu)可以推遲)

為什么設(shè)計(jì)如此重要

最后強(qiáng)調(diào)一下設(shè)計(jì)的重要性。

設(shè)計(jì)的本質(zhì),就是降低系統(tǒng)協(xié)作的復(fù)雜性。
好的設(shè)計(jì),可以使得 研發(fā)效率曲線 R 下降的更慢。這是設(shè)計(jì)好壞的有且唯一的評(píng)價(jià)指標(biāo)。
-- John Adhoc

再舉例來(lái)說(shuō),假設(shè)以10000行代碼為基本生產(chǎn)單位。下表是一個(gè)具體的例子(注意到研發(fā)效率隨代碼規(guī)模增加而遞減),假設(shè) R = 10000 / (10000 + C / 2) 。(這次我們聘請(qǐng)了經(jīng)驗(yàn)豐富的設(shè)計(jì)師,做了充分且有效的架構(gòu)設(shè)計(jì),使得研發(fā)效率下降變慢)

C Ce 當(dāng)前研發(fā)效率:Rc 每再增加10000行代碼能獲得的有效代碼
0 0 10000 / (10000 + 0) = 1.0 10000 * 1.0 = 10000
10000 10000 10000 / (10000 + 10000 / 2) = 0.67 10000 * 0.67 = 6700
20000 16700 10000 / (10000 + 20000 / 2) = 0.5 10000 * 0.5 = 5000
30000 21700 10000 / (10000 + 30000 / 2) = 0.4 10000 * 0.4 = 4000
40000 25700 10000 / (10000 + 40000 / 2) = 0.33 10000 * 0.33 = 3300
50000 29000 10000 / ( 10000 + 50000 / 2) = 0.28 10000 * 0.28 = 2800
60000 31800 注意到,之前完成30000行有效代碼,需要花費(fèi)110000行代碼,現(xiàn)在僅需要 60000行,效率提升接近1倍

從上表可以看到,僅僅是修正研發(fā)效率曲線 R , 從 R = 10000 / (10000 + C) => R = 10000 / (10000 + C / 2),即使得研發(fā)效率在生產(chǎn)30000行有效代碼時(shí),提升接近100%(有興趣的讀者可以繼續(xù)計(jì)算,越往后差異越大)。 這就是 設(shè)計(jì)的力量

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容