“軟件和大教堂是類似的矢炼,都是先構(gòu)建,然后祈禱”阿纤【涔啵————Earl Everett
關(guān)于技術(shù)債務(wù)的討論時(shí)而蔓延時(shí)而消退,技術(shù)債務(wù)仿佛是個(gè)筐欠拾,什么東西都可以往里裝胰锌,然而當(dāng)我們企圖倒光筐里東西的時(shí)候,卻發(fā)現(xiàn)每人看到的東西都不一樣藐窄,甚至有時(shí)候都數(shù)不清里面都有些什么资昧。 作為一個(gè)半吊子全棧工匠,試圖從一個(gè)老碼農(nóng)的視角審視一下技術(shù)債務(wù)荆忍。
一個(gè)比喻導(dǎo)致的分歧
技術(shù)債務(wù)是由敏捷先驅(qū) Ward Cunningham(https://en.wikipedia.org/wiki/Ward_Cunningham)
在1992年的一個(gè)報(bào)告中的一個(gè)比喻格带,大意是做了錯(cuò)誤的或不理想的技術(shù)決策所導(dǎo)致的債務(wù)。由于是個(gè)比喻刹枉,所以產(chǎn)生了每個(gè)人眼中的哈姆雷特叽唱。
首先,Steve McConnell將技術(shù)債務(wù)分為兩類:無意的和有意的微宝。
1)無意產(chǎn)生的技術(shù)債務(wù):由于缺乏經(jīng)驗(yàn)而編寫了低質(zhì)量的代碼棺亭。
2)有意產(chǎn)生的技術(shù)債務(wù):根據(jù)當(dāng)前情況進(jìn)行設(shè)計(jì)選型,可能很快就能解決當(dāng)前的問題芥吟,有時(shí)會(huì)變得拙劣侦铜。
作為《重構(gòu)》一書的作者,Martin Fowler認(rèn)為技術(shù)債務(wù)產(chǎn)生的利息是指由于魯莽的設(shè)計(jì)決策導(dǎo)致需要在未來的研發(fā)中付出更多钟鸵。面對(duì)技術(shù)債務(wù)箱玷,可以持續(xù)付利芹彬,也可以通過重構(gòu)一次付清旷祸。代碼中的壞味道也是技術(shù)債務(wù)熊榛,是一種不計(jì)后果的債務(wù),會(huì)讓問題變得更加嚴(yán)重,進(jìn)而將技術(shù)債務(wù)劃分為4個(gè)象限:
Bob大叔則認(rèn)為壞味道并非技術(shù)債務(wù)俊卤。技術(shù)債務(wù)的評(píng)價(jià)標(biāo)準(zhǔn)是真實(shí)的項(xiàng)目約束嫩挤,這些約束是風(fēng)險(xiǎn)和好處并存的。壞味道是由懶惰和外行導(dǎo)致的消恍,總是意味著損失岂昭。技術(shù)債務(wù)要求牢記保持代碼的整潔,就好像一個(gè)人在背負(fù)巨大的抵押債務(wù)時(shí)需要時(shí)刻保持警醒一樣狠怨。
關(guān)于技術(shù)債務(wù)的更多定義討論參見http://wiki.c2.com/?TechnicalDebt约啊。
技術(shù)債務(wù)的現(xiàn)象與類型
將一個(gè)比喻作為定義是不嚴(yán)謹(jǐn)?shù)模液芏嗳藢?duì)定義的重要性并不是很關(guān)注佣赖。于是恰矩,可以從現(xiàn)象和構(gòu)成的角度來看待技術(shù)債務(wù)。
如何認(rèn)識(shí)無意產(chǎn)生的技術(shù)債務(wù)呢憎蛤?當(dāng)出現(xiàn)如下現(xiàn)象的時(shí)候外傅,說明技術(shù)債務(wù)開始累積:
1)類似的代碼在不同的項(xiàng)目/產(chǎn)品間遷移
2)代碼已經(jīng)穩(wěn)定但回歸測(cè)試的陳本在增加
3)每一次交付的成本逐漸增加
4)類似feature 開發(fā)的周期開始變長
5)在既有代碼上開發(fā),還不如推到了重來
技術(shù)債務(wù)的類型是由產(chǎn)生的原因和方式來定義的俩檬,其中一種分類如下:
- 戰(zhàn)略債務(wù):為了戰(zhàn)略利益(例如首次上市)故意為之萎胰,并長期存在。
- 戰(zhàn)術(shù)債務(wù):在知情的情況下為了快速收益而產(chǎn)生豆胸,適用于短期奥洼。
- 疏忽債務(wù):在不知情的情況由于缺乏知識(shí)和意識(shí)而產(chǎn)生。
- 增量債務(wù):定期不慎產(chǎn)生的而導(dǎo)致增量債務(wù)晚胡。
技術(shù)債務(wù)包括那些現(xiàn)在選擇不做的內(nèi)部事務(wù),但會(huì)影響未來的開發(fā)工作嚼沿,例如延遲重構(gòu)估盘。不包括推遲的功能實(shí)現(xiàn),除非交付功能對(duì)客戶來說“足夠好”的情況下骡尽,但不滿足某些標(biāo)準(zhǔn)(例如遣妥,UI元素不完全符合某些UI標(biāo)準(zhǔn))。
技術(shù)債務(wù)的組成
技術(shù)債務(wù)是多方面的攀细,涉及技術(shù)的多個(gè)維度箫踩,這也是每人眼中都有著自己的哈姆雷特的一個(gè)重要原因。
現(xiàn)羅列自己經(jīng)歷或者看到過的一些方面:
- 代碼債務(wù):代碼重復(fù)谭贪、違反靜態(tài)分析工具和代碼異味等境钟。
- 設(shè)計(jì)債務(wù):設(shè)計(jì)異味、違反設(shè)計(jì)規(guī)則等
- 架構(gòu)債務(wù):違反架構(gòu)規(guī)則俭识,對(duì)非功能性約束認(rèn)知不足等慨削。
- 測(cè)試債務(wù):缺乏測(cè)試、測(cè)試覆蓋面不足和不正確的測(cè)試設(shè)計(jì)等。
- 質(zhì)量債務(wù):缺乏穩(wěn)定性和健壯性的技術(shù)驗(yàn)證缚态,QA的自動(dòng)化不足等
- 配置債務(wù):版本控制的模糊磁椒,環(huán)境參數(shù)的混淆等
- 平臺(tái)債務(wù):平臺(tái)經(jīng)驗(yàn)的匱乏,云服務(wù)融合與應(yīng)用不足等
- 文檔債務(wù):存在重大問題的文檔玫芦、缺乏文檔和文檔過期等浆熔。
針對(duì)每一類技術(shù)債務(wù),都有著相應(yīng)的原則和處理方法桥帆,有時(shí)間再仔細(xì)展開医增。
技術(shù)債務(wù)的度量之痛
No measurement,No management环葵。令人遺憾的是调窍,很難有相關(guān)工具或者框架來提供量化數(shù)據(jù)對(duì)其進(jìn)行準(zhǔn)確而完整的分析。
技術(shù)債務(wù)并沒有一個(gè)普遍接受的范圍定義张遭,甚至認(rèn)為已知的bug也構(gòu)成了技術(shù)債務(wù)邓萨。當(dāng)前可用的技術(shù)債務(wù)量化工具僅僅關(guān)注幾個(gè)維度,比如代碼債務(wù)和一定程度的設(shè)計(jì)債務(wù)和測(cè)試債務(wù)菊卷。對(duì)于同其它維度相關(guān)的問題缔恳,比如架構(gòu)債務(wù)或文檔債務(wù),這類工具并沒有提供全面的檢測(cè)支持洁闰。實(shí)際上歉甚,已支持的維度的全面性也是有問題的。
一般扑眉,技術(shù)債務(wù)的量化工具通常會(huì)轉(zhuǎn)換成償還這些債務(wù)所需的工作量纸泄,而工作量會(huì)隨問題的嚴(yán)重性、范圍腰素、平臺(tái)聘裁、技能等的變化而不同。這樣所產(chǎn)生的估計(jì)值與實(shí)際情況大不相符弓千,最多只是一種近似衡便,而不是準(zhǔn)確的結(jié)論。
任何類型的債務(wù)都會(huì)包含本金和利息洋访,而當(dāng)前的一些所謂的量化工具都關(guān)注與技術(shù)債務(wù)相關(guān)的本金镣陕,而忽視了利息部分,從而并不可信姻政。利息部分關(guān)系到了理解的難度等因素呆抑,越發(fā)難以準(zhǔn)確地量化。
技術(shù)債務(wù)很好地充當(dāng)了溝通拙劣設(shè)計(jì)結(jié)果和持續(xù)重構(gòu)需求的隱喻扶歪。但試圖測(cè)量和量化技術(shù)債務(wù)時(shí)理肺,變得同準(zhǔn)確測(cè)量軟件生產(chǎn)力或者量化軟件質(zhì)量一樣困難摄闸!
技術(shù)債務(wù)的現(xiàn)金衡量
當(dāng)然,技術(shù)債務(wù)的貨幣化有助于了解技術(shù)債務(wù)的嚴(yán)重程度妹萨,提供了一種跟蹤技術(shù)債務(wù)償還進(jìn)度的方法年枕。不過,需要謹(jǐn)慎對(duì)待這些成本和工作量估計(jì)乎完。
一旦有了與技術(shù)債務(wù)直接相關(guān)的金錢數(shù)目熏兄,關(guān)于軟件的多種復(fù)雜而麻煩的問題就可能得到答案。Israel Gat提出:除非對(duì)于技術(shù)債務(wù)有一個(gè)量化的賬單树姨,否則團(tuán)隊(duì)都會(huì)忽略其重要性摩桶。他提到了以金錢方式計(jì)算技術(shù)債務(wù)的需要,以金錢方式計(jì)算技術(shù)債務(wù)有如下好處:
- 能夠告訴團(tuán)隊(duì)何時(shí)停止開發(fā)帽揪,開始重構(gòu)硝清。團(tuán)隊(duì)進(jìn)入重構(gòu)過程,除非債務(wù)得以償還转晰,否則不加入任何功能芦拿。
- 客戶對(duì)于軟件的風(fēng)險(xiǎn)得以了解。
- VC們可以以此判斷向某項(xiàng)軟件產(chǎn)品中投入資金是否理智查邢。
- 有助于判斷軟件的支付能力蔗崎,判斷在重構(gòu)和重寫這二者之間做出選擇
有哪些有效的方式可以用來將技術(shù)債務(wù)以金錢衡量呢?
Sonar中的技術(shù)債務(wù)插件是一種方式扰藕。在Sonar的站點(diǎn)上缓苛,已經(jīng)有了對(duì)于項(xiàng)目的技術(shù)債務(wù)分析。要計(jì)算成本邓深,首先要使用下面的方式找出債務(wù):
債務(wù)(人/天)=修復(fù)重復(fù)部分的成本
+修復(fù)違規(guī)的成本
+為公共API做注釋的成本
+修復(fù)未發(fā)現(xiàn)的復(fù)雜性的成本
+帶入低于閾值復(fù)雜性的成本
+在包的層面上切斷生命周期的成本
對(duì)于每個(gè)小時(shí)的成本有個(gè)默認(rèn)值未桥,例如人工200塊每小時(shí)。與之類似芥备,就可以做出各種情況的現(xiàn)金分析钢属,并可以計(jì)算出技術(shù)債務(wù)的總和。
因此门躯,以金錢方式計(jì)算技術(shù)債務(wù)能夠深入理解與軟件相關(guān)的潛在成本。對(duì)于所有希望監(jiān)控技術(shù)債務(wù)成本并將其保持在一定限額內(nèi)的敏捷團(tuán)隊(duì)來說酷师,這很關(guān)鍵讶凉。
直面技術(shù)債務(wù)
面對(duì)已知的技術(shù)債務(wù),普遍的經(jīng)驗(yàn)是防止技術(shù)債務(wù)的積聚山孔,以及有計(jì)劃地償還技術(shù)債務(wù)懂讯。
防止技術(shù)債務(wù)產(chǎn)生的主要方法是了解開發(fā)團(tuán)隊(duì)存在的技術(shù)債務(wù)。開發(fā)團(tuán)隊(duì)必須了解技術(shù)債務(wù)台颠,它的各種方面和類型褐望,以及債務(wù)對(duì)他們的項(xiàng)目的影響勒庄。他們必須具備完善的設(shè)施與代碼質(zhì)量的概念,干凈的編碼習(xí)慣瘫里、設(shè)計(jì)嗅覺实蔽、以及如何重構(gòu)它們。合適的流程可以幫助開發(fā)團(tuán)隊(duì)避免技術(shù)債務(wù)積累谨读,例如代碼局装、設(shè)計(jì)、架構(gòu)和測(cè)試的審查等劳殖。然而铐尚,這些流程必須是務(wù)實(shí)的,否則事與愿違哆姻。
對(duì)于償還技術(shù)債務(wù)而言宣增,首先同樣是識(shí)別并記錄現(xiàn)有債務(wù),優(yōu)先處理異味矛缨,在每個(gè)迭代中分期償還債務(wù)爹脾。如果一個(gè)研發(fā)團(tuán)隊(duì)的以團(tuán)隊(duì)交付功能的數(shù)量或修復(fù)bug的數(shù)量為考核標(biāo)準(zhǔn),那么團(tuán)隊(duì)將只專注于增加功能和修復(fù)bug劳景。但實(shí)際上誉简,做好它和完成它同樣重要。同時(shí)盟广,留意可能出現(xiàn)的大規(guī)模債務(wù)償還闷串,屬于不同維度的債務(wù)實(shí)例相互影響。在某些情況下筋量,即使債務(wù)很高烹吵,也不值得償還技術(shù)債務(wù)。這些情況包括原型桨武、概念實(shí)現(xiàn)和即將廢棄的產(chǎn)品所產(chǎn)生的技術(shù)債務(wù)肋拔。此外,如果計(jì)劃為一個(gè)傳統(tǒng)項(xiàng)目遷移到一個(gè)新的技術(shù)呀酸、平臺(tái)或架構(gòu)凉蜂,不償還的技術(shù)債務(wù)是明智的,因?yàn)橄嚓P(guān)的債務(wù)可以在遷移過程中解決的性誉。
管理他人的技術(shù)債務(wù)
由于不提倡重復(fù)造輪子窿吩,我們所使用的第三方軟件和開源軟件產(chǎn)生的技術(shù)債務(wù)同樣會(huì)對(duì)我們?cè)斐捎绊憽K鼈兊腂ug會(huì)成為我們的Bug错览,安全漏洞也會(huì)成為我們的安全漏洞纫雁,錯(cuò)誤決定會(huì)成為了我們的錯(cuò)誤決定。
我們所使用其他軟件的代碼量可能會(huì)非常大倾哺,由此產(chǎn)生的技術(shù)債務(wù)也可能大轧邪,甚至超過自己所編寫的代碼量刽脖。根據(jù)Sonatype的一項(xiàng)調(diào)查顯示,80%的Java應(yīng)用都是由開源組件與框架裝配起來的忌愚,一個(gè)大型系統(tǒng)甚至?xí)褂?0多個(gè)不同的庫或組件曲管。
要想了解這種債務(wù)問題的嚴(yán)重性,需要審查代碼中使用了哪些第三方開源包與依賴菜循。一旦清楚了其他人的軟件可能會(huì)造成的影響翘地,就需要評(píng)估由此所帶來的風(fēng)險(xiǎn)和問題了,并需要緊密追蹤這些軟件的補(bǔ)丁癌幕、升級(jí)信息及Bug報(bào)告等衙耕,這確實(shí)不太容易。
知道問題的嚴(yán)重性是一方面勺远,修復(fù)問題則是另一方面橙喘。對(duì)最新的發(fā)布打補(bǔ)丁并非易事。最好能在外圍打補(bǔ)丁胶逢,因?yàn)檠a(bǔ)丁并非總是適合于我們所使用軟件的方式:Apache厅瞎、Tomcat、Web Service庫初坠、客戶端組件等和簸。我們需要更加謹(jǐn)慎地管理這些后端代碼。如果每當(dāng)出現(xiàn)一個(gè)Linux補(bǔ)丁時(shí)需要立刻打上碟刺,那就說明架構(gòu)可能有些問題锁保。
升級(jí)更是一個(gè)大問題了,升級(jí)到最新的OS半沽、RDBMS爽柒、VM等都涉及到很高的代價(jià)與風(fēng)險(xiǎn)。雖然可以通過升級(jí)的方式獲得在可伸縮性者填、管理性及新特性等方面的一些優(yōu)勢(shì)浩村,不過升級(jí)項(xiàng)目還需要更加關(guān)注一些潛在的問題:功能回歸、兼容性問題占哟、操作流程的變化心墅、對(duì)其他系統(tǒng)的依賴變化等等。升級(jí)之后榨乎,大多數(shù)軟件會(huì)變得更大而不是更好嗓化,也許會(huì)加入很多新特性,不過可能壓根就用不上這些特性谬哀,這也意味著需要花更多的時(shí)間進(jìn)行安裝、配置和測(cè)試严肪。我們需要搞清楚變化的地方史煎,重新進(jìn)行測(cè)試和調(diào)優(yōu)谦屑。
技術(shù)債務(wù)的價(jià)值
把技術(shù)債務(wù)和金融債務(wù)來類比,貸款就會(huì)產(chǎn)生債務(wù)篇梭,如果定期還款氢橙,那么債務(wù)是可接受的,不會(huì)產(chǎn)生進(jìn)一步的問題恬偷。但是悍手,如果他不還款,就會(huì)以利息作為懲罰袍患,并隨著不還款次數(shù)的增加而增加坦康。如果很長一段時(shí)間不能支付任何款項(xiàng),那么應(yīng)計(jì)利息使得債務(wù)更難以償還诡延。
同樣地滞欠,當(dāng)我們采用一個(gè)非最優(yōu)或次優(yōu)技術(shù)決定,就引入了技術(shù)債務(wù)肆良。在很長一段時(shí)間未償還累計(jì)的技術(shù)債務(wù)的情況下筛璧,軟件越來越難以改變,在極端情況下惹恃,軟件產(chǎn)品變得在技術(shù)上已經(jīng)破產(chǎn)夭谤,往往會(huì)導(dǎo)致項(xiàng)目終止。利息有復(fù)合的性質(zhì):開發(fā)團(tuán)隊(duì)越是忽略或推遲它巫糙,隨著時(shí)間的推移朗儒,債務(wù)變得越大。因此曲秉,是利息使得技術(shù)債務(wù)成為一個(gè)顯著問題采蚀。
我們談及技術(shù)債務(wù)的時(shí)候往往都清楚它的種種弊端,卻缺乏主動(dòng)使用技術(shù)債務(wù)的勇氣承二。 債務(wù)具有著現(xiàn)金價(jià)值榆鼠,在金融領(lǐng)域中,貨幣杠桿的作用顯著亥鸠。 對(duì)企業(yè)而言妆够,現(xiàn)金流更是關(guān)鍵因素, 所以负蚊,沒有必要談債色變神妹,沒有債的企業(yè)未必都是一流的好企業(yè)。
合理使用技術(shù)債務(wù)家妆,在這個(gè)快節(jié)奏的時(shí)代鸵荠,我們有責(zé)任迅速為客戶提供價(jià)值。在這種追求中伤极,有各種情況團(tuán)隊(duì)必須選擇快速或者骯臟的解決方案蛹找。需要注意的是姨伤,在這種情況下,需要我們以勤奮和務(wù)實(shí)的態(tài)度處理技術(shù)債務(wù)庸疾。