什么是技術(shù)債務(wù)饼问?##
許多團隊都受技術(shù)債務(wù)困擾影兽,不過,很少有團隊能真正地設(shè)計一個計劃從中掙脫出來莱革。為了更好的理解如何才能擺脫債務(wù)峻堰,我們首先要正確地理解什么是技術(shù)債務(wù)。
技術(shù)債務(wù)是由團隊為了短期的項目利益故意做了欠佳的技術(shù)決策而招致的盅视。例如捐名,為了使一個產(chǎn)品更快的投放市場,團隊可能不會像面對一段棘手的代碼那樣闹击,編寫深入的自動化測試镶蹋。或者,他們可能會決定基于一個很快就會過時的框架構(gòu)建項目贺归,而不是花錢購買那個框架的一個經(jīng)過升級淆两、服務(wù)支持更好的版本。不管決策是什么拂酣,關(guān)鍵是要認識到秋冰,真正的技術(shù)債務(wù)是團隊為了獲得短期利益故意做了會招致長遠債務(wù)的決策。
![]()
這意味著婶熬,許多我們通常歸咎于“技術(shù)債務(wù)”的事情實際上根本就不是債務(wù)丹莲。例如,隨著系統(tǒng)使用年限增加尸诽,團隊會無法一直保持最佳編碼實踐,在那種情況下出現(xiàn)“位衰減(bit dot)”是正常的盯另,不是債務(wù)性含。或者鸳惯,團隊自愿做出的技術(shù)決策在隨后實現(xiàn)時竟然發(fā)現(xiàn)是不正確的商蕴,這也不是技術(shù)債務(wù)。在任何一種情況下芝发,團隊都不是為了獲得短期利益而故意做了欠佳的長遠決策绪商。這種差別很重要,因為我們只有在究竟是什么組成了技術(shù)債務(wù)的問題上達成一致辅鲸,我們才能針對如何減少技術(shù)債務(wù)做出最佳決策格郁。
考慮我們在無意間引入代碼庫的債務(wù)所帶來的影響也很重要。不過独悴,由于這類債務(wù)不是有意承擔的例书,所以我們無法計劃如何提前解決它。在這些情況下刻炒,我們一定要在發(fā)現(xiàn)的時候優(yōu)先考慮并解決這種債務(wù)……就像團隊解決新發(fā)現(xiàn)的Bug所做的那樣决采。
一個金融比喻##
我們經(jīng)常將技術(shù)債務(wù)與金融債務(wù)進行對比。但是坟奥,這是一個對等的類比嗎树瞭?比如,如果不首先確定何時以及如何償還爱谁,銀行真會愿意借給我們錢嗎晒喷?很可能不愿意。既然不首先描述如何償還債務(wù)管行,我們就確實無法借到金融資本厨埋,那么我們也就不應該以這種方式對待技術(shù)資本。
這個金融比喻確實非常有效,因此荡陷,我們將對它進行更充分的討論雨效。
- 償還計劃
正如金融債務(wù)一樣,在談?wù)摷夹g(shù)債務(wù)時废赞,我們需要確定兩件事:如何償還債務(wù)和何時償還債務(wù)徽龟。
- 如何償還債務(wù)
讓我們以前文提到的放棄自動化測試為例。如果為了一項功能能夠盡快投入生產(chǎn)環(huán)境唉地,我們的團隊自愿決定放棄為棘手的代碼段編寫自動化測試据悔,那么我們需要確定我們將如何糾正那塊債務(wù)。在這種情況下耘沼,我們只需要表明极颓,我們會在將來的某個時點回到這段代碼,然后添加測試群嗤。不過菠隆,只表明“我們將在稍后添加測試”并沒有合理地解決這個問題。為了幫助干系人真正地了解我們的決策對招致技術(shù)債務(wù)會有多大的影響狂秘,我們需要盡我們最大的能力準確地說明等到后來添加自動化測試的影響骇径。比如,我們應該指明需要添加測試的代碼段者春。我們也需要明確指出破衔,在已有的代碼段上增加自動測試比在代碼段創(chuàng)建時直接添加測試總是難度更大成本更高。最后這點很重要钱烟,因為它明確指出晰筛,將這項工作推遲到后來完成,我們實際上要比現(xiàn)在直接完成花更多的錢來做這項工作拴袭。換句話說传惠,……債務(wù)是會產(chǎn)生利息的。
在討論完償還方式之后稻扬,團隊及其干系人可能會意識到卦方,這個問題要比他們是否應該在編寫代碼時編寫自動化測試更復雜。實際上泰佳,他們可能會發(fā)現(xiàn)盼砍,在兩個極端之間,他們確實有多種更適合整個項目的選擇逝她。比如浇坐,他們可能會決定,使用類似“圈復雜度(Cyclomatic Complexity)”這樣的指標識別出新特性中最復雜的部分是非常有意義的黔宛,并立即添加測試覆蓋那些方面近刘,而把簡單一些的方面推遲。或者觉渴,他們可能會決定介劫,像單元測試這種更簡單但同時價值也更低的自動化測試類型可以立即添加,但像自動化用戶驗收測試這種難度更高的自動化測試可以推遲到將來的沖刺中案淋。不管是哪種決定座韵,團隊及其干系人都不大可能做出,因為他們沒有在第一時間對技術(shù)債務(wù)進行討論踢京。
- 何時償還債務(wù)
除了指明如何償還債務(wù)外誉碴,我們還希望指明何時償還債務(wù)。通常瓣距,債務(wù)越早償還越好黔帕。出于這個原因,最好是在債務(wù)產(chǎn)生的時候安排債務(wù)償還工作蹈丸,以便更好地傳達承擔債務(wù)的影響蹬屹。比如,如果你的團隊遵照一個由沖刺構(gòu)成的時間表白华,那么你可能會選擇將工作安排到下一個沖刺,或者贩耐,在最壞的情況下也不超過幾個未來的沖刺弧腥。
通常,團隊都會有最美好的愿望潮太,就是在債務(wù)出現(xiàn)的時候償還管搪,但他們只是似乎從來都沒有時間那樣做。當你要消除債務(wù)的時候铡买,在日歷上記下最后償還期限更鲁,并堅持按時完成。
- 如果違約會怎么樣 ?
對于我們的金融比喻奇钞,最后一部分是弄清楚澡为,如果我們選擇拖欠債務(wù),會出現(xiàn)什么后果景埃。在金融領(lǐng)域媒至,如果我從來不償還汽車貸款,那銀行會開走我的汽車谷徙。拖欠技術(shù)債務(wù)的后果同樣應該明確指出拒啰。
讓我們繼續(xù)自動化測試的例子,如果團隊決定不償還技術(shù)債務(wù)完慧,那么以現(xiàn)有的未經(jīng)測試的功能為基礎(chǔ)構(gòu)建新功能只會使難度越來越大成本越來越高谋旦。在生產(chǎn)環(huán)境中,我們可能會看到更多的Bug報告,這意味著册着,客戶可能會對我們的產(chǎn)品質(zhì)量產(chǎn)生不好的印象拴孤。我們快速響應市場變化的能力也會被削弱,因為我們產(chǎn)品的很大一部分要么很難快速修改指蚜,要么快速修改風險太大乞巧。
上述各點都需要向干系人講清楚,幫助我們避開技術(shù)債務(wù)違約的誘惑摊鸡。
- 應對位衰減
截至目前绽媒,我們討論的所有內(nèi)容都集中在有計劃的技術(shù)債務(wù)上,就是那些作為正常項目的一部分團隊故意招致的債務(wù)免猾,而如果我們不討論未計劃的技術(shù)債務(wù)是辕,我們就失職了,因為它們也困擾著許多項目:位衰減猎提。
![]()
如前所述获三,位衰減不是我們故意招致的,我們無法提前決定如何以及何時償還锨苏,在這個意義上疙教,它不同于正常的技術(shù)債務(wù)。不過伞租,雖然我們無法確切地知道位衰減在我們項目中的呈現(xiàn)形式贞谓,但這并不意味著我們無法計劃它。
就像我們計劃償還已知技術(shù)債務(wù)時所做的那樣葵诈,我們也可以在我們的項目計劃中加入一個緩沖區(qū)裸弦,用于在每次沖刺中處理位衰減。雖然那時可能并不知道填充這個緩沖區(qū)的具體任務(wù)作喘,但有一個這樣的緩沖區(qū)在那里理疙,使我們有了一個專門的空間,可以應對那些未計劃的問題泞坦,如Bug窖贤,必須立即處理的小規(guī)模重構(gòu),或者我們稱之為代碼庫自然老化和衰減的小塊系統(tǒng)維護贰锁。
但是主之,對于那些用幾個小時的開發(fā)時間都無法解決的更大的問題,該怎么辦李根?可能會有更多讓我們倍感困擾的系統(tǒng)性問題槽奕,如基礎(chǔ)設(shè)施故障或架構(gòu)日益老化無法再滿足業(yè)務(wù)需求。由于這些問題太大房轿,不容易解決粤攒,我們就可以使用這個緩沖區(qū)確認和研究這些問題所森,那樣,我們后續(xù)就可以在項目中給予它們應有的注意夯接。比如焕济,在基礎(chǔ)設(shè)施故障的情況下,或許我們能夠確定基礎(chǔ)設(shè)施中最經(jīng)常出現(xiàn)故障的部分盔几,那樣我們就可以在待辦事項列表中增加故事晴弃,用于替換這些部分。然后逊拍,我們會在正常的開發(fā)中排定優(yōu)先級并照此調(diào)度那些故事上鞠。或者芯丧,在架構(gòu)日益老化的情況下芍阎,我們可以花些時間來確定,我們對于架構(gòu)能夠動態(tài)做出的最有價值的修改是什么缨恒,然后將那些修改分解成可以在將來的沖刺中分段處理的故事谴咸。不管問題是什么,有時間確定問題并制定計劃就意味著可以像解決其它任何技術(shù)問題一樣解決它骗露。
- 預算

