高品質軟體值得花費成本嗎?

2019 年 5 月 29 日



在軟體開發專案中,常見的爭論在於花時間提升軟體品質,或專注於釋出更有價值的功能。通常交付功能的壓力主導了討論,導致許多開發人員抱怨沒有時間處理架構和程式碼品質。

Betteridge 標題定律 是一句格言,表示任何標題或標題以問號結尾的文章都可以用「否」來總結。認識我的人不會懷疑我想推翻這條定律的渴望。但這篇文章更進一步,它推翻了問題本身。這個問題假設了品質與成本之間的常見取捨。在本文中,我將說明這種取捨不適用於軟體,高品質軟體的生產成本實際上較低。

雖然我的大部分文章都是針對專業軟體開發人員,但對於這篇文章,我不會假設讀者具備任何軟體開發機制的知識。我希望這篇文章對任何參與思考軟體工作的相關人士都有價值,特別是那些擔任軟體開發團隊客戶的商業領導者。

我們習慣在品質與成本之間進行取捨

正如我在開頭所提到的,我們都習慣在品質和成本之間做取捨。當我更換智慧型手機時,我可以選擇配備更快速處理器、更好螢幕和更多記憶體的昂貴型號。或者我可以放棄其中一些品質來省錢。這並非絕對的規則,有時我們可以撿到便宜貨,也就是高品質的商品更便宜。更常發生的是,我們對品質有不同的價值觀 - 有些人根本不會注意到一個螢幕比另一個螢幕好在哪裡。但這個假設在大部分時間都是正確的,較高的品質通常需要付出較高的成本。

軟體品質包含許多面向

如果我要談論軟體的品質,我需要解釋一下那指的是什麼。這裡出現了第一個複雜性 - 有許多事情可以算作軟體的品質。我可以考慮使用者介面:它是否能輕鬆引導我完成需要執行的任務,讓我更有效率並消除挫折感?我可以考慮它的可靠性:它是否包含會導致錯誤和挫折感的缺陷?另一個面向是它的架構:原始碼是否被分成明確的模組,以便程式設計人員可以輕鬆找到並了解他們這週需要處理的程式碼片段?

這三個品質範例並非詳盡無遺,但足以說明一個重要的觀點。如果我是軟體的客戶或使用者,我不會欣賞我們會稱之為品質的部分事項。使用者可以分辨使用者介面是否良好。主管可以分辨軟體是否讓她的員工在工作上更有效率。使用者和客戶會注意到缺陷,特別是如果它們會損毀資料或讓系統暫時無法運作。但客戶和使用者無法感知軟體的架構。

因此,我將軟體品質屬性分為外部(例如使用者介面和缺陷)和內部(架構)。區別在於使用者和客戶可以看到哪些因素讓軟體產品具有高外部品質,但無法分辨較高或較低的內部品質。

乍看之下,內部品質對客戶來說並不重要

由於內部品質並非客戶或使用者可以看到的事物 - 它重要嗎?讓我們想像 Rebecca 和我撰寫了一個追蹤和預測航班延誤的應用程式。我們的兩個應用程式都執行相同的必要功能,都擁有同樣優雅的使用者介面,而且幾乎沒有缺陷。唯一的不同是她的內部原始碼組織得井然有序,而我的則是一團亂。還有另一個不同:我以 6 美元出售我的應用程式,而她以 10 美元出售她的應用程式。

由於客戶永遠不會看到這個原始碼,而且它不會影響應用程式的運作,為什麼有人會願意多付 4 美元購買 Rebecca 的軟體?更普遍地說,這表示不值得為了較高的內部品質支付更多費用。

我換個方式說明,就是說用成本換取外部品質是有道理的,但用成本換取內部品質卻沒有道理。使用者可以判斷他們是否願意花更多錢換取更好的使用者介面,因為他們可以評估使用者介面是否好到值得花這筆額外費用。但使用者看不到軟體的內部模組化結構,更不用說判斷它是否更好。何必花更多錢買一個沒有效果的東西?既然如此,為什麼軟體開發人員要花時間和精力來改善他們工作的內部品質?

內部品質讓軟體更容易增強

那麼,為什麼軟體開發人員會把內部品質當成一個問題?程式設計師大部分時間都在修改程式碼。即使在一個新的系統中,幾乎所有的程式設計都是在現有程式碼庫的脈絡下完成的。當我想新增一個功能到軟體中,我的第一個任務就是找出這個功能如何融入現有應用程式的流程中。然後我需要改變那個流程,讓我的功能融入其中。我常常需要使用應用程式中已有的資料,所以我需要了解資料代表什麼,它與周圍資料的關聯性,以及我可能需要為我的新功能新增哪些資料。

