天天看點

準确識别技術債務才是改造遺留系統的破解之道

作者|白嗣健

編輯|支小亞

本文由極客時間整理自華為雲化平台技術專家白嗣健在 QCon+ 案例研習社的演講《千萬級規模遺留系統債務度量改造實踐》。

今天來聊聊大規模的遺留系統。大廠的遺留系統一般會呈現什麼樣的特點呢?第一是存量代碼規模特别大,其次是技術棧特别全,最後是架構的演進時間長,10 年至 20 年的祖傳遺留系統非常常見。

祖傳代碼

遺留系統的架構通常如上圖所示:它可以完整運作,整個系統功能也比較穩定。然而由于技術棧過時造成演進性不足,文檔過時或丢失導緻與真實的系統脫節,當初的設計者可能已經離開公司,或者升遷到管理層,輕易的改動帶來的連鎖反應很容易導緻整個系統的不穩定。面對這樣的遺留系統一般人都會比較謹慎,技術人員更願意重寫而不是做遺留系統的改造。

但從成本上來看改造比推倒重來短期成本要高(分析問題,制定政策),長期成本要低得多(變化及規格丢失導緻客戶投訴)。考慮到風險成本,我更願意去做遺留系統的改造而非重構。重寫過程中面臨需求的雙重傳遞壓力,文檔缺失規格很容易丢失,在測試階段僅僅補齊規格就需要很長一段時間,技術人員很容易陷入到技術情結中,重寫前承諾的收益往往很難兌現,更換架構和程式設計語言極易造成團隊不穩定,架構師通常會選擇他喜歡的語言,程式員通常會選擇他擅長的語言,僅僅選擇語言就是一門很難的功課,通常 App 開發的選擇是 Java、Scala、Go,高性能系統開發選擇是 Rust,C++,而膠水類腳本語言開發選擇 TS/JS、Python、Lua。

如果你是一個信心滿滿的架構師,選擇了更具挑戰的遺留系統改造,動手前你應該知道這個遺留系統有哪些呆賬壞賬,這些欠賬稱為技術債務。你不僅要搞清楚都有哪些債務,還要搞清楚欠債的根因是什麼。架構與代碼代表工程師寫的瞬間對架構、代碼、業務、環境的認知,随着技術進步,環境變化技術債務就自然産生了,這部分債務屬于良性債務,或者說無法避免的債務。另一種債務可能是快速疊代追求商業價值的妥協産物,如果沒有重構的投資,或團隊缺乏重構的基因,就需要要去改進流程和工具。以我的經驗債務的消減需要雷鋒,團隊文化要求不能讓雷鋒吃虧。

不同規模遺留系統的特點

規模系統

管理的規模不同,面臨的問題就不一樣,面臨的問題不一樣,所采用的方法就不一樣。如果你管理一個代碼規模 20K 左右的微服務,相信你通過個人能力很快可以将其改造為最佳狀态。如果你是一個技術負責人,管理 10 個微服務約 200K 代碼,依靠個人能力很難将其改造為最佳狀态。你需要想辦法在團隊中建立起某個機制,比如每日代碼集體檢視,它解決了日常的管理、能力提升、review 設計思路,每一個 commit等問題,避免了錯誤的設計落入版本的尴尬場面。那些在檢視中投入度比較高,經常能夠給别人提出建設性建議(檢視意見)的人就是可以重點培養的下一任的 Tech Lead,相信我,集體檢視是小團隊最有效的管理方式。

如果你是一個技術專家,管理 100 個微服務大概 200 萬行規模的代碼。這時你僅靠個人能力和代碼檢視是不夠的 。100 個微服務的團隊人數一般是 100+,這樣的團隊規模需要的是一套優秀的實踐體系,從軟體的架構設計(模組化,設計與實作一緻),到需求分解(并行,Tasking),再到代碼送出(代碼持續內建,小步送出,每日檢視),最後是測試方法(TDD,BDD,統一測試架構)。