既然我們已經(jīng)對招致技術(shù)債務(wù)的影響有了一個更好的了解岭佳,那么我們該如何真正確保償還技術(shù)債務(wù)?為了對此有一個感官的認識萧锉,我們將上述金融比喻向另一個方向擴展……預算珊随。
我們中有許多人每隔幾周就會掙得一份固定工資。這份工資是年度工資的一部分驹暑,全年平均分布。比如辨赐,如果我們每年能掙52000美元优俘,那么我們可能每隔2周就會收到2000美元……就是說,每年26次掀序。
不過帆焕,雖然按規(guī)則我們每次都能領(lǐng)到2000美元工資,但我們實際上不大可能全部存放在活期賬戶上不恭。相反叶雹,我們更可能只將一部分存放在活期賬戶上,而把其它部分用于長期投資或者償還債務(wù)换吧。
比如折晦,我們起初有2000美元存款,預算分解實際上可能是下面的樣子:
500美元用于長期投資沾瓦,比如存入退休賬戶
200美元用于償還短期債務(wù)满着,如信用卡
300美元用于償還長期債務(wù)谦炒,如按揭貸款或汽車貸款
250美元直接扣除,用于支付地方或國家稅收
剩下的750美元存入活期賬戶
現(xiàn)在风喇,雖然沒人對這種安排感到特別興奮宁改,但也基本沒人質(zhì)疑。在某種程度上魂莫,它簡直是公認的規(guī)范还蹲。既然這種安排被如此廣泛地接受,那么為什么不將它擴展到我們的項目計劃中呢耙考?
想象一下谜喊,我們正以故事點為單位計劃一次沖刺,并且琳骡,我們?yōu)槟莻€沖刺分配了50個故事點锅论。盡管我們希望將所有50個點都用在新的開發(fā)上,但實際上楣号,最合理的方式是安排一些點用于償還技術(shù)債務(wù)最易。比如,對于原有的50個點炫狱,我們可能決定安排:
10個點用于償還技術(shù)債務(wù)
5個點用于不間斷的代碼庫維護藻懒,如修復Bug或處理位衰減
35個點用于新的開發(fā)
看看我們的點預算,我們可以看到它與我們前面描述的金融預算有一些明顯的相似之處视译。雖然每個沖刺我們有50個點用來做事嬉荆,但并不是所有那些點都用在新的開發(fā)上。更確切地說酷含,我們必須把那些點中的10個用于償還我們有意招致的技術(shù)債務(wù)鄙早,正如我們把工資的一部分用于償還我們的長期和短期債務(wù)。此外椅亚,我們將5個點完全用于保持不間斷的代碼庫維護限番,正如我們把每份工資的一部分用于稅收,幫助維持我們社區(qū)的正常運轉(zhuǎn)呀舔。剩下的點是我們自己的弥虐,可以根據(jù)我們的意愿用于任何新的開發(fā),正如剩下的錢存入活期賬戶媚赖,我們可以根據(jù)自己的意愿自由支配霜瘪。
通過工作預算的方式,我們可以確保我們的項目仍然在向前進行惧磺,而不允許它在技術(shù)債務(wù)的重壓之下崩潰颖对。
當然,就像個人預算一樣磨隘,這種預算會有些偏差惜互。比如布讹,如果我們償還技術(shù)債務(wù)的速度比預期快,那么我們就會有些剩余的故事點可以用在新功能開發(fā)上训堆。而同樣的描验,如果我們發(fā)現(xiàn)我們承擔著特別多的技術(shù)債務(wù),那么我們可能需要稍微降低新功能的開發(fā)速度坑鱼,直到技術(shù)債務(wù)的數(shù)量回到一個更可控的水平膘流。
小結(jié)##
通過以金融債務(wù)做類比考慮技術(shù)債務(wù),我們可以對什么時候會招致技術(shù)債務(wù)有一個更明智的判斷鲁沥,有利于項目改善呼股。在項目進行過程中,我們還可以更好地計劃試圖償還債務(wù)所帶來的影響画恰。
而且彭谁,通過在日常工作中計劃日常預算,我們可以更好地了解我們的債務(wù)什么時候是可控的以及什么時候會讓我們負擔過重允扇。