軟件的高質量意味著高成本?

文:Martin Fowler

譯:王薇

審校:劉申


軟件開發項目中,一個常見的爭論是花時間提高軟件質量還是專注於發佈更有價值的功能。通常,功能的交付壓力會主導著討論,導致許多開發人員抱怨他們沒有時間提升架構和代碼質量。

“Betteridge’s Law of headlines”這句諺語說的是任何以問號結尾的文章標題都可以用“否”來概括。瞭解我的人知道我會顛覆這樣的規律,但是這篇文章討論的更進一步:它顛覆了問題本身。這個問題假定了質量和成本之間的權衡,通過本文,我將解釋這種權衡並不適用於軟件,高質量的軟件實際上更便宜。

雖然我大部分的文章都是針對專業軟件開發人員的,但本文並不需要具有軟件開發的專業知識。我希望這篇文章對任何關注軟件工作的人都有價值,特別是那些軟件開發團隊客戶的商業領袖。

我們習慣於在質量和成本之間進行權衡

正如本文開篇所講,我們習慣於在質量和成本之間進行權衡。當我更換智能手機時,可以選處理器更快、屏幕更好、內存更大但同時也更昂貴的機型,或者可以放棄一些質量換取更低的價格。但事無絕對,有時候我們也可以花更少的錢買到高質量的東西。我們往往對質量有不同的定義:有些人並沒有真正注意到一個屏幕比另一個更好。但多數情況下,更高的質量意味著更多的花費。

軟件質量意味著很多事

在談軟件質量之前,需要先來解釋下什麼是軟件質量。這是第一個複雜問題,很多東西可以算作軟件的質量。從用戶界面的角度來看:它是否能便捷的引導我完成某項任務,使我更有效率且不會遇到阻礙?從可靠性的角度來看:它是否包含導致錯誤和崩潰的缺陷?從架構的角度來看:源代碼是否分為明確的模塊,以便程序員可以輕鬆找到並理解本週需要處理的代碼?

這三個質量的例子並不是一個詳盡的列表,但它們足以說明一個重要的觀點。如果我是軟件的客戶或用戶,我並不理解我們稱之為“質量”的一些東西。用戶可以判斷用戶界面是否良好,一位管理者可以判斷該軟件是否使他的員工工作更有效率,用戶和客戶會注意到缺陷,特別是損壞數據或使系統暫時無法運行的缺陷,但是客戶和用戶無法理解軟件的架構。

因此,我將軟件質量屬性劃分為外部(例如UI和缺陷)和內部(架構)。區別在於,用戶和客戶可以理解什麼樣的軟件產品具有高外部質量,但無法區分內部質量的高低。

乍一看,內部質量和客戶沒有關係

既然客戶或用戶看不到內部質量,那麼它重要嗎?想象一下我和Rebecca各自寫了一個跟蹤和預測航班延誤的應用程序。我們的應用程序核心功能相同,都有同樣優雅的用戶界面,並且幾乎沒有任何缺陷。唯一的區別是她的內部源代碼整潔有序,而我的卻是混亂的。另外一個區別是:我的產品售價6美元,她的產品售價10美元。

由於客戶不會看到源代碼,並且它不會影響應用程序的運行,為什麼有人會為Rebecca的軟件額外支付4美元?通俗的講,沒有必要為更高的內部質量支付更多的錢。

換句話說,為外部質量買單是有意義的,但為內部質量買單是沒意義的。用戶可以判斷他是否要為更好的用戶界面支付更多的費用,因為他們能夠評估用戶界面的好壞。但是用戶無法看到軟件內部模塊化的結構,更不用說判斷它的好壞了。既然如此,為什麼軟件開發者要花時間和精力來提高軟件的內部質量呢?

提升內部質量使軟件改進更加便捷

為什麼軟件開發人員會在內部質量上大做文章呢?程序員大部分時間都在修改代碼。即使在新系統中,幾乎所有編程都是在現有代碼庫上完成的。當我想為軟件添加新功能時,第一個任務就是弄清楚這個功能如何適應現有應用程序的流程,然後我需要更改該流程以使適應我的功能。我經常需要使用已經在應用程序中的數據,因此我需要了解這些數據代表什麼,它與周圍數據的關係以及需要為新功能添加哪些數據。

