勁爆觀點即將上演,請做好準備。
我花了不少時間撰寫關於技術債的文章,倡導編寫整潔程式碼,並力求建立合理的架構。我告訴開發人員如何避免技術債務,如何償還技術債務,以及如何與他們的經理協商解決技術債問題。
事情是這樣的:我錯了一部分。
並非指具體的做法──那些做法仍然是好的。甚至也並非指這個術語的所有用法。而是指不加批判地接受這個框架。
技術債不僅被誤解,它本身就是一個根本錯誤的比喻,扭曲了我們對軟體開發的思考方式。更糟的是,我們仍然在使用它,因為它是高階主管唯一能理解的財務比喻,這意味著我們只能用一些實際上掩蓋了問題本質的術語來解釋工程問題。
讓我解釋一下。
沃德·坎寧安在1992年創造了「技術債」一詞,用來描述一種特定場景:故意選擇快速實現方案,並承諾以後會進行重構。就像金融債務一樣,你現在是在藉時間,並承諾以後連本帶利地償還。
但大多陣列織中實際發生的情況是這樣的:
經理: “為什麼這個功能開發時間這麼長?你不是說兩週就能完成嗎?”
工程師: “嗯,我們有很多技術債需要解決…”
經理: “唉,你們為什麼一開始就不寫出更好的程式碼呢?”
就這樣,工程師們成了壞人,成了「累積債務」的人,成了「走捷徑」的人,成了現在拖公司後腿的人。
但這完全是胡說八道。
真正的債務運作方式是這樣的:你去找貸款人,協商條款,簽署文件,並同意償還本金加利息。你理解交易內容,並且同意接受。
技術債?它實際上是如何產生的:
經理: “我們需要在周五之前把這個產品寄過來,用於投資者演示。”
工程師: “時間不夠,無法做好。至少需要三週時間才能把它建好。”
經理: “想辦法解決,我不在乎用什麼方法。”
【三個月後】
經理: “這段程式碼庫一團糟。”
看出問題所在了嗎?工程師們並沒有「借」任何東西。他們並非自願負債。他們被賦予了不可能的任務,並且已經盡力做到最好。而現在,他們卻要為「利息」負責。
這不是技術債,而是管理階層決策帶來的技術後果。
還有一件事讓我很抓狂:把任何舊程式碼都稱為「技術債」。
你那用了四年、還在用 React 16 而不是最新版本的程式碼庫,不是「債務」。你那回傳 XML 而不是 GraphQL 的 API,不是「債務」。你那現在人人都希望是微服務的單體應用,也不是「債務」。
那隻是存在於時間長河中的法典。
需求會變化,平台會演進,最佳實踐會改變,新的框架會出現。你編寫程式碼時的環境與它現在所處的環境已經截然不同。
把這稱為「債務」意味著有人犯了錯誤,意味著疏忽大意,意味著如果工程師們更聰明、更有遠見、更稱職,就不會出現這個問題了。
但軟體並非如此運作。任何事物都不是這樣運作的。你無法預測未來。你無法為尚未存在的需求進行開發。即便你能做到,你也會過度設計,浪費時間建立永遠用不到的彈性。
咱們來聊聊你兩年前做的那個MVP吧。那個現在已經「過時」的MVP。那個「需要重寫」的MVP。那個「阻礙你前進」的MVP。
你知道MVP還做了什麼嗎?它驗證了你的商業模式。它幫你獲得了最初的一千名用戶。它創造的收入讓你能夠進行今天的對話。
如果沒有那些“糟糕的程式碼”,你就什麼都沒有。你會因為等待「完美架構」而倒閉。
但現在它成功了,現在它正在擴展規模,現在你想加快速度…突然間就出現了「技術債」。突然間,那些打造了讓公司得以生存的產品的工程師們,卻因為當初沒有「正確地」開發而受到指責。
這是倖存者偏差和後見之明偏差的混合體,簡直是一團糟。
每一項工程決策都是一種權衡取捨。不是有些決策,也不是大多數決策,而是每項決策。
速度與靈活性
簡潔性與功能性
成熟技術 vs. 尖端技術
自建還是購買
單體架構 vs. 微服務架構
SQL 與 NoSQL
測試覆蓋率與出貨速度
這些問題都沒有「正確」答案,只有「適合我們當前情況、限制條件和優先事項的答案」。
優秀的管理者明白這一點。他們會參與這些決策。他們會說這樣的話:
“我們目前正在優化速度,因為我們需要驗證市場需求。一旦產品與市場契合,我們就會重新審視架構。”
糟糕的管理者會說:
“想辦法解決就好了。”
後來:
“為什麼會有這麼多技術債?”
如果管理者不了解維護成本的累積效應,實際上會發生以下情況:
第一年: “快速發貨!不用擔心程式碼是否完美!”
第二年: “為什麼新功能的開發時間變長了?我們以前發布速度很快!”
第三年: “我們需要停止所有功能開發工作,進行重寫。”
這不是技術債。這是管理階層沒有意識到軟體維護並非免費。他們沒有意識到每個功能都會增加系統開銷,每個依賴項都需要更新,每個 API 都需要版本控制。
工程師早就知道這一點。他們告訴過你。你沒聽,因為你一心只想著下個季度。
好吧。沒錯。有時候工程師確實會偷工減料。我們會省略編寫測試。我們會直接將數值硬編碼。我們沒有妥善處理錯誤。我們會複製貼上而不是進行抽象。
但你知道嗎?這種情況幾乎總是由於外部壓力造成的。
“我們明天演示需要這個。”
“客戶威脅說,如果我們這週不發貨,他們就要終止合作。”
“我們資金嚴重短缺,急需收入。”
即使是真正糟糕的工程決策,通常也是在壓力下做出的,時間有限,資訊不完整,而且來自……等等……管理層的巨大壓力。
好吧,咱們實話實說吧。我不能寫一整篇文章來為工程師辯護,而不去正視一個顯而易見的問題:有時候程式碼確實很糟糕,但這並非管理階層的錯。
有時你會聘請一位這樣的開發人員:
不理解他們使用的語言或框架。
複製 Stack Overflow 上的答案,卻不懂它們
他們寫出了十二層嵌套的條件語句,因為他們從未學過提前還款。
建立包含 5000 行程式碼的 God 類,因為「這樣更容易把所有內容都放在一個地方」。
拒絕學習或成長,因為「我一直都是這麼做的」。
有時候,你的程式碼審查流程有嚴重缺陷,導致這些程式碼最終還是會被投入生產環境。
程式碼審查,對所有事情蓋章批准。
你一定看過這種套路。有人在周五下午 4:45 提交了一個 PR,修改了 23 個文件,總共 847 行程式碼。審核人員掃了一眼,只花了 90 秒,沒發現明顯的語法錯誤,就點擊了“批准”,好開始享受週末。
更糟的是,你有一個「資深」工程師,他有很強的領地意識和防禦心,每個人都不敢給出真正的反饋,因為上次有人建議重構程式碼時,他們收到了一篇 2000 字的文章來解釋他們為什麼錯了,隨後又經歷了三週的 Slack 被動攻擊訊息。
當團隊沒有標準時
有些團隊真的沒有任何編碼標準。沒有風格指南。沒有架構原則。沒有公認的模式。每個人都只是憑感覺做事。
一個人用不可變資料結構來寫函數式程式碼。另一個人用大量繼承編寫物件導向程式碼。第三個人上週發現了依賴注入,現在恨不得把所有東西注入進去。第四個人只想趕緊發布,對這些都漠不關心。
結果呢?拼湊而成的程式碼庫,每個模組都像是出自不同的公司之手。
初級開發人員無人監管
以下這種情況比我們願意承認的要常見得多:你僱用了一位初級開發人員,給他分配了一個任務單,然後……就沒人跟進。他苦苦掙扎了兩週,最終透過反覆試驗弄出了一個能用的東西,然後發布了。它(大部分)都能正常工作,所以就上線了。
六個月後,有人必須修改那段程式碼,結果發現它簡直就是靠著膠帶和祈禱勉強維持著。沒有測試,沒有錯誤處理。變數名稱亂七八糟,只有temp1 、 temp2 、 finalFinal 、 finalFinalActual之類的。業務邏輯、UI 程式碼和資料庫查詢混雜在一起。
這是技術債嗎?這是管理階層的錯嗎?某種程度上是,某種程度上又不是。
管理層未能提供指導和監督。但同時,這位工程師本可以尋求幫助,可以查看現有程式碼尋找規律,可以…你知道的,試試看。
所以問題就出在這裡。因為即使程式碼確實由於工程失誤而有缺陷,「技術債」的說法仍然是錯誤的。
為什麼?因為仍然稱之為「債務」:
將其描述為一種有意為之的權衡(實際上並非如此)
暗示應該“償還”(應該修復)。
掩蓋了根本原因(招募、培訓、程式碼審查或標準問題)。
如果你招了個能力不足的人,那就是招募的問題。如果你的程式碼審查沒能發現問題,那是流程的問題。如果你的團隊沒有標準,那是領導的問題。如果初級程式設計師交出的程式碼難以維護,那是指導的問題。
這些都不是“債務”,而是組織上的失誤,最終表現為程式碼品質問題。
更令人震驚的是:即使是這些失敗,往往也能追溯到管理決策。是誰決定:
寧願聘用最便宜的開發人員,也不願聘用最好的開發人員?
因為候選人“看起來很聰明”,所以跳過面試的技術環節?
不給資深工程師安排時間進行程式碼審查與指導?
從未投入資源建立團隊標準或架構準則?
優先考慮故事點數而不是程式碼品質?
你看,我們最終總是回到管理階層這個問題?
但我們不能完全推卸責任。身為工程師,我們需要對自己的專業負責。我們需要:
認真檢討程式碼,而不是敷衍了事。
像專業人士一樣給予和接受回饋
投資學習與成長
遇到困難時要尋求協助。
即使令人不舒服,也要對 PR 中糟糕的法典提出異議。
團隊合作,建立並維護標準。
如果你在沒看程式碼的情況下就批准了 PR,那麼你也要對那段程式碼負部分責任。如果你因為懶得認真而寫出了糟糕的程式碼,那就是你自己的問題。如果你五年來一直沿用同樣的糟糕程式模式,並且拒絕學習,那麼問題就出在你身上。
差別在於?當我們正視這些失誤時,我們才能真正著手解決它們。我們可以改進程式碼審查文化。我們可以提升自身技能。我們可以建立更完善的實踐。
但是,當我們躲在「技術債」這個模糊的萬能詞背後時,我們就什麼都解決不了,因為我們甚至沒有找到真正的問題所在。
與其說是“技術債”,不如試試這些:
「過去商業決策的技術後果」 —措辭略顯冗長,但準確無誤。這讓責任人承擔了應有的責任。
「維護成本」 ——每個程式碼庫都有維護成本,而且會隨著時間的推移而成長。務必將其納入預算。
「情境轉換」 ——兩年前合理的事情現在可能就不合理了。這沒關係。
「必要的重構」 ——軟體會不斷發展演進。重構是正常的。不要把它當成懲罰。
「學習的代價」 ——你當初並不知道你開發的產品會成功。現在你知道了。是時候進行優化了。
技術債並非神話,因為不存在捷徑。它之所以成為神話,是因為這個比喻已經被曲解得面目全非。
這已成為管理者的一種方式:
將商業決策歸咎於工程師
逃避資源分配責任
將正常的軟體演進視為疏忽
逃避無法完成的截止日期所帶來的責任
優秀的管理者會坦然面對權衡取捨。他們會說:“我們當初選擇了速度而非靈活性,現在需要重新優化。這需要時間和資源。我會合理分配這兩項資源。”
糟糕的管理者會利用事後諸葛亮。他們會說:“你應該一開始就把它做好。為什麼會有這麼多技術債?”
如果你是一位正在閱讀本文的管理者,並且曾經抱怨過技術債務,請捫心自問:你是否給了你的團隊足夠的時間和資源來「正確地」建構它?你甚至知道「正確」的意思嗎?還是你只是想盡快發布?
如果你是正在閱讀此文的工程師,請停止為並非由你所做的決定負責。下次有人在回顧會議上提到技術債時,不妨試試這個方法:
“我們來談談當時做出這些決定時所面臨的種種限制。因為我非常確信,在當時的訊息和時間條件下,我們已經做出了最佳選擇。”
如果他們反駁呢?如果他們堅持說那是你「借」的「債」呢?
開始面試吧。因為你現在的老闆根本不懂軟體開發,遇到困難時他總是會怪你。
原文出處:https://dev.to/adamthedeveloper/technical-debt-is-a-myth-created-by-bad-managers-2l3k