高品質軟體,真的卡貴嗎?

軟體內部品質顧好,程式碼乾淨好改,長期成本卡省錢

高品質軟體,真的卡貴嗎?
Photo by Alexandr Podvalny / Unsplash

軟體開發專案中,常常爭論到底要花時間提升軟體品質,還是衝功能。大多時候,趕著推出功能的壓力比較大,很多工程師都會抱怨沒時間顧架構和程式碼品質。

貝特里奇標題定律 講的是,標題用問號結尾的文章,答案通常是否定的。認識我的都知道,我喜歡打破這種定律。這篇文章不只這樣,我還要挑戰問題本身。這個問題預設了品質和成本之間的取捨,但我認為,高品質軟體的製作成本其實比較低。

雖然我大部分文章的讀者是專業軟體工程師,但這篇不會預設讀者有軟體開發的背景知識。我希望這篇文章對所有在軟體領域工作的人都有幫助,尤其是軟體開發團隊的客戶,例如企業主管。

品質和成本,魚與熊掌?

如同開頭所說,我們都習慣品質和成本之間的取捨。買手機時,貴的型號處理器快、螢幕好、記憶體大;如果預算有限,就只能犧牲部分品質。當然,有時候也會有俗擱大碗,但通常品質越好,價格越高。

軟體品質,眉角多多

講到軟體品質,我們得先定義它。問題來了,軟體品質的定義很多。使用者介面好不好用?會不會一直出錯?架構清不清楚,工程師能不能快速找到要改的程式碼?

這些例子只是冰山一角,但重點是,有些品質是使用者有感的,例如介面和錯誤,但有些是使用者感覺不到的,例如架構。

我把軟體品質分成 外部品質(例如使用者介面和錯誤)和 內部品質(例如架構)。使用者可以判斷外部品質,卻感受不到內部品質。

內部品質,使用者看不到就不重要?

既然使用者看不到內部品質,那它重要嗎?假設我和麗貝卡寫了同一個航班預測 App,功能、介面、錯誤都一樣,差別只在於她的程式碼乾淨整齊,我的亂七八糟。另一個差別是,我的 App 賣 6 塊美金,她的賣 10 塊。

使用者看不到程式碼,程式跑起來也一樣,為什麼要多花 4 塊錢買麗貝卡的 App?換句話說,提升內部品質似乎不划算。

所以,投資外部品質有道理,投資內部品質沒道理。使用者可以判斷要不要花錢買更好的介面,卻不知道內部架構好不好,更別說判斷值不值得花錢。既然如此,工程師為什麼要花時間提升內部品質?

內部品質好,改程式才快

那為什麼工程師這麼在意內部品質?因為他們大部分時間都在改程式碼。即使是新系統,幾乎所有程式都是在既有的程式碼基礎上修改。要加新功能時,首先要搞懂它要怎麼加到現有的程式裡,還要知道資料是什麼意思、彼此的關係,以及需要加哪些新資料。

這些都跟理解程式碼有關。但程式碼很容易變得難懂。邏輯可能很亂、資料看不懂、變數名稱對半年前的 Tony 來說可能很有意義,但對我來說就像他離職的原因一樣神秘。這些就是工程師說的 cruft,也就是程式碼跟理想狀態的落差。

Cruft 常被比喻成 技術債。加新功能的額外成本就像在付利息,整理 cruft 就像在還本金。雖然這個比喻很貼切,但也讓人誤以為 cruft 很好衡量和控制。

內部品質好,程式碼就容易懂,改起來也比較快。如果程式碼模組化,就不用看幾十萬行程式碼,只要看幾百行就好。如果命名清楚,就能快速理解程式碼的功能,不用在那邊猜。如果資料結構和商業邏輯一致,就能輕鬆理解資料的意義。Cruft 會增加理解程式碼的時間,也更容易出錯。如果發現錯誤,就要花時間除錯;如果沒發現,上線後就會出問題,又要花更多時間修。

修改程式碼也會影響未來。可能為了趕時間,用了一些破壞程式架構的方法,雖然現在快,但之後其他人改程式碼就會變慢。如果大家都這樣做,程式碼很快就會累積一堆 cruft,到時候一點小修改都要花好幾週。

使用者在意的是新功能出的速度

這就是為什麼內部品質對使用者很重要。內部品質好,加新功能就快,成本也低。我和麗貝卡的 App 現在一樣,但接下來幾個月,麗貝卡可以每週加新功能,而我還在跟 cruft 搏鬥。我的速度比不上她,她的 App 功能很快就比我多,到時候使用者就會跳槽,麗貝卡還可以漲價。

內部品質的影響

內部品質的重點是降低未來修改的成本。雖然一開始要多花點時間,但長期來看是值得的。