所有這些都是有關理解現有代碼的。但是軟件很難理解。邏輯可能變得糾結,數據可能難以理解,某個命名可能六個月前對Tony有意義,但對我來說,這和他離開公司的理由一樣神祕。凡此種種,開發人員稱之為cruft(1),即當前代碼與理想情況之間的差異。

內部質量的一個主要特點是讓我更容易弄清楚應用程序的工作原理,這樣就可以知道如何添加內容。如果將軟件很好地劃分為獨立的模塊,就不必閱讀全部500,000行代碼,我可以在幾個模塊中快速找到幾百行。如果我們將精力放在明確的命名上,我可以快速瞭解代碼的各個部分,而不必閱讀細節。如果數據合理地遵循基礎業務的語言和結構,我可以很容易地理解它與客戶服務端的請求之間的關係。技術債使我需要花費更多的時間理解如何做出更改,也提升了犯錯誤的概率。如果發現問題,則需要花費更多的時間去定位和解決問題。如果沒有發現這些問題,它們就會成為線上問題,以後會花更多的時間來修理。

我的改動也會影響未來。我可能會找到一種快速添加這個功能的方式,但這會違背程序模塊化結構,增加了技術債。如果我這樣做了,雖然今天可以更快的完成,但是在未來幾周和幾個月裡,其他所有必須處理此代碼的人都只能放慢速度。一旦團隊中的其他成員也決定用這種快捷的方法來完成功能,一個易於修改的應用程序會變得任何一個微小的改動都要耗費數週的時間。

客戶確實會關心新功能的快速引入

在這方面內部質量對用戶和客戶至關重要。更好的內部質量使得添加新功能更容易、更快、更便宜。可能現在我和Rebecca的應用程序是相同的,但在接下來的幾個月裡,由於Rebecca的高內部質量,她可以每週都添加新功能,而我卻一直努力試圖在這些技術債中增加新功能。我的生產速率在降低,很快她的軟件就比我的軟件有更多的功能了。然後,即便她提升價格,客戶也都刪除了我的應用程序,用了Rebecca的。

軟件的高質量意味著高成本?

內部質量影響的可視化

內部質量的基本作用是降低未來變化的成本,但是編寫好的軟件需要額外的努力,這在短期內會產生一些成本。

一種可視化的方法是使用以下偽圖(pseduo-graph),縱座標為軟件累積的功能,橫座標為實現它的時間(成本)。對於大多數軟件工作,曲線看起來像這樣。

軟件的高質量意味著高成本?

內部質量較差時如上圖所示。最初進展很快,但隨著時間的推移,添加新功能變得更加困難。即使很小的變化也需要程序員理解大量晦澀難懂的代碼。修改代碼時,會產生意外的破壞,導致需要長時間來測試,且有很多缺陷要修復。

專注於高內部質量就是減少生產力的下降。事實上,有些產品會產生相反的效果,開發人員可以利用先前的工作輕鬆構建新功能。這種情況是一種罕見的情況,因為它需要一支技術精湛,訓練有素的團隊來實現這一目標。但我們偶爾會遇到。

軟件的高質量意味著高成本?

這裡的微妙之處在於,在一段時間內,低內部質量比高內部質量的生產力更高。在此期間,在質量和成本之間存在某種權衡。問題是:兩條線交叉前的這段時間有多長?

此時我們可以明白為什麼這是一個偽圖。因為無法量化軟件團隊所交付的功能。由於無法量化產出,從而無法衡量生產率,因此無法對低內部質量的後果進行可靠的量化。無法衡量產出在專業工作中非常普遍,比如我們如何衡量律師或醫生的生產力?

我通過收集我所知道的熟練開發人員的意見來評估兩條線交叉點。答案讓很多人感到驚訝。開發人員發現質量差的代碼會在幾周內顯著降低開發速度。因此,內部質量和成本之間的權衡取捨並不多。即使很小的軟件工作也會受益於對良好軟件實踐的關注,當然我可以從我的經驗中證明這一點。