不過我想重點談一談如果管理 500 個微服務,大概千萬級代碼規模。想要管理這樣一個組織,讓這些服務都按照你想要的方式去進行演進,就要結合上面提到的所有實踐,包括個人的能力、團隊的氛圍、優秀實踐,還要多加上一些方法論的應用。其難點在于不能生搬硬套,要為團隊量身打造,通過影響力形成團隊共識,制定落地政策,下一篇會舉例講解。

再往上管理 5000 個左右微服務,這樣的團隊通常可能會跨地域。我并沒有真實地管理過這麼大規模的項目,是以我沒有發言權。

不同規模遺留系統的應對政策

小規模政策

進階工程師

我個人認為進階工程師管理一個微服務隻要熟讀設計模式,可以熟練地使用,就可以把一個微服務改造得非常好。

微服務的開發,可能連使用複雜設計模式的機會都沒有,在雲原生的領域裡已經把單體應用的架構子產品設計通過微服務及基礎設施解耦掉了,甚至做到了 Serverless。面向雲原生開發你隻需要專注于把業務代碼寫出來就可以。

靜态掃描工具可以掃出來爛代碼,因為爛代碼有規則,寫好出好代碼是沒有固定模式的,現階段識别好代碼最靠得住的方案仍然是人工識别。業界比較好的工具如 Codota,它是一款免費 AI 自動補全編碼工具,可以內建在 IDEA 中,輸入字元後它會自動幫你聯想補全最佳代碼片段,還可以片段檢索。另外就是讀一下 Clean Code、Clean Arch、Effective Code、設計模式等書籍,可以幫助你提升自己的代碼品位。

技術負責人

如果管理 10 個服務,怎麼樣確定讓這 10 個服務履行你的架構設計意圖呢?我做團隊技術負責人的時候堅持每天做代碼檢視。代碼檢視是一個非常好的手段,誰的代碼是 TDD 的,誰做了重構,誰有想法都是一目了然的。前提是檢視會議不能隻是上司在講,開發在開小差的狀态,在我看來代碼檢視是每天的黃金 30 分鐘。

代碼檢視實際上有很多優秀實踐,比如檢視前要求每位同學檢視代碼前先自己過一遍,想想怎麼講,要有邏輯,要容易讓别人聽懂,這樣才能縮減檢視時間。有時候上午寫的代碼,到下午就忘了今天上午我為什麼這樣想這樣寫。

其次,我們對檢視的時間有要求,如果你能堅持每天檢視,每天檢視時間一般不會超過半個小時。檢視的第一步就是把 Commit、Comments 過一下,快速地讓别人知道我今天幹了什麼事情。接着快速地浏覽每一行代碼,在浏覽過程中如果遇到一些常見的問題和共性的問題,我們可以在檢視中講一下。

最後,在檢視中我們可以盡早發現設計方面的問題,選用更合适的設計模式。代碼已經寫完以後才發現設計有問題就晚了,這時技術債務就已經形成了。是以代碼檢視的過程是學習的過程,也是互相促進的過程。我們在代碼檢視中經常可以發現一些檢視的意見領袖,這些意見領袖在我們團隊裡面就是我們後備的 Tech Lead。

除了檢視,我們在團隊中還落地了一些優秀實踐,比如 TDD。如何落地 TDD?我們要求在新的需求中最好可以用 TDD 的方式,這個是 nice-to-have,并不是 need-to-have,是以在檢視中如果誰用了 TDD 的方式,我們會給予他鼓勵。

這兩年通過微服務火起來的 DDD 炙手可熱,今年我們也搞了一些 DDD 的實踐——Event-Storming 模組化、基于 DDD 的微服務實戰項目。DDD 是一個概念,一套理論,如何讓大家在實踐中把 DDD 落到項目中需要有一個 DDD Demo Project,有先鋒團隊願意去嘗試,我認為這是團隊氛圍好的展現。

百萬級代碼規模政策

技術專家

如果你是一個管理 100 個微服務的技術專家,想要管理這麼大的團隊,你要做到前面提到的所有實踐,實踐是累加的過程,理論上來講你無法跳過小團隊管理經驗直接到首席架構師。有一些團隊的 Tech Lead 并不認可 TDD,不認可 DDD,這是很正常。在我們團隊中會尊重不同的 Tech Lead 的選擇,永遠拒絕一刀切。