我用一張圖來表示,橫軸是時間(成本),縱軸是累積功能。大部分軟體專案的曲線如下圖:

內部品質差,一開始進度很快,但後來加新功能就越來越慢。即使是小修改,也要花很多時間理解程式碼,還容易出錯。

注重內部品質可以避免這種情況。有些團隊甚至可以越做越快,因為可以重複利用之前的程式碼。但這種情況比較少見,需要團隊很厲害而且紀律很好。

要注意的是,一開始內部品質差的團隊進度比較快。這時候品質和成本之間的確有取捨。問題是,這個優勢可以維持多久?

這張圖只是示意,因為我們沒辦法衡量軟體的功能和生產力。就像律師或醫生的生產力也很難衡量。

我問過很多厲害的工程師,他們的經驗是,品質差的程式碼幾週內就會開始拖慢速度。所以,品質和成本之間的取捨期很短。即使是小專案,也要注重軟體開發的品質。

再厲害的團隊也會產生 cruft

很多人,包括一些軟體業的人,以為 cruft 是因為團隊不小心或犯錯造成的。其實,再厲害的團隊也會有 cruft。

我認識一個很厲害的技術主管,他完成了一個很成功的專案,客戶很滿意,團隊也很開心。但他說系統架構不夠好。我問他:「怎麼可能?你不是最厲害的架構師之一嗎?」他的回答是:「我們做的決定都是對的,但現在才真正了解應該怎麼做。」

很多人把寫程式比作蓋房子,所以才會有「架構師」這個職稱。但寫程式跟蓋房子不一樣,充滿了不確定性。客戶一開始也不知道自己要什麼功能,都是邊做邊學,尤其是早期版本上線後。軟體開發的工具,例如程式語言、函式庫、平台,每隔幾年就會有大改變。如果蓋房子也這樣,客戶可能會在房子蓋到一半時加樓層或改格局,而且水泥的成分每兩年就會變一次。

DORA 精英團隊研究

軟體開發中,不只品質和速度之間的取捨是錯的,快速開發和系統穩定之間的 雙峰 選擇也是錯的。DevOps 狀態報告 的科學研究證明了這一點。

他們分析了多年的問卷調查,發現頂尖團隊每天可以多次更新程式碼,而且從開發到上線不到一小時。他們的錯誤率比其他團隊低很多,而且復原速度也很快。此外,頂尖團隊的組織績效也比較好。

軟體專案常常都在開發新東西,很少有機會處理已經解決過的問題。我們都是在開發的過程中學習,所以很多團隊都是做了一年後才真正了解系統架構應該怎麼設計。即使是最厲害的團隊,也會有 cruft。

差別在於,頂尖團隊產生的 cruft 比較少,而且會定期清理,所以才能持續快速開發新功能。他們會寫自動化測試,快速找出問題,減少除錯時間。他們會定期重構,避免 cruft 累積。持續整合也可以避免團隊成員互相衝突,減少 cruft。就像煮菜一樣,不可能不把廚房弄髒,但如果不清乾淨,髒東西乾掉後更難清,還會影響下一道菜。

高品質軟體,省錢又有效率

總結一下:

  • 忽略內部品質會累積 cruft。
  • Cruft 會拖慢開發速度。
  • 即使是頂尖團隊也會產生 cruft,但他們會控制 cruft 的數量。
  • 內部品質好,cruft 就少,開發新功能也比較省時省力。

可惜的是,很多工程師不太會跟管理層解釋這件事。我常常聽到工程師說:「老闆不讓我們寫高品質的程式碼,因為太花時間。」他們常常用專業精神來合理化對品質的要求,但這也暗示了品質是有代價的。結果就是,程式碼品質差,工程師的工作變難,客戶也要花更多錢。所以,我們應該用經濟效益來說服老闆,內部品質好,未來開發成本就低,寫好程式碼其實比較省錢。

這就是為什麼這篇文章標題的問題沒有意義。高內部品質的軟體成本是負的。品質和成本之間的取捨,在軟體內部品質上不適用。(外部品質,例如使用者體驗,還是適用。)因為品質和內部成本之間的關係很特別,不容易理解,但了解這一點對提升軟體開發效率至關重要。

衡量低內部品質的影響

(新增:2024-01-29)

前面有提到,我們不知道怎麼衡量內部品質和生產力,所以很難用數據證明內部品質的重要性。但近年來有一些相關研究。

Adam Tornhill 和 Markus Borg 的研究蠻有意思的。他們用 CodeScene 這個工具分析了 39 個程式碼庫,發現低品質程式碼的除錯時間是高品質程式碼的兩倍多,而且錯誤率高了 15 倍。