即使最好的團隊也會產生技術債

許多非開發人員傾向於認為只有當開發團隊粗心大意或犯錯時才會發生這種事情,但即使是最優秀的團隊也會在工作時不可避免地產生一些技術債。

我想用一個和我們最好的技術團隊負責人聊天的故事來說明這一點。他剛剛完成了一個被廣泛認為是非常成功的項目。無論是在功能,時間和成本方面,客戶都對交付的系統感到滿意。同事們對在此項目的工作經驗給出了非常積極的評價。技術負責人非常高興,但承認系統的架構並不那麼好。我的反應是“怎麼可能,你是我們最好的架構師之一?”他的答覆是任何一位經驗豐富的軟件架構師都熟悉的答案:“我們做出了很好的決策,但現在才明白應該如何構建它”。

許多人,包括軟件行業的一些人,將構建軟件比作建造教堂或摩天大樓,這也是為什麼我們稱資深程序員為“架構師”。但構建軟件相比於物理世界不同,它是存在於未知的不確定世界中。軟件的客戶只是粗略地瞭解他們在產品中需要哪些功能,並在構建軟件時瞭解更多信息(特別是一旦早期版本發佈給用戶後)。軟件開發的構建模塊(語言,庫和平臺)每隔幾年就會發生重大變化。映射到物理世界中就是,當建築物被建造和使用後,客戶要添加新樓層並改變樓層平面圖,混凝土的基本屬性也每隔一年就會發生變化。

鑑於這種程度的變化,軟件項目總是推陳出新。我們幾乎不會去主動了解那些已經被輕易解決的問題。當我們構建解決方案時,自然會了解它,所以我常常聽到,團隊只有在花了一年左右的時間構建它之後,才能真正理解軟件的架構。即使是最好的團隊在他們的軟件中也會有技術債。

不同的是,最好的團隊其技術債較少,同時也會償還技術債,以便繼續快速添加功能。他們花時間完成自動化測試,以便能夠快速解決問題並減少時間的浪費。他們經常進行重構,以便持續的償還技術債。當團隊成員工作目標相互衝突時,持續集成可以最大限度地減少技術債。一個常見的比喻就是清理廚房的工作臺面和廚具。你做飯時不得不弄髒東西,但是如果不快速清理東西,淤泥乾涸,更難去除,所有骯髒的東西會妨礙烹飪下一道菜。

高質量的軟件生產成本更低

總結起來有如下幾點:

  • 忽視內部質量會導致技術債快速累積
  • 技術債降低了功能的開發速度
  • 即使最優秀的團隊也會產生技術債,但是通過保持高內部質量可以使其變得可控
  • 高內部質量可以最小化技術債,使得添加新功能的工作量、時間和成本都更少

可悲的是,軟件開發人員通常不會很好地解釋這種情況。我多次和開發團隊談過,他們說“他們(管理層)不會讓我們寫出高質量的代碼,因為這需要太長時間”。開發人員通常需要適當的專業性來關注質量。但是,這種道德主義的論證意味著高質量是有代價的,這使他們的論點失敗了。令人討厭的是,低質量的代碼既使得開發人員的生活更加艱難,又讓客戶付出了更多成本。在考慮內部質量時,我強調我們應該使用經濟論證的方法。高內部質量降低了未來功能的成本,這意味著花時間編寫好的代碼實際上降低了成本。

這就是為什麼文章開頭提出的問題忽略了這一點。為構建軟件高內部質量所帶來的“損耗”實際上是在降低損耗。我們在生活中做大多數決策的時候,習慣於在成本和質量之間進行權衡,但這對於軟件的內部質量沒有意義。(它適用於外部質量,例如精心設計的用戶體驗。)因為成本和內部質量之間的關係是一種不同尋常和反直覺的關係,所以通常很難理解。但瞭解它對於以最高效率開發軟件至關重要。


註釋:

(1)通常也將cruft稱為Technical Debt,即技術債,後文中涉及cruft翻譯,統一用技術債。

原文:https://martinfowler.com/articles/is-quality-worth-cost.html?from=timeline&isappinstalled=0

相關推薦

推薦中...