除此之外,我認為管理這麼多微服務比較重要的是 Metrics。比如去度量團隊的架構債務,代碼債務有多少,把債務通過公式轉換成時間,這樣就得到 A 團隊的技術債務是 30 分鐘,B 團隊的技術債務是 3 天。大概有一個 Metrics 的 Dashboard,我們就可以看到它每天的債務是增長的還是燃盡的,如果資料的次元比較多,那麼就需要通過一個成熟度評估,比如 Level3,或 3 star 團隊。

另外一個是 Backlog,Backlog 并不是一個 list 來記需要幹的事情,我們通常會給團隊投資一個 Backlog 去做重構或寫測試。如果你要求一個團隊或者一個工程師寫完代碼以後必須要帶測試,寫完代碼以後必須要重構,一般來說他不會去做,因為這對他來說沒有收益。我認為重構、寫測試也是編碼,也屬于産出,是以要給團隊一個 Backlog,給團隊一定的比例去做重構和開發者測試。開發者測試包括了 UT、FT、AT 等等,還包括一些性能測試、內建測試。

10 年前,我第一次體驗靈活,那時我還覺得靈活是一種管理手段。後來我接觸了一些極限程式設計的工程實踐和一些優秀的人,和這些人一起工作 1 年後,最終使我認可靈活。像我司這樣的雙模 IT 企業比較少,所謂雙模就是 IT 加 CT,我的感受是 IT 領域更适合遵循計劃,CT 領域更适合響應變化。

給大家講一個故事,我有一個做硬體的朋友,他每個季度都要出一趟差把他們的設計送到工廠中的房間去生産出來一批樣機。他每次都非常擔心,如果樣機出現任何設計問題他的麻煩就大了。像這樣的開發模式必須充分設計、充分驗證,充分測試,才能上線。

CT 領域就更适合靈活了,尤其是網際網路。我也曾在網際網路工作過,網際網路的訴求是要快速地試錯,允許灰階釋出。回報好就加大投資,回報平平就下線。是以軟體領域更适合微服務,更适合靈活。

其次就是 CI/CD、DevOps,很多團隊有 CI/CD 流水線,他可以給你展示——看我們的流水線是這樣跑的,但是點進去一看就會發現有很多問題。比如說微服務什麼時候拆?很多人可能會說我們在模組化時候就已經拆好了,這是架構師分析來的。多年的工作經驗告訴我微服務并不是拆出來的,而是演進來的。

拆分服務最佳時機我認為是在內建的過程中。一個服務持續內建時間過長會導緻團隊的整體速率變弱,此時就需要改進了。如果開發人員合一次代碼需要 30 分鐘以上,如果團隊規模是 Two Pizza,那每個人內建一次這需要很長時間,這可能導緻無法準時下班。

此時通過一些手段去優化測試、優化內建效率仍然不能滿足 30 分鐘以下,就可以分析如何拆分服務了,然後相應地根據康威定律的需要把這個團隊進行拆分,這是我用來識别什麼樣的服務應該要被拆分的一種方式。

千萬級代碼規模政策

軟體總工

當你要改造千萬級的代碼——一般是 2000 萬行左右的代碼,這種情況團隊可能都不在一個地域,如何去管理這麼多人、這麼多的服務?如果技術沒有管控覆寫絕大多數技術棧,那麼難度會指數暴增。在這種場景下你身為一個總工也好進階技術專家也好,首先你要建構你的通用程式設計架構,基礎設施,通用的公共元件以及債務的識别能力。

《演進式架構》裡面提到了一個非常重要的點叫 Fitness Function,這是用于遺傳學的算法。大家想想如果你開了上帝視角,如何確定整個世界根據你的想法進行疊代演進?世界是随機的,我們隻能定義一些系統性方程,讓适合方程的活下來,淘汰掉不合格的,這就是優勝劣汰。講到這裡,如果你可以寫一組方程來落地架構和代碼的演進意圖,就可以用适應性方程來控制整個大盤。

另外一個是 Clean Architecture,這是 Uncle Bob 的一個方法論(https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html)。我們的架構演進參考了 Clean Architecture,但是我們做了一個變種,更适合我們的 Clean Architecture Plus。