這一切都是關於我理解現有的程式碼。但軟體很容易變得難以理解。邏輯可能會糾纏在一起,資料可能難以追蹤,用來指稱事物的名稱可能在六個月前對 Tony 來說是有道理的,但對我來說卻像他離開公司的原因一樣神秘。所有這些都是開發人員所稱的累贅形式,也就是當前程式碼與理想程式碼之間的差異。

內部品質的主要特色之一,就是讓我在了解應用程式運作方式時更加容易,如此一來我就能知道如何新增項目。如果軟體能適當地分成不同的模組,我就不必閱讀所有 500,000 行的程式碼,我可以在幾個模組中快速找到幾百行。如果我們努力使用明確的命名,我就能快速了解程式碼的各個部分在做什麼,而不用費力了解細節。如果資料合理地遵循基礎業務的語言和結構,我就能輕易了解它如何與我從客戶服務代表那裡收到的請求相關。雜亂會增加我了解如何進行變更所需的時間,也會增加我犯錯的機率。如果我發現自己的錯誤,那麼我必須了解錯誤是什麼以及如何修正,這會浪費更多時間。如果我沒有發現錯誤,那麼我們就會產生生產缺陷,並在之後花更多時間修正問題。

我的變更也會影響未來。我可能會看到一個快速加入此功能的方式,但這條路徑與程式的模組化結構相違背,會增加雜亂。如果我採取這條路徑,我會讓自己今天更快,但會讓所有必須在未來幾週和幾個月處理此程式碼的人變慢。一旦團隊的其他成員做出相同的決定,一個容易修改的應用程式就會快速累積雜亂,到最後每個微小的變更都需要花費數週的努力。

客戶確實在乎新功能是否能快速推出

在這裡,我們看到一個線索,說明為什麼內部品質對使用者和客戶很重要。更好的內部品質讓新增新功能變得更容易,因此更快速、更便宜。麗貝卡和我現在可能擁有相同的應用程式,但在接下來的幾個月,麗貝卡的高內部品質讓她能夠每週新增新功能,而我卻卡在嘗試砍掉雜亂,只為了推出一個新功能。我無法與麗貝卡的速度競爭,很快她的軟體就會比我的功能更多。然後我所有的客戶都會刪除我的應用程式,並改用麗貝卡的,即使她能夠提高價格。

視覺化內部品質的影響

內部品質的基本角色是降低未來變更的成本。但撰寫好的軟體需要一些額外的努力,這確實會在短期內造成一些成本。

一種視覺化方式是使用以下的擬圖,我繪製軟體的累積功能與產出所需時間(以及成本)。對於大多數軟體專案,曲線看起來會像這樣。

這是低內部品質會發生的事。一開始進度很快,但隨著時間推移,新增新功能會越來越困難。即使是微小的變更,程式設計師也需要了解大範圍的程式碼,而這些程式碼難以理解。當他們進行變更時,會發生意外的中斷,導致測試時間拉長,以及需要修正的缺陷。

專注於高內部品質是要減少生產力的下降。的確,有些產品會看到相反的效果,開發人員可以加速,因為可以輕鬆使用先前的成果來建置新功能。這種令人滿意的狀況比較少見,因為需要技術熟練且有紀律的團隊才能實現。但我們偶爾會看到。

這裡的微妙之處在於,有一段時間低內部品質比高品質更具生產力。這段時間品質與成本之間會有一些權衡。當然,問題是:在曲線相交之前,這段時間有多長?

在這個時候,我們會遇到為什麼這是擬圖的原因。沒有辦法衡量軟體團隊提供的功能。無法衡量產出,進而無法衡量生產力,這使得無法針對低內部品質的後果(也很難衡量)提出具體數字。無法衡量產出在專業工作中很常見 - 我們如何衡量律師或醫生的生產力?

我評估曲線相交的方式是徵詢我認識的技術熟練開發人員的意見。答案讓很多人感到驚訝。開發人員發現,低品質程式碼會在幾週內顯著降低他們的開發速度。因此,內部品質與成本之間的權衡適用範圍不大。即使是小型的軟體專案,也能從關注良好的軟體實務中受益,這是我從經驗中可以證明的事。

即使是最好的團隊也會產生廢棄物

許多非開發人員傾向於認為廢棄物只會在開發團隊粗心大意並犯錯時才會發生,但即使是最優秀的團隊在工作時也難免會產生一些廢棄物。

