聊一下,技術債務治理
前言
在現代軟件開發中,技術債務(Technical Debt)已成為一個不可忽視的重要概念。它指的是在軟件開發過程中,為了追求短期目標而做出的妥協,導致未來需要付出額外成本來修復這些妥協所帶來的問題。技術債務的管理不僅影響項目的質量和可維護性,還直接關系到團隊的工作效率和公司的長期發展。
什么是技術債務?
技術債務的定義可以追溯到Ward Cunningham,他將其比喻為“借款”,即在軟件開發中選擇了一個較為簡單的解決方案,而非最佳實踐。這種選擇雖然在短期內能加快開發進度,但卻可能在未來導致更高的維護成本和更復雜的技術問題。
圖片
為了提升需求開發速度,我們有時會在應當采納最佳方案時作出妥協,轉而選擇那些短期內能迅速推進項目進程的方案。然而,這種做法往往會導致未來的錯誤問題增多,并給自己帶來額外的開發負擔。這種技術層面的抉擇,猶如背負了一筆債務。
技術債務的分類
同樣,技術債務也有其層次之分,通常根據其影響程度和解決的緊迫性,我們可以將其劃分為四個象限,即技術債務的四象限模型。
圖片
技術債務可以根據不同的標準進行分類:
有意和無意兩種:
有意技術債務:團隊明確意識到當前的解決方案并非最佳選擇,且計劃在未來進行改進。
無意技術債務:團隊在缺乏足夠信息或經驗的情況下做出的選擇,往往潛伏較久,難以察覺。
魯莽型和謹慎型:
魯莽技術債務:由于缺乏規劃和規范而產生的債務,通常會導致嚴重的后果。
謹慎技術債務:在項目進度中做出的合理妥協,雖然存在風險,但在可控范圍內。
技術債務全景圖
根據卡內基-梅龍大學軟件工程研究所(SEI)的Robert Nord在《The Future of Managing Technical Debt》中提出的“技術債務全景圖”,技術債務可以從多個維度進行分析:
圖片
這張全景圖清晰地展現了技術債務的多個層面,包括那些通常與架構相關聯的債務、因環境變化而產生的技術差距型債務,以及主要由內部代碼質量低下引起的小粒度技術債務。
此外,通過這張圖,我們還可以洞察到兩個重要的方向。
可演進性
本質上,架構的元特征描述的是軟件架構在演進過程中趨于目標的能力。這種演進目標并不僅限于支撐功能快速迭代的靈活性,同樣可以涵蓋其他重要的架構屬性,如高可用性和可擴展性。
可維護性
狹義上的代碼問題主要涉及代碼的易理解性、問題的易修復性,以及在現有基礎上的易擴展性。這些因素共同影響著代碼的質量和可維護性。
背景
當技術債務已經嚴重影響了公司的運作、工作的效率時,才會著手去處理這些方面的問題,可要付出的代價就太大了。
圖片
隨著滴滴國際化業務的快速發展,技術棧的多樣化使得技術債務的管理變得愈發復雜。當前,研發所需的語言已不僅局限于平臺原生語言,跨平臺技術(如Flutter及其Dart語言)逐漸成為主流。這一轉變帶來了新的技術債務挑戰,尤其是在代碼質量和架構設計方面。
演繹過程
在項目的初期階段,我們面臨著快速上線和快速迭代的壓力,因此問題的積累是不可避免的。然而,隨著我們的不斷發展,我們意識到如果繼續這種狀態,將會對項目的質量和成本帶來雙重風險。同時,隨著業務逐漸融入Flutter跨平臺能力,我們在學習和研發Flutter的過程中,也遇到了諸多挑戰。特別是隨著Flutter SDK的不斷升級,我們在這個過程中也積累了大量的技術債務,例如空安全適配問題。目前,我們的SDK版本支持2.12.0,這是一個允許空安全和非空安全混合的版本,因此存在很大的隱患。
影響分析
對開發的影響
也許某一天我們接收了一個陌生的模塊,也許是自己曾經的代碼,發現如同屎山一樣,如下圖,自己都看不懂了,為了應付快速迭代的需求,只能不停的往這上面堆,這個屎山也會愈發龐大和混亂,如果這樣繼續下去,知道某一天因為一個小小的Bug,你需要花半天的時間來排查問題出在哪里,最后當你覺得問題終于改好了的時候,卻不料碰了不該碰的地方,結果就是 fixing 1 bug will create 10 new bugs,甚至程序的崩潰。
我們需要正確面對、積極面對這個事情,它不是沒有技術含量,他能給我們帶來更多的技術和業務上的挑戰。
對效率的影響
技術債務的治理本質上是提升效率的過程。
治理不當將導致開發周期延長、資源浪費和團隊士氣下降。因此,及時識別和解決技術債務是確保項目成功的關鍵。
圖片
現狀梳理
業務發展至今,通過整理存量問題和結合監控報警沉淀的問題,可以看出目前工程存在的問題方向。(非最全)
圖片
代碼復雜
在快速迭代過程中,往往忽視了良好的代碼組織與模塊化設計,導致組件間出現高度耦合的現象。此外,類文件行數過長也是一個需要關注的問題。這些問題可能會影響代碼的可讀性和可維護性,進而降低開發效率。因此,我們需要重視代碼結構的優化和模塊化設計,以降低組件間的耦合度,并合理控制類文件行數,從而提高代碼質量。
架構混亂
- 業務架構在從初期到后期的迭代過程中,經歷了逐步分化和嘗試等階段,尚未形成統一的結構走勢。
- 目前存在新舊架構混合使用的情況。
代碼風格
在Flutter跨平臺代碼中,代碼結構和規范風格的不統一是一個常見問題。這主要是由于不同IDE的使用,很容易引發代碼風格上的沖突,進而帶來潛在的風險。為了提高代碼的可讀性和可維護性,降低風險,我們需要確保在整個代碼庫中保持一致的代碼結構和規范風格。
基建混亂
在業務組件基建和服務基建方面,由于缺乏統一的最佳實踐范式,導致使用層的代碼出現混亂。這一問題亟待解決,以確保代碼的整潔性和可維護性。
工程效率
管理缺乏統一性,功能分散,導致功能可用性低下。
性能債務
- 解決由持續SDK升級觸發的報警問題
- 優化內存管理
- 清理未使用的資源和已下架的代碼
- 實施lint代碼質量檢查與治理
- 進行空安全適配(針對Flutter框架)
目標
產物目標
一套簡易可視化運營平臺
- 結合Lean平臺,對Lean平臺錄入信息,通過腳本產出自定義報告。
- 增加巡檢能力,周頻次跟進問題狀態。
穩定性目標
沉淀問題,整合債務
通過深入剖析問題和細致整合債務,將技術債務治理提升為確保系統穩定性的關鍵環節。
質量目標
提高代碼質量
- 提高代碼質量,確保代碼符合Lint標準。
- 完成Flutter的空安全適配。
面對挑戰
業務挑戰
- 穩定性的設計需要針對老業務流程進行二次梳理,如何保證線上穩定性是關鍵。
- 在需求中不斷植入Fix的問題,確保技術債務的及時解決。
技術挑戰
- 優化思路和設計需要更全面的考慮。
- 如何通過架構設計更完美地落地修改和重構。
- 對技術的深入理解是實現更好方案的基礎。
治理方案
債務整體架構
圖片
方向:通過對當前問題的歸納,合理劃分技術債務的治理方向
- 業務架構:主要以業務代碼實現為主,最佳范式等;
- 基建:對接底層基建能力,使用上不合理不舒服的點。
- 代碼:實施代碼規范、Lint治理和代碼格式化。
- 效能:所有輔助程序運行的腳本能力。
治理運營:一套可持續運行的方案
任何人不管問題的大小,都可以暢快的提出問題(不是誰提出誰修改,你只管提),把痛點問題進行描述,通過Lean平臺記錄,并會有專門的人(提出人)標記方向(分類),負責的同學或者感興趣的同學都可以進行認領,并做出合理的方案和同步進度。
沉淀:
通過這些點沉淀能力,不斷的下沉能力,解耦業務。
建設:
- 非開源:可以按照產物進行成果分享。
- 開源:是最好的狀態,開源我們一些厲害的能力,無論是什么方向的結果。
債務治理機制
為了解決這些問題,我們決定采取一系列措施來優化我們的項目和技術棧,并最終沉淀出一套我們可執行可長期運營的方案。
圖片
識別
- 技術的持續改進離不開團隊中每個人的努力,因此需要每個成員都積極參與。在日常交付中,團隊成員應該持續識別和記錄需要改進的問題并將其放入Lean平臺中,以便在技術改進會議中與團隊同步。
- 此外,團隊還可以定期組織頭腦風暴,以收集技術痛點和改進建議。
可視化平臺
通過一個共享平臺,我們可以高效地錄入和展示信息,從而更清晰地一覽所有問題的分布情況和各類問題的占比。這樣的設計不僅提升了工作效率,還使得數據分析更加直觀、便捷。
優先級
我們時常會遇到的問題是,需要改進的地方太多,尤其是對于遺留系統。怎么辦?先排優先級。我們可以基于價值/成本矩陣來評估改進任務的價值和成本。
圖片
基于矩陣:
- 優先解決高價值+低成本的技術債。
- 嘗試將高價值+高成本的技術債拆分為高價值+低成本的技術債,“盡早、頻繁、小批”地進行PDCA(Plan/Do/Check/Adjust)的迭代解決。
- 在沒有高價值+高/低成本的技術債時,再來考慮低價值+低成本的技術債。
- 最后如果只剩下低價值+高成本的技術債,還是先拆分,再解決,或可考慮直接移除。
執行
債務問題,是無法集中清理的,每個人每天都有自己的業務需求,所以我個人認為可以存在兩個進度方式:
- 在版本跌在中,引入20%的工作量進行技術任務的改進。
- 在技術架構升級或者重構等方案中,評估債務任務的清理。
總結&公式
- 每周固定時間進行報告產出。
- 存在這個能力,就能更好的整體觀測治理的大盤,有助于促進治理的節奏,不會石沉大海。
- 讓債務問題成為一個話題榜,成為一個論壇貼。從枯燥變成一種可持續輸出知識點的平臺。
我認為在技術債務管理中,這一步是很重要的,我們需要分享解決的思路和成果,它是具有價值的,分享的過程是信息同步也是團隊認知的對齊。
圖片
總結
通過這套精心設計的治理機制,我們能夠高效地對問題進行細致分類,并實現有條不紊的治理。結合先進的可視化平臺Lean+報告產出平臺,我們可以實時追蹤問題的處理進度。這一機制不僅幫助我們成功解決了問題,還促進了寶貴知識的積累和共享,形成了豐富的知識庫。
穩定性方向沉淀
公司層面一直在推進穩定性,通過事前、事中、事后三個階段進行預防、監控、復盤總結,形成一個閉環流程。
圖片
在技術債務治理方面,我認為它扮演著事前過濾器的重要角色。通過運用技術債務治理的手段,我們可以有效地識別并處理許多潛在隱患,從而為系統的穩定性奠定堅實基礎。
在整體穩定性的三個階段中,事中和事后階段能夠持續揭露技術債務問題的多維面貌,并對其進行系統歸納與整理。這些寶貴的經驗教訓隨后被轉化為事前階段的預防性過濾網,從而助力我們更加精準地預防和應對未來潛在的問題挑戰。
總結
在事中、事后階段,我們要能夠及時發現并沉淀歸納債務問題,確保問題留痕、總結到位,并達成共識,以便更出色地完成事前規劃的任務。
代碼質量治理
lint治理
從此時此刻起:債務問題不再新增,趨勢線逐步下降;
嚴格執行代碼規范、CR機制、Dlinter統一規范,提交高質量代碼。
圖片
工程配置規則、遠程代碼配置規則開啟,自動reject。(Flutter 配置為主)
圖片
空安全適配(Flutter)
我們強烈建議你按順序遷移代碼,先遷移依賴關系中的處于最末端的依賴。例如,如果 C 依賴了 B,B 依賴了 A,那么應該按照 A -> B -> C 的順序進行遷移。
圖片
遷移時序層
從底層服務類出發,逐層向上適配。
圖片
總結
技術債務是項目進程中難以避免的現象,然而,如何將其控制在可管理范圍內,卻是我們必須深思的問題。要想有效預防和化解技術債務,離不開優秀開發人員的貢獻,而團隊的協同合作更是至關重要。借助這套精心設計的治理機制,我們能夠對各類問題進行科學分類和有序治理。同時,結合高效的可視化平臺,我們可以實時追蹤問題進展,不僅及時解決現有問題,還能在此過程中積累并提煉出大量寶貴的共享知識資源。
結論
技術債務在現代軟件開發中屢見不鮮,然而,借助高效的治理策略與團隊的協同合作,我們完全有能力將其潛在影響壓縮至最小。不懈的學習與持續的改進乃是項目取得成功的基石,唯有如此,我們方能在日新月異的技術浪潮中穩立潮頭,保持強勁的競爭力。
技術債務是一個普遍存在的問題,它不受平臺或編程語言的限制。我們應該共同努力,不斷學習和提升自己,以應對這一挑戰,共同推動技術進步。