在改造過程中,架構演進難免碰到基礎設施不相容的場景,如何進行架構重構呢?第一步将基礎設施比如 MQ、DB、DFS、Cache 等進行了基礎設施的抽象,這一層很薄,但是卻很重要。第二步是 App 開發依賴新的接口進行開發,這樣就做到了應用開發與基礎設施的解耦,由于應用不關心基礎設施是什麼,讓我們服務更加 Serverless,在程式設計過程中也更容易寫測試。第三步是基礎設施團隊根據 API 去實作,在架構重構中難免會出現更換基礎設施的情況,對于應用來說不感覺,在基礎設施實作過程中去做适配,Bazel 是可以按需建構的,整個過程中接口作為了契約,通過契約測試實踐進行接口及契約管控,契約測試也根據現狀進行了改造,比如使用 git repo 代替 service broker,開發及建構過程通過 git 稀疏檢出進行通路,操作麻煩就統一 CLI 工具集,這樣基礎設施架構和應用架構滿足了依賴倒置及權限分離管控。如果你是一個善良的架構師,程式設計架構 runtime 的統一也必不可少。

落地實踐閉坑指南

經常有人抱怨 A 技術不行,B 實踐不好,在我腦海裡就會浮現出下面這幅圖:

賣家秀和買家秀

這是典型的“賣家秀”和“買家秀”。我見過太多團隊把靈活落地成了管理手段,把檢視變成了批判大會,與其說沒有學到精髓,不如說他們偷換了概念,我的經驗是你想學會一個東西,最好最快的方式就是和他們工作過。

靈活的精髓是什麼?我認為靈活的精髓就是靈活宣言裡面講的 4 條價值觀。在學靈活的過程中一不小心就會學成買家秀,然後大罵這個理論是有缺陷的!理論是不對的!比如現在很多人在讨論是不是 TDD 已死?是不是設計已死?我仍然認為任何一個東西都有人可以把它玩得非常好,任何一個再好的東西都有人會把它執行得非常地偏,非常地差,以至于整個團隊的動作變形。

有很多團隊負責人給我講靈活就是騙人的,覺得靈活就是一些流程的動作,靈活在遺留系統改造中起不到任何作用,僅僅是一些管理的手段。很多人覺得代碼檢視是一件浪費時間的事情,怎麼可以每天做呢?我們把代碼送出給 Committer 去 Review 就可以了。這些東西見仁見智,隻有你去優秀的團隊踐行過你才能真正體會到這裡面的精髓是什麼,你才能把檢視做好。

我認為心得體會和經驗才更有借鑒價值而非實踐本身。優秀實踐是如何誕生的呢?大都是把一個實踐當做模闆,結合團隊的認知資料和現狀資料,經過無數次疊代,參考會議上大家的改良意見進而形成優秀實踐。軟體開發之是以無法被 AI 完全替代(20 年内),恰恰因為沒有銀彈。

總 結

1. 不同規模遺留系統的特點

代碼量特别多

技術棧特别全

架構的演進時間比較長

2. 應對政策

小規模——熟讀設計模式,熟練地使用、代碼檢視

百萬級代碼規模——Metrics、度量團隊的架構債務、靈活

千萬級代碼規模——統計債務、Clean Code、CleanArchitecture

學到靈活的精髓

作者簡介

白嗣健

華為 雲化平台技術專家

軟體特戰隊隊長,華為人報戰鬥在 0 與 1 的世界作者,管理千萬級代碼規模行平台産品。

活動推薦

遺留系統一直是技術領域的“重災區”,想要深入剖析遺留系統的特點和問題,推薦你學習這門專欄,它将從代碼、架構、DevOps 和團隊現代化四大方向,解決遺留系統治理的疑難雜症,幫你和所在團隊走出遺留系統的泥潭。現開通超級會員首月 6 元即可解鎖,還有 200+ 體系課和 1400+ 視訊課,等你來品鑒!

掃碼開通會員,立省 99 元

免費看《遺留系統現代化實戰》專欄

點個在看少個 bug

繼續閱讀