關於技術債的溝通與管理

某次在一個技術社群中分享關於敏捷的議題,演說後有一位年輕夥伴問了我一個問題:「公司內有很多 legacy code,架構疊床架屋,時常改A錯B,跟老闆溝通了很多次,但始終排不進去工作中,永遠都被業務的需求排擠,在這種公司工作,很無奈,怎麼辦?」
我告訴他:「這是很棒的一件事,技術債是屬於活下來的公司,而技術債會愈來愈嚴重,某種程度也代表公司還在成長與發展,正面來看是一件好事。」
我也跟他分享了我看過的各種可怕技術債,但這些滿滿技術債的公司,它們卻是逐年在成長,而且活得還不錯。如果技術債是不好的,那為何這些公司沒有因此而倒閉呢?
「你怎麼看待『債』這種東西?它一定得償還嗎?」
如果你跟銀行借款,當你手上有錢的時候,你會立刻一次還清嗎?還是你會逐月逐月還,然後留些錢在手邊作其他用途呢?我相信多數人會選擇後者,留一部分的錢在身邊。為什麼呢?很大一部分原因是因為那些債並沒有立即償還的迫切性,也就是說選擇負債,但讓手邊有充足現金,對自己來說,有時是相對聰明的選擇。
對產品團隊來說,開發資源就如同手上的現金,這些資源是投入在償還技術債,或者開發新的需求,一樣也得從價值的角度來思考。
債,不是一定得立刻還,還不還得看它的價值。
技術債償還的必要性
所謂的技術債(technical debt)成因很多,最常見的是壓縮時程趕工所導致,例如本來一個專案任務得花2個月才能完成,但因為公司面對市場的時程要求得在1個月內完成,壓縮掉的1個月,如果也沒有做妥善的範疇控制(scope management),也就是減少工作內容,讓工作量減少到1個月可完成的分量,而是要團隊在1個月內完成2個月的工作量。
這種狀況下團隊必然得選擇其他 workaround 來解決問題,而 workaround 畢竟不是正規解法,這些不太好的解法都在為系統埋下長期的問題,在軟體架構領域最常用的描述詞就是「疊床架屋」,現在只是維持了一個恐怖平衡,但隨著堆疊的高度愈高,風險也愈高,而且一旦崩毀所帶來的損害也愈大。
之前公司因為發展快速,沒有太多的時間停下腳步來處理技術債,許多的問題反覆出現,但工程師們往往都是用 workaround 來處理,例如直接下 SQL 更新資料、重啟服務、釋放資源、重啟主機、寫死代碼等,這些問題都隨著客戶數量增加、資料增加、開發團隊更動代碼頻率提高等各種原因持續惡化,而維運人員則疲於奔命的東補西補...
五成的時間花在 workaround,五成的時間花在開發新功能,技術債?誰理啊。
除了這種典型的技術債外,還有架構設計不良所造成的可怕債務,當時的四個產品,功能其實有 9 成像,但這幾個產品的底層架構都不太一樣,甚至連 table schema 也有不小的差異。
這種問題挺常見的,在團隊沒經驗時所做的第一個產品,通常架構都挺糟糕的,而當團隊有機會做第二個產品時,會想將第一個產品做不好的地方徹底解決,因此第二個產品在架構上通常與第一個差異很大,這有個專有名詞叫第二系統效應。
而第二系統效應不只出現在第二個產品,連第三與第四個產品也都有這樣的狀況在,接手的人總想用新的架構來做新產品,因此四個產品有四個架構,要上一個新功能,必須要做四次開發工作,分四次上線。
第一個產品花1個月做完新功能,其他三個產品要花額外的 2-3 週來完成,明明是一樣的功能,卻要做四次。
這種架構的技術債,在任何有經驗的人眼中看來都是必然要被解決的,但老闆與業務部門通常認為這是技術部門應該解決的,一般不會主動要技術部門排入專案計畫中。這意味著,改善架構這件事不會發生。
連看起來這麼關鍵的問題,都不被納入考慮,技術部門還能怎麼辦呢?我建議,你必須試試更有效的溝通方法。
技術債殺不死你,但會持續帶來商業損耗
我出社會後負責的第一個產品本身就是一個充滿技術債的產物,技術架構設計本身不錯,但經過幾代人的維護與修改後整個設計邏輯凌亂,維護難度非常高,加上一些深埋底層的架構謬誤在我接手一年後開始大量爆發,系統不穩且效能不好,但在那個時候,我們已經有上千家客戶在使用這個產品,也不是說改就能立刻改。
但不改也不行,因為每天都會有許多來自於客戶的客訴,而客服部門跟業務部門也都把我當箭靶打,後來的一年,我的日子就在每天處理客戶問題,並一邊重構整個技術架構的過程中渡過。
但我對自己的這段經歷感到慶幸,因為這段時間讓我有機會重新思考一個好的技術架構應該長怎麼樣,也讓我對技術架構的理解提升了好幾個等級,我甚至相信,沒有重構過爛 code 的工程師通常很難成長成一個可靠的工程師。
而這樣看起來滿滿問題的技術平台,還是成長到了 2,000 家以上的客戶數,從這邊我們也可以得知,其實技術債殺不死產品,真正殺死產品的是缺乏好的市場策略。
多年後我轉換跑道到 TutorABC,我剛去的時候也驚訝我們竟然可以用這樣落後的技術與管理方法成長到一年數十億的營收,同時也訝異我們團隊竟然可以持續用各種 workaround 來解決日復一日的問題,但即便是如此落後,我們的市場成長速度並沒有因此緩下來,我進去的前一年它們才達成了 300% 的成長,所以你說技術債真的會殺的死一家公司嗎?我不這麼認為。
技術債最大的問題是帶來更高的修改與維護成本。
我前面提到,我在 TutorABC 的早期,我們有很多技術債,光是花在處理緊急問題的人力大約就佔整個 RD 團隊 1/3 以上,而當時我們共有約 60 個工程師,而隨著市場規模變大,需要投入維護的人數只會增加,成本也是持續上升的。
除此之外,我們的四個產品,功能大同小異,但因為底層設計不同,所以每次要發布一個功能更新,RD 團隊得修改四次、測試四次、發布四次,中間花費的人力成本巨大,而錯過的市場時間一樣寶貴,如果我們可以提早3週上線,或許我們有機會多增加幾千萬的營收。
其實技術債在公司規模小的時候你真的感受不到痛,但此時要修正它也是相對容易的,但隨著公司規模長大,持續累積下來的技術債也可能會長成一個大怪獸,它會像寄生蟲一樣跟公司一起長大,影響也會逐漸加劇。
所以,身為產品經理,能強烈感受到技術債的痛其實是一種成就感,代表你的產品已經成長到一定規模了,先開心三秒鐘,然後再回過頭來面對技術債。
我是這麼溝通技術債的
過去我看技術團隊在跟老闆溝通技術債時,大多從技術觀點來提,例如多花了工程師多少時間,可能的系統風險等,老闆聽完這些普遍的反應是「感覺挺重要的,但我覺得還是開拓業績的專案更重要。」
在溝通技術債時,務必把技術債當成需求的一種,用價值的角度來切入將償還技術債排入當前任務的必要性。一般而言,技術債的嚴重性若只有技術人才能理解,那就很難排入 top priority,我們必須用商業的語言來溝通才有機會,什麼叫商業的語言?那就是效益,所謂的效益不能是系統穩定性、效能提升、錯誤率降低這種含糊的用詞,請務必精準到收入、成本這類容易被量化與理解的數字。
舉例來說,以系統穩定度為例,原先的說詞是,這個問題偶爾會發生,每次發生時用戶會出現服務中斷問題,過去幾個月來發生的頻率愈來愈高。這段說詞貌似問題不大,但仔細想想,這段話完全無法讓我們了解問題的嚴重性,也絲毫感受不到它被解決的價值會有多大,交涉顯然是無效的。
如果我們換個說法:
這個問題從去年 1 月開始發生,2017 年共發生了 16 次,2018 年到目前為止共發生了 58 次,兩年下來總共影響了 62 萬人次的使用,其中有 50,000 個受影響用戶在問題發生後的 3 天內發生了退費,造成的退費金額約為 5,000 萬,期間帶來的客訴數量約 23 萬件,這是客服中心三個月的客訴總量,以客服中心人數 120 位來算,每位每月的人事成本為 8 萬台幣,額外衍生的人事成本約為 2,940 萬,光退費金額與人事成本就近 8,000 萬,平均每個月約 330 萬。
此外,2018 年的 58 件中有 28 次是發生在最近 3 個月,共影響了 34 萬人次,光是近三個月,退費金額就超過 2,400 萬,問題愈來愈惡化。
第一個重點,掌握數據,讓所有人知道你是真的做了功課,而且明白這個問題的嚴重性;
第二個重點,圍繞著效益,8,000 萬、330 萬,這些都是大家比較能理解的用詞,可以直接拿來對比帶業績或省成本的專案;
第三個重點,說明趨勢正在惡化,所有技術債中最可怕的就是那種會持續惡化與累積的,這種技術債若不趁早解決,時間迫近時便只剩下極少數的時間能應對,屆時的壓力就不可同日而語了。
永遠要記得,用大家能聽得懂的語言來描述技術債的影響性,而別一廂情願的認為其他人天生就該聽懂你說的。
技術債的處理,絕對不是一蹴可幾,沒有辦法一次就搞定後從此就不出現了,身為產品經理,你必須在每個 release 中判斷是否排入一些重構任務,讓產品一邊發展一邊償還日積月累的技術債。
技術債與「過度設計」間的取捨
前面我們提到第二系統效應,這種問題時常發生在有一定經驗的產品經理或技術團隊身上,他們希望有個機會能重新設計一個產品,好一次改掉舊系統的所有問題。
因此在開發第二個系統時,情不自禁地將一大堆想法全部都投注在這個新產品上,最經典的案例就是 Diablo III,因為二代太經典,暴雪團隊為了突破經典,並且希望將二代中所有的問題都解決,因此延宕了 10 年的時間才推出三代,但市場對三代的反應卻不如預期,連火都火不起來。
第二系統效應很容易導致過度設計,過早尋求產品的最佳化,但卻忽略了市場需求是會改變的,我們必須要透過汲取市場回饋來決定如何調整產品以及資源如何投入,當你過早將資源投入在完善產品,而非盡快推出產品,那你就落入了過度規劃過度設計的陷阱中。
這些過度設計的產品功能除了導致短期資源的錯誤投入外,如果之後市場的反應不如預期,團隊還得花時間將這些已經上線的功能改掉,這會導致再一次的重工,反倒成了技術債。
結語
我覺得技術債是一種產品發展過程必然的產物,產品經理可以以平常心看待,但必須要時時跟技術團隊溝通,掌握技術債的累積狀況,並將技術債的償還當成一種需求,並在每一次的 release 中多少償還一些技術債,以免團隊落入技術債泥沼中。
不曉得你有沒有發現,產品經理在處理的種種問題像極了人生呢?需求太多得取捨,要面對的人太多得識別,還有一大堆債務得處理,而這也是為什麼我認為每個人都得具備產品思維的原因了,因為人生就像是打造一個自己期望的產品,想要變成什麼樣的,還得靠你這位產品經理來打造了。
如果你覺得我內容寫得還不錯,歡迎訂閱我的電子報,我每雙週會發送一封電子報到你的信箱。訂閱連結在這,過往的電子報也在這:Gipi電子報
也鼓勵你可以將我的電子報分享給你認為有需要的朋友們,也許你的舉手之勞,將會改變另一個人的思維與習慣。