|
我們?cè)龅竭^(guò)最后期限即將到來(lái)、時(shí)間非常緊迫的情況。當(dāng)時(shí),我們必須盡快修復(fù)Bug,然而其中的一個(gè)Bug特別堅(jiān)韌,任我們百般努力也無(wú)可奈何!隨后,我的某個(gè)同事接手了調(diào)試工作。他強(qiáng)行寫入了一些應(yīng)該從數(shù)據(jù)庫(kù)中檢索來(lái)獲取的值——它們?cè)谙到y(tǒng)運(yùn)營(yíng)的最初幾個(gè)月里不會(huì)發(fā)生變化——隨后……系統(tǒng)神奇地正常工作了!
對(duì)于這類“莫名其妙的代碼”,我的這位同事以非常風(fēng)趣的埃及俚語(yǔ)稱之為“Habya’a”,意即臨時(shí)拼湊的組件。
我同事和他的創(chuàng)造性俚語(yǔ)相仿,Ward Cunningham在1992年把這種糟糕的代碼稱之為“技術(shù)債務(wù)”——在Wiki百科上對(duì)技術(shù)債務(wù)的定義是“在判定某項(xiàng)任務(wù)完成之前,需要先完成的工作”,而Steve McConnell將技術(shù)債務(wù)定義為“一種設(shè)計(jì)或構(gòu)建的方法,它是一種短期內(nèi)的權(quán)宜之計(jì)——因?yàn)樗鼤?huì)產(chǎn)生這樣的一種技術(shù)環(huán)境:與現(xiàn)在動(dòng)手完成相比,稍后完成同樣的工作需要更高的投入。”
如果從實(shí)用主義的角度來(lái)看待技術(shù)債務(wù),我們會(huì)發(fā)現(xiàn)實(shí)際上它并不總是件壞事。當(dāng)截止日期已過(guò)的時(shí)候,技術(shù)債務(wù)就相當(dāng)于為了交付而付出的“高速公路的過(guò)路費(fèi)”。我的另一個(gè)朋友曾經(jīng)這樣對(duì)我說(shuō)“技術(shù)債務(wù)就像在沒(méi)有停車區(qū)域的地方停車:亂停車是錯(cuò)誤的行為,而且會(huì)導(dǎo)致我們吃罰單,但有時(shí)候我們?yōu)榱粟s上旁邊建筑里的一次重要約會(huì),就不得不這樣鋌而走險(xiǎn)!”
所以,有時(shí)候效益成本比決定了一切!然而技術(shù)債務(wù)必須及早解決,它與像金融上的債務(wù)相似的另一個(gè)地方,正是在于它們都會(huì)產(chǎn)生利息。
這里的利息是指在每次維護(hù)系統(tǒng)的過(guò)程中,我們面對(duì)以下狀況需要付出的努力:由于緊耦合、過(guò)大的類、未經(jīng)測(cè)試的代碼或任何其他形式的技術(shù)債務(wù),而導(dǎo)致代碼和/或設(shè)計(jì)的維護(hù)變得極其困難。
從我的觀察來(lái)看,技術(shù)債務(wù)的總利息并不固定,而是會(huì)隨著時(shí)間的推移而增長(zhǎng)。我的意思是,在面對(duì)一個(gè)帶有技術(shù)債務(wù)的系統(tǒng)時(shí),每一個(gè)Sprint中我們都需要在系統(tǒng)維護(hù)上花費(fèi)比之前更多的精力。這個(gè)現(xiàn)象源自以下兩項(xiàng)因素:
- 維護(hù)時(shí)很有可能會(huì)引入額外的債務(wù),這是因?yàn)楫?dāng)我們的系統(tǒng)中擁有一些混亂的代碼時(shí),任何維護(hù)都會(huì)遵從相同的代碼和/或設(shè)計(jì)方法。這些新增的債務(wù)會(huì)在下一次維護(hù)時(shí)消耗更多的精力,而這一切將不斷重復(fù)。
- 隨著時(shí)間的流逝,由于沒(méi)有遵從設(shè)計(jì)模式以及缺乏文檔化,更多的開發(fā)者會(huì)從各自對(duì)代碼或設(shè)計(jì)片段如何工作的假設(shè)出發(fā),給系統(tǒng)打上不同的補(bǔ)丁。毫無(wú)疑問(wèn),這將在系統(tǒng)中引入新的Bug。而修訂這些新Bug又會(huì)引入更多的Bug……
基于以上原因,每份利息都會(huì)對(duì)技術(shù)債務(wù)的增長(zhǎng)“做出貢獻(xiàn)”,因此這里的利息實(shí)際上是復(fù)利計(jì)算方式。復(fù)利計(jì)算使用以下指數(shù)公式:
Yt = Y0(1+r)t
在這里,Yt是在第t個(gè)Sprint時(shí)的債務(wù)值,Y0是債務(wù)初始值,r代表增長(zhǎng)率,而t代表Sprint序號(hào)。在敏捷項(xiàng)目環(huán)境中,“t”是一個(gè)整數(shù),因此在這里我們可以說(shuō),技術(shù)債務(wù)將隨著時(shí)間的推移按幾何方式增長(zhǎng)(因?yàn)閹缀魏瘮?shù)是指數(shù)函數(shù)的一個(gè)特定情況——當(dāng)指數(shù)函數(shù)中的“t”永遠(yuǎn)取整數(shù)值的時(shí)候)。
因此,隨著混亂的代碼庫(kù)不斷積累,系統(tǒng)將變得更加脆弱且難以維護(hù)。技術(shù)債務(wù)利息增長(zhǎng)的另一個(gè)副作用則是,由于用在維護(hù)上的時(shí)間越來(lái)越多,導(dǎo)致團(tuán)隊(duì)生產(chǎn)力遭到了抑制。
在某個(gè)項(xiàng)目中,我們?cè)诤荛L(zhǎng)時(shí)間內(nèi)都在忍受這樣的糟糕代碼實(shí)踐,當(dāng)我們最終進(jìn)入正式投入使用前的階段時(shí),系統(tǒng)突然之間就崩潰了!我們不可能進(jìn)行重構(gòu)的同時(shí),又能夠避免在系統(tǒng)中諸多部分帶來(lái)重大影響,因此我們決定一切推倒重來(lái)!
圖1:累計(jì)柱狀圖展現(xiàn)了技術(shù)債務(wù)的利息隨著時(shí)間推移呈現(xiàn)幾何增長(zhǎng)的態(tài)勢(shì)。圖中所用的是假設(shè)值,而非真實(shí)項(xiàng)目數(shù)據(jù)。
下一節(jié)將簡(jiǎn)要介紹一套用來(lái)管理技術(shù)債務(wù)的推薦流程。在初始假設(shè)中,我們認(rèn)為技術(shù)債務(wù)是一種風(fēng)險(xiǎn)。這項(xiàng)假設(shè)基于對(duì)風(fēng)險(xiǎn)的定義:“可能會(huì)影響至少一項(xiàng)項(xiàng)目目標(biāo)——范圍、計(jì)劃、成本或質(zhì)量——的一件不確定事件。”技術(shù)債務(wù)非常符合這條定義,因?yàn)樗鼘?duì)項(xiàng)目來(lái)說(shuō)是一項(xiàng)潛在威脅,如果不能及時(shí)解決的話,可能會(huì)對(duì)項(xiàng)目造成負(fù)面影響。
作為敏捷愛(ài)好者,我將把這個(gè)流程放在Scrum項(xiàng)目中,來(lái)進(jìn)行分析。實(shí)際上我發(fā)現(xiàn),非常有必要管理敏捷項(xiàng)目的技術(shù)債務(wù)。因?yàn)榕c其他方法相比,敏捷方法中的快速交付節(jié)奏更加鼓勵(lì)快速且不干凈的代碼風(fēng)格。而且在敏捷項(xiàng)目中,我們只進(jìn)行恰到好處的設(shè)計(jì)和架構(gòu),并通過(guò)重構(gòu)來(lái)跟上任何需求的調(diào)整;這樣的后果是,在某種程度上我們總會(huì)擁有技術(shù)債務(wù),因?yàn)槲覀兛偸遣坏貌辉谡归_設(shè)計(jì)的過(guò)程中優(yōu)化我們的代碼。
技術(shù)債務(wù)管理流程如下:
- 設(shè)定技術(shù)信用限額(TCL)——TCL是我們?cè)敢饨璩龅睦硐牍ぷ餍r(shí)數(shù)或用戶故事點(diǎn)的最大總額。可以用總項(xiàng)目大小的百分比形式來(lái)計(jì)算該限額,例如10%。
- 識(shí)別技術(shù)債務(wù)因素——技術(shù)債務(wù)因素是指這樣的情況:某位團(tuán)隊(duì)成員希望繞過(guò)一些良好的代碼、設(shè)計(jì)或測(cè)試實(shí)踐,以便實(shí)現(xiàn)快速交付。我們應(yīng)該在每天Scrum會(huì)議通過(guò)小組討論來(lái)識(shí)別這些因素。
- 記錄技術(shù)債務(wù)任務(wù)——對(duì)于每項(xiàng)技術(shù)債務(wù)因素,需要在技術(shù)債務(wù)記錄里添加兩項(xiàng)任務(wù),并使用立項(xiàng)工作小時(shí)或用戶故事點(diǎn)的方式來(lái)估算其大小。這兩項(xiàng)任務(wù)是:
- 開拓型任務(wù):指我們決定利用技術(shù)債務(wù)因素時(shí),需要做什么。這是技術(shù)債務(wù)的累加。
- 償還型任務(wù):當(dāng)決定重構(gòu)代碼或設(shè)計(jì)的時(shí)候,我們需要做什么。這一任務(wù)的大小,代表了我們從TCL中拿出多少來(lái)償還發(fā)生的債務(wù)。
- 選擇任務(wù)——在Sprint規(guī)劃會(huì)議中,選擇希望開拓的技術(shù)債務(wù)因素。技術(shù)債務(wù)因素的選擇應(yīng)該基于產(chǎn)品所有者確定的優(yōu)先級(jí)。
- 從TCL中減去償還型任務(wù)所關(guān)聯(lián)的技術(shù)債務(wù)的大小(限額扣減)。
- 在Sprint待辦事項(xiàng)列表中增加與開拓型任務(wù)相關(guān)的技術(shù)債務(wù),并將其大小累加到項(xiàng)目總大小上。
如果我們發(fā)現(xiàn)TCL已經(jīng)快要用光了,那么接下來(lái)我們需要:
- 在Sprint待辦事項(xiàng)列表中添加一項(xiàng)償還型任務(wù)。
- 在完成該償還型任務(wù)后,對(duì)TCL增加等量額度。
這樣,我們將TCL作為監(jiān)視系統(tǒng),以便在技術(shù)債務(wù)開始積聚的時(shí)候警告自己,以便我們努力使其恢復(fù)到健康水平。
圖 2:技術(shù)債務(wù)隨著開拓和償還任務(wù)發(fā)生的變化,以及與技術(shù)信用限額的對(duì)比。當(dāng)開拓任務(wù)完成時(shí),技術(shù)債務(wù)上升,而償還任務(wù)完成時(shí)則下降。
結(jié)語(yǔ)
將技術(shù)債務(wù)作為風(fēng)險(xiǎn)來(lái)進(jìn)行管理,并使用技術(shù)信用限額,能夠有效地減少技術(shù)債務(wù)的負(fù)面影響,同時(shí)令收益最大化——特別是在敏捷方法中,我們很容易濫用技術(shù)債務(wù),將其作為一種加速交付的手段,因此也就需要更加關(guān)注技術(shù)債務(wù)。
關(guān)于作者
Yaser Marey是來(lái)自埃及的軟件工程師、項(xiàng)目經(jīng)理、PMP和Scrum大師。在過(guò)去14年間,他領(lǐng)導(dǎo)團(tuán)隊(duì)為國(guó)家和區(qū)域客戶開發(fā)企業(yè)級(jí)軟件系統(tǒng)。他是敏捷、精益和持續(xù)改進(jìn)的狂熱愛(ài)好者,他相信這些對(duì)埃及和中東的軟件產(chǎn)業(yè)來(lái)說(shuō)必不可少。Yaser在他的博客中分享了軟件架構(gòu)和項(xiàng)目管理方面的經(jīng)驗(yàn)。
it知識(shí)庫(kù):Habya'a(臨時(shí)拼湊的組件)與技術(shù)債務(wù),轉(zhuǎn)載需保留來(lái)源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。