作者 | ALEX EWERL Ö F 譯者 | baoyu.io
出品 | CSDN(ID:CSDNnews)
任何長期維護軟件的人都會意識到,随着時間的推移,軟件似乎逐漸 " 腐朽 "。防止這種情況的發生,需要付出刻意的努力。本文我将分享一個團隊如何成功應對這一挑戰,并提供一些實際的操作建議。
所謂的軟件腐朽或軟件熵主要表現爲幾個症狀:
平均故障間隔時間(MTBF)縮短:軟件出錯的頻率增加,發生的故障也越來越多。
實施時間(LT)延長:對于價值相似的功能,從實施到審查,再到部署和發布,所需的時間随時間增長而加長。
效率降低:價值與投入的比率下降。
修複或補救時間(TTR)延長:修複軟件缺陷以及确保問題不再發生的時間變長。
首次提交時間(TTFC)延長:這是衡量新人适應代碼庫效率的多個指标之一。
其根本原因一般包括:
外部因素:運行環境、操作系統、依賴組件随時間變化,需要開發者做出相應的調整。
内部因素:程序錯誤、配置偏差、技術債務。
混合因素:需求和用戶的期望變化速度超過團隊用現有代碼滿足這些需求的能力。
在所有這些原因中,技術債務是開發團隊可以主動控制和解決的部分。
技術債務就像是你的代碼庫的信用卡:容易積累,但擺脫起來卻非常困難。
—— Juan Jose Behrend
技術債務就像是你的代碼庫的信用卡:容易積累,但擺脫起來卻非常困難。
我不打算在這裏重複互聯網上已有的信息:
Martin Fowler 提出了 4 種技術債務類型
Gergely Orosz 在 2020 年寫過關于實用的中間立場
David Pereira 談論了産品經理的觀點
Devopedia 有關技術債務曆史的頁面。
維基百科列出了技術債務的原因。
相反,我将分享一個最成功的處理技術債務的案例,并在文末提供一些實用的建議。
故事
多年前,我和一個 12 人的工程師團隊共事,他們負責兩個大型全棧應用程序。每個應用程序都有超過 18 萬行源代碼(SLOC),這還不包括代碼中的依賴項、注釋和空行,但包括了測試代碼。
這些代碼是幾年前爲一個定制解決方案構建的 " 平台化 " 過程的結果。公司曾經有多個解決同一問題的方案,最終合理地選擇了最成熟的一個,将其轉化爲一個通用平台,并組建了一個由頂尖工程師組成的團隊來負責。
這就催生了所謂的 " 内源 " 巨型單體架構(也就是共享代碼庫),大約有 150 多人在這個項目中協作。
那時,我從公司的另一個部門調過來。在技術(Tech)、領域(Domain)和人員(People)這三個方面,我對技術和人員很熟悉,但對業務領域相對較新。
我的挑戰從第一天就開始了。我發現自己難以理解代碼庫,感到非常沮喪。那時我已有 19 年的編程經驗,其中最後七年都在專注于這些應用程序所使用的技術。
盡管我的經驗似乎比團隊中的其他成員都要豐富(至少從紙面上看是這樣),但即便是簡單的任務也比我預期的要花費更多的時間。這讓我感到自己既無能又無助。
幸運的是,原始代碼庫的一些創造者仍在平台團隊中,并給了我總共 2 小時的介紹。這段介紹不僅幫助我理解了代碼,更讓我了解了項目背後的曆史、團隊心态以及塑造這些代碼的更廣泛的背景因素。
你看,領導層并不關心代碼的質量,隻要按時完成任務就行。爲了趕工期,常常有代碼質量被犧牲,測試被忽略。我記得牆上甚至挂着這樣一個标志:"fuck it, ship it"(随它去吧,趕緊上線),其中 "ship" 一詞被一艘船的圖片所替換。
fuck it, ship it
我沒有向他人表達我的感受。顯然,邀請我加入團隊的高級主管(來自我之前所在的部門)可能有他的考慮。也許這是一個考驗,看我會如何應對?作爲新人,我需要建立自己的信譽,然後才能引導團隊進行改變。正如我經常說的:" 在嘗試改變之前先去理解。" 在我的眼中,代碼和團隊成員是緊密相連的,你無法用技術手段解決文化層面的問題。
我爲團隊做出的第一個真正貢獻,是在牆上挂了一張幽默的圖片。這張圖片上寫着 " 臨時解決方案,你在開玩笑嗎?" 它受到了團隊的歡迎。
臨時解決方案,你在開玩笑嗎?
如果是現在,我可能會在牆上挂上這樣一張圖片:
你聽說過破窗理論嗎?在軟件維護的語境中,這意味着:技術債務越多,對新開發的關注就越少。
換句話說,随着時間的推移,技術債務帶來的負面效應會逐漸累積。
理念
我發現,并不隻有我一個人對技術債務感到沮喪。在連續幾次的回顧會議中,技術債務問題一直被提出,直到管理層決定正視這一問題并采取措施。
因此,我們舉行了一個研讨會,深入探讨這個問題:了解其發生的原因以及我們如何能夠掌控它。在團隊的坦誠對話中,我對他們的尊重有了新的提升。事實證明,在壓力山大的日常中,他們幾乎沒有時間去整理這些混亂。這是出乎意料的。我加入時,代碼就像是一個搖搖欲墜的建加塔:
建加塔倒塌
他們非常清楚這個問題,但主要難題是缺乏時間和對最佳實踐的認識。
來源:Twitter
回想起來,一位開發者曾這樣說:
技術債務太多了,我們應該停下所有日常工作,花上六個月時間去解決這個問題。
項目經理(PM)反駁說:
但我們不能這麽做。那誰來維護産品,增加新功能呢?在償還技術債務的同時,我們是否可以将工作分解成更小的部分,與日常任務并行進行,逐步加班完成?
另一位開發者提出:
要我清理代碼,我就得有專門的時間,而這個時間不能是原本計劃用于修複 bug 或開發新功能的。
還有一位開發者建議:
如果我們能共同協作清理,那就太好了。我們可以一起找出最好的方法,分攤那些機械性的工作。讓一個人單獨承擔清理工作是不公平的。而且,如果隻有一個人負責技術債務,我們可能還會制造出更多的債務。
工程經理(EM)提出:
我們需要對這項活動進行時間限定,以免占用本應用于開發新功能和修複 bug 的時間。你們認爲花在解決技術債務上的時間應該是多少?
經過一番讨論,大家達成了每周投入一天時間的共識,相當于團隊總工作量的 20%。
項目經理(PM)質疑:
你們是說,我們必須用掉我們 20% 的時間,僅僅是爲了保持現狀?
這之後出現了一段尴尬的沉默,好似在問:" 你願意降低 20% 的薪水嗎?"
項目經理(PM)繼續說:
我們還有很多待辦事項需要完成,所以我們需要一個平衡兩種任務的折中方案。那 10% 怎麽樣?
接下來的事情就成了曆史。" 技術債務星期五 " 由此誕生。爲什麽是星期五?我已不太記得,但這可能與一些人星期五休息有關,實際上,這意味着技術債務并不會确切地占用 10% 的時間。不過,這依然是一個勝利!✌️
這個過程經過幾次調整才逐漸完善。但在我離開團隊的最後一年裏,它保持不變。即使工程經理和項目經理更換了,團隊也成功地讓新經理适應了這個 " 傳統 "。
實施細節
我們每兩周舉行一次 " 技術債務清理日 "。這些日子不是爲了解決具體的問題或任務而設立的。我忘了複制詳細的政策,但它大緻是這樣的:
我們将 10% 的時間用于處理技術債務。
最重要的原則是盡量不産生技術債務。
産生技術債務的代碼提交(Pull Request)應該伴随一個解決方案的問題登記。
所有技術債務工作都要作爲問題記錄下來,并标記爲 "tech-debt"。
我們在同一天集中處理技術債務,并盡量減少當天的會議安排。
建議(但非強制)在下次團隊展示時展示處理結果。
在修改代碼以解決技術債務時,記得添加或更新相關的測試和文檔。
工程師們對技術債務清理日充滿期待。團隊會提醒管理層,這一天不能用于安排常規的功能開發或錯誤修複工作。盡管我們順便修複了一些錯誤,但主要目的是爲了降低未來功能開發的成本,同時提升系統的可維護性和可靠性。
最初,将團隊 10% 的時間用于處理技術債務似乎難以說服人,但時間證明了這做法的巨大回報:
我們盡可能快地分攤并清償了這些債務,通常在不到 10 天内完成。
由于缺乏固定的問題和任務分配結構,這些日子成了我最喜歡的集體編碼時光。我們一起深入探讨代碼庫,了解其背後的曆史。
我們發現,一些看似明顯的技術債務其實最好保持原狀,如果有更好的文檔的話。對于那些我們決定不去改動的代碼,我們進行了詳細記錄。
漸漸地,我們學會了如何應對這個系統。定期處理技術債務使我們更加注重在一開始就避免産生它。因此,我們能夠把技術債務清理日用于更有價值的工作,例如改善測試、代碼審查或優化 CI/CD 流程,以減少錯誤發生或降低其成本。
協同處理技術債務使我們能夠更快地完成日常工作,因爲我們對代碼有了更深入的共同理解,而且代碼更易于操作。這可能被視爲集體編碼的積極成果,但沒有具體議程也增強了自主性,從而激發了創造力。
對代碼設計和架構的清晰理解使我們在時間緊迫時做出更明智的決策。我們更清楚地知道處理技術債務需要付出什麽,以及爲了加快交付速度而從未來借用時間是否值得。
管理層逐漸開始欣賞這種做法,因爲技術債務不再幹擾常規工作,也不會導緻令人尴尬的不必要問題。此外,這種自由和信任提升了團隊士氣。團隊被尊重并被視爲成熟的團隊成員,因此表現也更加成熟。
公司中的其他團隊也開始嘗試實行 " 技術債務清理日 "。
結論
僅僅因爲代碼能運行,并不代表它就是正确的實現方式。代碼的複雜結構很難直觀展現給決策者(如項目經理 PM),這使得他們難以抽出時間來解決問題。這樣怎麽辦呢?
技術債就像是快餐一樣。在别無選擇時,它或許是個不錯的臨時方案,但必須通過不斷的努力來減少它帶來的負面影響。
從這個角度來看," 代碼膨脹 " 完全有可能成爲一個現實問題!
技術債可被視爲 " 短期目光的代價 ",因爲隻有片面且短視的思維才會忽略它。
《富爸爸窮爸爸》的作者羅伯特 · 清崎曾經指出:
壞的債務是那種讓你損失金錢的債務;好的債務則能幫你賺錢。
對于技術債務也是如此,它分爲好的和壞的兩種:
好的技術債務是一種深思熟慮的權衡,旨在快速獲得成果。它像是加速發現的工具,并應盡快還清。
壞的技術債務通常與消極态度有關,它是因懶惰而推遲必要工作,而且沒有明确的好處。這就像爲了一時的滿足而借錢買昂貴的鞋子一樣!
如果你無法承擔其後果,那就不應該産生技術債務。技術債務未償還的兩大原因通常是:
工程能力不足:指的是低估了創建一個可維護産品所需的工作量。
領導力缺失:如果工程師需要向管理層證明償還技術債務的必要性,那麽就應該反思管理層的存在意義。
遺憾的是,能力不足的工程師和領導往往相互依存,就像門與門框一樣緊密相扣。打破這種共生關系很難,有時候選擇離開,加入一個真正重視軟件可持續性的團隊會是更明智的選擇。