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