1992 年,Ward Cunningham 在敏捷宣言中首次提出了“技術(shù)債”概念,主要指有意或無意地做了錯誤的或不理想的技術(shù)決策所累積的債務(wù)。隨后,《重構(gòu)》一書的作者 Martin Fowler 基于 Cunningham 的比喻,創(chuàng)建了一個“技術(shù)債務(wù)四象限”,包括: 魯莽 / 有意:“我們沒有時間去設(shè)計”; 謹(jǐn)慎 / 有意:“我們必須現(xiàn)在交付,之后再處理因為追求速度所產(chǎn)生的結(jié)果”; 魯莽 / 無意:“什么是分層?”; 謹(jǐn)慎 / 無意:“我們現(xiàn)在知道應(yīng)該怎么做了”。 前段時間,Reddit 上有關(guān)技術(shù)債的話題再次引起程序員的廣泛討論。用戶 spo81rtyOP 表示,“大多數(shù)軟件的實際使用壽命也就 5 到 10 年。即便軟件能幸存下來,完全由過時技術(shù)棧編寫這一現(xiàn)實也會讓它的路子變得很窄。這就是軟件工程師的真實命運。” 創(chuàng)業(yè)公司 CTO Matt Watson 則直言,他過去 20 年的職業(yè)生涯全是技術(shù)債。 Watson 13 歲開始編程,22 歲時創(chuàng)辦了自己的第一家科技公司 VinSolutions,實現(xiàn)了 3000 多萬美元的 ARR,并于 2011 年以 1.5 億美元的價格將其出售給 AutoTrader。離開 VinSolutions 后,Watson 創(chuàng)辦了一家名為 Stackify 的公司,為軟件開發(fā)人員提供應(yīng)用程序監(jiān)控。此外,Watson 還在菲律賓創(chuàng)辦了離岸開發(fā)公司 Full Scale ,以支持他的 SaaS 公司。Watson 透露,F(xiàn)ull Scale 已發(fā)展到擁有 300 多名員工。 Watson 在博客中提到,當(dāng)他聽到有人說“我們正在快速開發(fā) MVP,同時最大限度地減少技術(shù)債”時,他只是笑笑,因為他知道,最終所有東西都會變成技術(shù)債。Watson 在博客中介紹了自己的 20 年職業(yè)生涯發(fā)生的變化,他悲觀地表示:“如果時間足夠長的話,你的所有代碼都將被刪除?!?/p> Watson 的職業(yè)生涯始于 Visual Basic 6 的開發(fā)。從 1999 年到 2003 年,Watson 構(gòu)建了多個不同的應(yīng)用程序。后來,Watson 又花了很多時間進(jìn)行經(jīng)典的動態(tài)服務(wù)器頁面(ASP)開發(fā),自己也成為了在 Internet Explorer 6 和 Netscape Navigator 制作兼容網(wǎng)站的專家。 但在今天來看,Visual Basic、ASP、IE6 和 Netscape 都是早已被遺忘的技術(shù)了。 與此同時,在過去的 20 多年里,很多編程語言也都“失寵”了,比如 Perl、Delphi、Fortran、FoxPro、ColdFusion。也許這些古老的編程語言還存在某些應(yīng)用程序中,但大多數(shù)情況下,還應(yīng)用這些編程語言的公司必須要對舊的應(yīng)用程序進(jìn)行現(xiàn)代化改造,并將其淘汰。如果你用這些過時的編程語言構(gòu)建程序,最終的結(jié)果可能只有重寫,因為很難再找到使用這些語言的程序員了。 在 21 世紀(jì)初,人們認(rèn)為 Adobe ColdFusion 是最熱門的產(chǎn)品,但在今天呢?Ruby on Rails 也可能走上 Adobe ColdFusion 的老路,它已經(jīng)失寵了,并且很難找到使用它的開發(fā)人員。曾經(jīng) Ruby on Rails 獨有的東西,現(xiàn)在也可以在其他語言中使用了。 Watson 表示,編程語言來來往往,開發(fā)人員不希望學(xué)習(xí)工作中不需要的技能。同時,開發(fā)人員跳槽的速度也很快,他們總是希望自己的簡歷上有一些熱門的新東西。 Watson 最初開發(fā)的一些應(yīng)用程序使用了 Internet Explorer 6 中的 ActiveX 控件。當(dāng)時,需要用它們來做打印和其他一些非常不安全的黑客工作。PDF 在當(dāng)時并不常見,用瀏覽器打印簡直就是一場噩夢。 Java Applets 也曾輝煌過,但它運行緩慢,并且在電腦上安裝正確版本的 Java 總是一團糟。Watson 稱自己永遠(yuǎn)不會忘記處理 Java 小程序網(wǎng)絡(luò)防火墻的噩夢。“我一點也不懷念它們,幸運的是,它消失了?!?/p> 此外還有 Macromedia/Adobe Flash。當(dāng)時 Flash 游戲?qū)映霾桓F,許多軟件都是用 ActionScript 在 Flash 中構(gòu)建的?,F(xiàn)在,一個名為 CheerpX 的產(chǎn)品允許使用 WebAssembly 運行舊的 Flash 應(yīng)用程序。 微軟曾推出一個名為 Silverlight 的 Flash 競品。對于 C# 開發(fā)人員來說,這實際上是一個非常棒的框架。Watson 的公司也曾用 Silverlight 構(gòu)建了一些非常棒的東西。不過后來,蘋果在瀏覽器中放棄了對 Flash 和 Silverlight 的支持,從而終結(jié)了它們。 下圖是十多年前,Watson 在 VinSolutions 中使用 Silverlight 構(gòu)建財務(wù)計算器的屏幕截圖。Silverlight 現(xiàn)在早已不復(fù)存在,他們用 JavaScript 重寫了它,但 Watson 認(rèn)為,新版本沒有舊版本酷了。
2004 年還沒有 iOS 和 Android,當(dāng)時,Watson 曾為 Compaq PDA 編寫了一個應(yīng)用程序,用于跟蹤汽車經(jīng)銷商的庫存。它是用 C# 編寫的,用于在 Windows CE 上運行的 .NET Compact Framework 中。
這個 PDA 有一個 100 萬 像素的攝像頭,只要外面是陰天,照片就會糟糕些。這個應(yīng)用程序很早以前就被淘汰了,但在 2005 年時它還很前衛(wèi)。
Swift 是另一個很好地說明開發(fā)工具變化速度之快的例子。蘋果公司發(fā)布 Swift 后,就很難再證明用 Objective C 編寫代碼是合理的了。雖然在某些用例中仍然需要用 Objective C,但 Swift 明顯更易于開發(fā),并且是向前邁出的重要一步。
Watson 認(rèn)為,現(xiàn)在任何用 Objective C 編寫的應(yīng)用程序都可能是技術(shù)債了。
在為構(gòu)建 Web 應(yīng)用程序編寫了瘋狂的內(nèi)聯(lián)腳本之后,Watson 很樂意使用新的 ASP.NET Web 表單,其服務(wù)器端控件大大簡化了開發(fā)。它們的目標(biāo)是讓創(chuàng)建 Web 應(yīng)用程序變得像在 Visual Basic 6 中一樣簡單。開發(fā)者可以在服務(wù)器端構(gòu)建可重用的 UI 組件以呈現(xiàn)給瀏覽器,就像今天使用 100% 的 JavaScript 所做的那樣。
WebForms 并不完美,但它是一個相當(dāng)大的提升。在 Ruby on Rails 出現(xiàn)并普及了用于開發(fā) Web 應(yīng)用程序的 MVC(Model-View-Controller,模型 - 視圖 - 控制器)框架之前,它一直運行得很好。
MVC 很快就淘汰了開發(fā)者制作的所有 Web 表單應(yīng)用程序。Watson 認(rèn)為,任何網(wǎng)頁形式的東西都絕對是技術(shù)債。
不知不覺中,每種編程語言就都支持 MVC 框架了。Watson 也曾轉(zhuǎn)而使用 ASP.NET MVC 做所有的新功能。它無處不在,包括 Django、Laravel、Symfony、Spring 等。
快進(jìn)到今天,MVC 已經(jīng)過時了。現(xiàn)在一切都是在 React、Angular、Vue 和其他框架中完成的。在此之前,開發(fā)者還會使用 Javascript 框架。在 Stackify 工作時,Watson 還曾使用過 Knockout,這是一個相當(dāng)流行的前端框架。
但在今天,還有人記得 Knockout、Ember、Aurelia、Meteor、Backbone、Handlebars 這些框架嗎?它們都“失寵”了,甚至被劃分為技術(shù)債。毫無疑問,第一代前端框架輸給了 React 和 Angular。
2015 年,谷歌創(chuàng)建了 Angular,Angular 迅速成為最受歡迎的前端框架。2016 年,Angular 進(jìn)行了一次重大升級,不再向后兼容。這意味著,原始版本中的任何內(nèi)容現(xiàn)在都是技術(shù)債。
Watson 曾在項目中使用過舊版本的 Angular,如今卻成了他必須升級的主要技術(shù)債。
在 REST API 和 JSON 成為事實上的標(biāo)準(zhǔn)之前,另一種選擇是 SOAP,它代表簡單對象訪問協(xié)議,主要由基于 XML 的 Windows 通信框架(WCF)來使用。它使得調(diào)用 Web 服務(wù)并通過自動代碼生成代理類來正確調(diào)用服務(wù)變得更容易。
Watson 職業(yè)生涯中最糟糕的一個項目,就是要弄清楚如何在他的公司和另一家供應(yīng)商之間通過 WCF 和 SOAP 使用安全證書。SOAP 和 WCF 的承諾令人驚嘆,但隨著時間的推移,維護它簡直是一場噩夢。
微軟決定不再支持 .NET Core 中的 WCF,REST、gRPC 和 GraphQL 現(xiàn)在才是首選。盡管如此,有個社區(qū)項目最終使 CoreWCF 得以繼續(xù)發(fā)展。
隨著時間的推移,開發(fā)者用來調(diào)用 Web 服務(wù)的技術(shù)類型已經(jīng)發(fā)生了變化。舊的方式仍然有效,但大多數(shù)人可能更愿意淘汰它們。
此外還有編程語言的版本更改問題。無論是 Ruby、PHP、.NET 還是其他語言,它們通常需要改寫大量的代碼,甚至是完全重寫。
當(dāng) .NET Core 剛發(fā)布時,它是專為在 Linux 上運行而設(shè)計的更新、更輕、更快的 .NET 版本。基本的 C# 代碼都很容易移植過來,但沒有人會在真實的應(yīng)用程序中只使用基本代碼。然而,在復(fù)雜的企業(yè)應(yīng)用程序中,想要升級時可能會出現(xiàn)許多潛在的問題。這就成為了一筆必須解決的重大技術(shù)債。否則,開發(fā)者最終會陷在一個古老的版本中。
這些主要版本的更新,最終會成為重大的技術(shù)債項目。
Watson 在 Stackiy 遇到的最大挑戰(zhàn)之一是卡在了舊版本的 Elasticsearch 上。有一次,它們對其工作方式進(jìn)行了一些重大的更改,但這些更改并不完全向后兼容。Watson 的團隊大量使用了它,于是所有的升級工作都變成了海量的技術(shù)債和升級項目。
在 Stactify 時,Watson 曾為 6 種編程語言構(gòu)建了自己的跟蹤 / 測評分析庫,這項工作的工作量令人難以置信。隨著 OpenTelemetry 出現(xiàn),Watson 過去的這些工作變得毫無用處。既然可以使用開源的行業(yè)標(biāo)準(zhǔn),為什么還要自己管理呢?Stackiy 正在慢慢地消除那些 Watson 幫忙構(gòu)建的.NET 測評分析器。
Watson 在職業(yè)生涯早期開發(fā)的幾個應(yīng)用程序都已經(jīng)被終止了,因為這些公司被收購了,并且決定使用完全不同的技術(shù)。
Watson 認(rèn)為,隨著時間的推移,你會看到你創(chuàng)造的幾乎所有的東西都會因為各種原因而被廢棄和替換,或者現(xiàn)在就已經(jīng)都是基于舊技術(shù)的了。大多數(shù)軟件的使用壽命都很有限,比你想象的要短。所有的代碼最終都變成了技術(shù)債,每個人都想用更現(xiàn)代的方式重寫,或者業(yè)務(wù)需求發(fā)生重大的變化。
誠然,在企業(yè)界,更有可能擁有似乎永遠(yuǎn)存在的內(nèi)部應(yīng)用程序。像鐵路或大型銀行這樣的公司使用同樣的基于大型機的軟件已經(jīng)有 40 年了。
Watson 預(yù)測,WebAssembly 最終會超越當(dāng)今的前端開發(fā),一個全新的世界將不斷發(fā)展。
在做新項目時,大家總是希望將技術(shù)債降至最低。但 Watson 認(rèn)為,不可能不產(chǎn)生技術(shù)債,因為根本沒有十全十美的東西。隨著時間的推移,今天完美的東西將來也會不完美,因此,我們需要學(xué)會與不完美共存。
而技術(shù)債的另一面是,隨著時間的推移,一切都會慢慢“腐爛”——要么在升級到最新版本方面存在重大問題,要么由于更新的操作方式而最終失寵。
“一切最終都會變成技術(shù)債,否則項目就會夭折。如果幸運的話,你的代碼能存活足夠長的時間,從而成為別人的技術(shù)債。如果時間足夠長的話,你的所有代碼都將被刪除?!盬atson 在博文的最后說道。
Watson 的觀點引發(fā)了很多開發(fā)者的討論。贊同者認(rèn)為自己過去做的很多工作最終都被取代了,辛苦編寫的代碼可能幾年后就沒有了用武之地;反對者則認(rèn)為不應(yīng)如此悲觀,因為有些代碼真的可以長青不老。
Reddit 用戶、前幾年剛退休的開發(fā)者 vital_chaos 提到,他這輩子在編寫代碼方面投入了 40 年時間,在他參與過的所有技術(shù)要素當(dāng)中,只有一種至今仍在得到實際應(yīng)用:
“我的團隊從 1988 年起著手開發(fā)一款應(yīng)用程序,直到 1994 年正式開發(fā)完成,這就是 Deltagraph。如今,它的持有公司已經(jīng)在新冠疫情的沖擊下倒閉。據(jù)我所知,我做過的所有其他工作最終都被取代了,或者是雇主倒閉,總之成果消失在了歷史的長河中。當(dāng)然,有些可能仍被使用,這個我也不敢完全確定。 所以我覺得雖然很多事情在做的時候看似無比重要,老板也總在催促要加班加點完成任務(wù),但事后回頭再看,這些辛苦編寫的代碼很可能幾年之后就喪失了生命力!”
用戶 spo81rtyOP 也非常認(rèn)可 Watson 的觀點:“感謝你讓我確定,有這種感覺的不單是我自己。我覺得大多數(shù)軟件的實際使用壽命也就 5 到 10 年。之后,因為企業(yè)倒閉或者其他原因,軟件被替代的可能性會非常高。即便它能幸存下來,完全由過時技術(shù)棧編寫這一現(xiàn)實也會讓它的路子變得很窄。這就是軟件工程師的真實命運?!?/p>
用戶 com2kid 表示,他曾于 2008 年前后在微軟工作,當(dāng)時他看到過一個版權(quán)為 1994 年的頭文件,里面還有作者姓名。搜索后發(fā)現(xiàn),那位程序員已經(jīng)在微軟當(dāng)上副總裁了。所以他認(rèn)為,有些代碼真的可以長青不老。
用戶 chesterriley 則想象了一個極端可能:也許未來終有一天,人們會繼續(xù)使用 100 年前就編寫出來的代碼。最終的大贏家可能會是 Unix 實用程序或者 TCP/IP 代碼之類,又或者是某些編譯器、運行時引擎或解釋器。還有來自 Linux 或 Windows 等操作系統(tǒng)的代碼。人們可能突然發(fā)現(xiàn),自己修復(fù)的錯誤居然誕生自 100 多年前。
也有開發(fā)者認(rèn)為,有些代碼受到當(dāng)前炒作趨勢的影響很大,而 Web 開發(fā)應(yīng)該就是其中最典型的代表了??紤]到過去二、三十年間 Web 開發(fā)領(lǐng)域發(fā)生的一系列根本性變化,這種情況也在情理之中。
用戶 Otis_Inf 擁有 28 年從業(yè)經(jīng)歷,他表示,他還記得網(wǎng)景(Netscape)發(fā)布背景圖像的那一天,cgi 處理程序中的 Perl 腳本也曾經(jīng)是常態(tài)。無論是當(dāng)年還是現(xiàn)在,技術(shù)的發(fā)展速度都相當(dāng)驚人,開發(fā)者必須適應(yīng)新的做事方式——包括提交給 cgi 處理程序的靜態(tài) html 頁面,也包括異步獲取部分新元素來構(gòu)成視圖的客戶端渲染頁面。
當(dāng)然,也有些代碼并沒真正受到當(dāng)今炒作的影響。有趣的是,這類代碼大多集中在服務(wù)器端。雖然一直有強大的力量在“顛覆”微服務(wù)、Lambda 函數(shù)等服務(wù)構(gòu)建方式,但如果忽略掉這些實現(xiàn)細(xì)節(jié),那服務(wù)器的內(nèi)存空間里肯定還有 db+ 服務(wù)在運行、也還有空閑周期沒有利用起來。
Otis_Inf 認(rèn)為,IBM DB2 仍能運行 30 年前的 SQL 代碼是有原因的,這個原因就是組織仍然依賴這些功能?;蛘哒f,根本就沒有足夠多的人把它“重寫”成新代碼。那這些代碼是“爛代碼”或者說“技術(shù)債”嗎?還是得看具體情況。你家的錘子可能也用了十來年了,它過時了嗎?如果還能干活,那就沒過時。只有當(dāng)代碼確實需要變更,但卻沒人處理這項工作時,它才會真正淪為“爛代碼”。
“我希望看到當(dāng)下誕生的新項目能始終牢記長期可維護性的重要意義,甚至把它當(dāng)作一項基本設(shè)計前提。畢竟真的沒多少人有能力維護陳舊軟件項目。盡管地球人口仍在增加,但掌握足夠技能來維護這些古早軟件的開發(fā)者數(shù)量一直都跟不上?!?/p>
針對技術(shù)債問題,InfoQ 曾采訪過國內(nèi)一些技術(shù)從業(yè)者。
百分點 CTO 劉譯璟認(rèn)為,判斷技術(shù)債務(wù)的重點在于“哪些事情是應(yīng)該做的”,它是一個因組織而異、因項目而異、因人而異的過程,例如以下一些方面:
組織上要求做但沒做的:制度、流程、規(guī)范、分享學(xué)習(xí)等;
業(yè)務(wù)和技術(shù)上要求做但沒有做的:功能、性能、安全、高可用、擴展、監(jiān)控、輔助工具等。
如果按照軟件工程環(huán)節(jié)分類,技術(shù)債務(wù)可以分為:需求分析、方案設(shè)計、架構(gòu)設(shè)計(邏輯架構(gòu)、功能架構(gòu)、數(shù)據(jù)架構(gòu)、部署架構(gòu)、運行架構(gòu)等等)、編碼、測試、發(fā)布等。如果按照產(chǎn)出物類型分,可以分為:
文檔類:管理過程文檔、需求分析文檔、設(shè)計文檔、測試案例文檔等;
代碼類:代碼、腳本、規(guī)范等;
軟件包類:產(chǎn)品軟件包、依賴軟件、依賴資源等;
環(huán)境類:開發(fā)環(huán)境、測試環(huán)境、預(yù)上線環(huán)境、生產(chǎn)環(huán)境等。
至于如何決定要重寫還是繼續(xù)維護,需要判斷“繼續(xù)維護的收益”和“重寫的收益”哪個更大,來決定繼續(xù)維護還是重寫??梢跃C合考慮如下幾方面的收益:
開源:提升現(xiàn)有業(yè)務(wù)收入、支持新業(yè)務(wù)的開拓;
節(jié)流:節(jié)省維護人員、節(jié)省運營費用;
組織:人員結(jié)構(gòu)調(diào)整、組織能力培養(yǎng)。
債務(wù)是避免不了的,時刻判斷“持有債務(wù)的價值”,當(dāng)價值很低時要盡快處理。
騰訊研發(fā)總監(jiān)王輝表示,如果人力、物力和工期等資源豐富,能去優(yōu)化的就都可以做到極致。但通常,資源都是不豐富的,或者說是捉襟見肘的,那就要根據(jù)實際業(yè)務(wù)情況來看。騰訊一向的方式是“先抗住再優(yōu)化”,項目是否真的到了非優(yōu)化不可的地步,是否真的到了不優(yōu)化隨時都可能宕機的時候,如果先抗住了,就等業(yè)務(wù)占領(lǐng)了市場,站住了用戶,到了項目進(jìn)度慢下來之后,一些優(yōu)化再開展起來,此時可以要求高可用、高性能、高并發(fā)等。
“如果項目資源允許,一些稍微過度的優(yōu)化和重構(gòu),個人認(rèn)為是可以被接受的,保持團隊的技術(shù)熱情是不錯的,但如果資源不允許,就要數(shù)著錢花,判斷技術(shù)債務(wù)的合理性,如何更好的還債,是否真的到了非還不可,是否真的到了影響業(yè)務(wù)發(fā)展,需要與業(yè)務(wù)優(yōu)先級一起看,業(yè)務(wù)錯過一個時間窗就可能永遠(yuǎn)錯過,有些技術(shù)債務(wù)還可以后期再還。”王輝總結(jié)道。
參考鏈接:
https://blog.visionarycto.com/p/my-20-year-career-is-technical-debt
https://www.infoq.cn/article/xgP9W*MC6Svi9Zcqd5KX
https://news.ycombinator.com/item?id=35955336
https://www.reddit.com/r/programming/comments/13ihrtx/my_20_year_career_is_technical_debt_or_deprecated/