我喜歡用一個故事來說明這一點,當時我正在與我們其中一位最佳技術團隊主管聊天。他剛剛完成了一個被廣泛認為是大獲成功的專案。客戶對交付的系統感到滿意,無論是在其功能、建置時間和成本方面。我們的人員對參與專案的經驗感到正面。技術主管大致上感到滿意,但坦承系統的架構並不好。我反應說:「怎麼會這樣?你是我們其中一位最佳的架構師啊?」他的回答是任何經驗豐富的軟體架構師都會熟悉的:「我們做出了好的決定,但直到現在我們才了解到我們應該如何建置它」。

包括軟體產業中不少人在內,許多人將建置軟體比喻成建造教堂或摩天大樓,畢竟,為什麼我們會使用「架構師」這個詞來稱呼資深程式設計師?但建置軟體存在於一個實體世界所不知道的不確定性世界中。軟體的客戶只對他們在產品中需要的功能有一個粗略的概念,並在軟體建置時學到更多,特別是在早期版本釋出給他們的使用者之後。軟體開發的建構模組(語言、函式庫和平台)每隔幾年就會大幅變更。在實體世界中,這相當於客戶通常會在建築物建成並入住一半後新增樓層並變更樓層平面圖,而混凝土的基本特性每隔一年就會變更。

考量到這種變更程度,軟體專案總是在創造新穎的事物。我們幾乎從未發現自己在處理一個已經解決的眾所周知問題。自然而然地,我們在建置解決方案時會學到最多關於問題的知識,因此我常聽說團隊在花費大約一年時間建置軟體後,才真正最了解其軟體的架構應該是什麼。即使是最好的團隊,他們的軟體中也會有一些無用程式碼。

不同之處在於,優秀的團隊既能大幅減少廢棄代碼,又能移除他們所建立的廢棄代碼,讓他們可以持續快速新增功能。他們花時間建立自動化測試,以便能快速找出問題,並減少移除錯誤的時間。他們經常重構,以便在廢棄代碼累積到造成阻礙之前將其移除。持續整合可將團隊成員因目標不一致而累積的廢棄代碼降至最低。一個常見的比喻是,這就像清理廚房的工作檯面和設備。你在做菜時難免會弄髒,但如果你沒有快速清理,髒污就會乾掉,更難移除,而且所有髒東西都會妨礙你料理下一道菜。

高品質軟體的生產成本較低

總結以上所有內容

  • 忽略內部品質會導致廢棄代碼快速累積
  • 這些廢棄代碼會減緩功能開發
  • 即使是優秀的團隊也會產生廢棄代碼,但透過維持高品質的內部品質,就能將其控制在可控範圍內
  • 高品質的內部品質可將廢棄代碼降至最低,讓團隊能以較少的精力、時間和成本新增功能。

遺憾的是,軟體開發人員通常無法很好地說明這種情況。我曾無數次與開發團隊交談,他們說「他們(管理階層)不讓我們撰寫高品質的程式碼,因為這樣會花太久時間」。開發人員經常透過強調專業素養的必要性來證明對品質的重視。但這種道德論點暗示這種品質是有代價的,這會讓他們的論點破功。令人討厭的是,產生的廢棄代碼既讓開發人員的生活更艱難,也讓客戶付出金錢代價。在思考內部品質時,我強調我們應該只把它當成經濟論點。高品質的內部品質可降低未來功能的成本,這表示花時間撰寫良好的程式碼實際上可以降低成本。

這就是為什麼這篇文章標題的問題會錯失重點。高品質內部品質軟體的「成本」是負面的。我們在生活中大多數決策中習慣的成本與品質之間的權衡,並不適用於軟體的內部品質。(它適用於外部品質,例如精心設計的使用者體驗。)由於成本與內部品質之間的關係是一種不尋常且違反直覺的關係,因此通常很難吸收。但了解它對於以最高效率開發軟體至關重要。


衡量低品質內部品質的影響

(新增:2024-01-29)

如我上面所提到的,我們並不知道如何測量內部品質或生產力,因此很難取得可量化的證據來證明內部品質的重要性。然而,近年來,這方面已逐漸受到重視。

我讀過一篇特別有趣的論文,是 亞當·托恩希爾和馬庫斯·博格 的研究。他們使用其專有工具 CodeScene 來判定 39 個專有程式碼庫中檔案的健康程度。他們發現,解決低品質程式碼中的問題所花的時間,是解決高品質程式碼中的問題所花時間的兩倍以上,而且低品質程式碼的缺陷密度高出 15 倍。

重大修訂

2019 年 5 月 29 日:發布