天天看點

高品質的軟體是否值得付出代價?-Martin Flower

軟體開發項目中的一個常見争論是花時間提高軟體品質還是專注于釋出更有價值的功能。通常,傳遞功能的壓力在讨論中占主導地位,導緻許多開發人員抱怨他們沒有時間研究架構和代碼品質。

"貝特裡奇的标題定律"是一句格言,它說任何标題或标題以問号結尾的文章都可以用“否”來概括。認識我的人不會懷疑我想要颠覆這樣的法律。但這篇文章比這更進一步——它颠覆了問題本身。這個問題假設了品質和成本之間的共同權衡。在本文中,我将解釋這種權衡并不适用于軟體——高品質的軟體實際上生産成本更低。

盡管我的大部分文章都是針對專業軟體開發人員的,但在本文中,我不會假設您了解軟體開發的機制。我希望這篇文章對任何參與思考軟體工作的人都很有價值,尤其是那些作為軟體開發團隊客戶的商業領袖。

我們習慣于在品質和成本之間進行權衡

正如我在開頭提到的,我們都習慣于在品質和成本之間進行權衡。當我更換智能手機時,我可以選擇處理器更快、螢幕更好、記憶體更大的更昂貴的型号。或者我可以放棄其中一些品質來支付更少的錢。這不是絕對的規則,有時我們可以買到便宜的優質商品。更常見的是,我們對品質有不同的價值觀——有些人并沒有真正注意到一個螢幕比另一個更好。但大多數時候這個假設是正确的,更高的品質通常會花費更多。

軟體品質意味着很多事情

如果我要談論軟體品質,我需要解釋它是什麼。這是第一個複雜性 - 有很多事情可以算作軟體的品質。我可以考慮使用者界面:它是否可以輕松引導我完成我需要完成的任務,使我更有效率并消除挫折感?我可以考慮它的可靠性:它是否包含導緻錯誤和挫折的缺陷?另一個方面是它的架構:源代碼是否劃分為清晰的子產品,以便程式員可以輕松找到和了解他們本周需要處理的代碼?

這三個品質的例子并不是一個詳盡的清單,但它們足以說明一個重要的觀點。如果我是該軟體的客戶或使用者,我不會欣賞我們稱之為品質的某些東西。使用者可以判斷使用者界面是否良好。主管可以判斷該軟體是否使她的員工的工作效率更高。使用者和客戶會注意到缺陷,尤其是當它們損壞資料或使系統無法運作一段時間時。但是客戶和使用者無法感覺軟體的架構。

是以,我将軟體品質屬性分為外部 (例如 UI 和缺陷)和内部(架構)。差別在于使用者和客戶可以看到是什麼使軟體産品具有較高的外部品質,但無法區分内部品質的高低。

乍一看,内部品質對客戶來說并不重要

由于内部品質不是客戶或使用者可以看到的 - 重要嗎?讓我們想象一下 Rebecca 和我編寫一個應用程式來跟蹤和預測航班延誤。我們的兩個應用程式都執行相同的基本功能,都具有同樣優雅的使用者界面,并且幾乎沒有任何缺陷。唯一的差別是她的内部源代碼組織得井井有條,而我的則是一團亂麻。還有一個差別:我的賣我的賣 6 美元,她的賣 10 美元。

既然客戶從來沒有看到過這個源代碼,也不影響應用程式的運作,為什麼有人會為 Rebecca 的軟體多付 4 美元呢?更一般地說,這應該意味着不值得為更高的内部品質支付更多的錢。

我的另一種說法是,用成本換取外部品質是有意義的,但用成本換取内部品質是沒有意義的。使用者可以判斷他們是否願意支付更多費用來獲得更好的使用者界面,因為他們可以評估使用者界面是否足夠好以值得額外花錢。但是使用者看不到軟體内部的子產品化結構,更談不上判斷它的好壞。為什麼要為沒有效果的東西付出更多?既然是這樣——為什麼任何軟體開發人員都要花時間和精力來提高他們工作的内部品質呢?

内部品質使軟體增強更容易

那麼,為什麼軟體開發人員會因為内部品質而提出問題呢?程式員大部分時間都花在修改代碼上。即使在新系統中,幾乎所有的程式設計都是在現有代碼庫的上下文中完成的。當我想向軟體添加新功能時,我的首要任務是弄清楚該功能如何适應現有應用程式的流程。然後我需要更改該流程以讓我的功能适應。我經常需要使用應用程式中已有的資料,是以我需要了解資料代表什麼,它與周圍資料的關系,以及我可以使用哪些資料需要為我的新功能添加。

所有這些都是關于我對現有代碼的了解。但是軟體很容易讓人難以了解。邏輯可能會變得混亂,資料可能難以了解,用于指代事物的名稱在六個月前對托尼來說可能有意義,但對我來說就像他離開公司的原因一樣神秘。所有這些都是開發人員所說的cruft 的形式——目前代碼與理想情況下的差異。

cruft 的一個常見比喻是技術債務。添加功能的額外成本就像支付利息。清理垃圾就像支付本金一樣。雖然這是一個有用的比喻,但它确實鼓勵許多人相信 cruft 比在實踐中更容易測量和控制。

高品質的軟體是否值得付出代價?-Martin Flower

内部品質的主要功能之一是讓我更容易弄清楚應用程式的工作原理,以便我可以了解如何添加内容。如果将軟體很好地劃分為單獨的子產品,我不必閱讀所有 500,000 行代碼,我可以在幾個子產品中快速找到幾百行。如果我們努力進行清晰的命名,我可以快速了解代碼的各個部分的作用,而不必費解細節。如果資料明智地遵循基礎業務的語言和結構,我就可以輕松了解它與我從客戶服務代表那裡得到的請求之間的關系。Cruft 增加了我了解如何進行更改所需的時間,也增加了我犯錯誤的機會。如果我發現了我的錯誤,那麼就會損失更多的時間,因為我必須了解錯誤是什麼以及如何解決它。如果我沒有發現它們,那麼我們就會出現生産缺陷,并且以後會花更多的時間來修複問題。

我的改變也會影響未來。我可能會看到一種快速添加此功能的方法,但它與程式的子產品化結構背道而馳,增加了 cruft。如果我走這條路,我今天會做得更快,但會減慢在未來幾周和幾個月内必須處理此代碼的其他所有人的速度。一旦團隊的其他成員做出同樣的決定,一個易于修改的應用程式會迅速積累到每一個小的變化都需要數周的努力的地步。

客戶确實關心新功能很快就會出現

在這裡,我們看到了為什麼内部品質對使用者和客戶很重要的線索。更好的内部品質使添加新功能更容易,是以更快、更便宜。Rebecca 和我現在可能有相同的應用程式,但在接下來的幾個月裡,Rebecca 的高内在品質使她每周都能添加新功能,而我卻被困在嘗試剔除繁瑣程式,隻推出一個新功能。我無法與 Rebecca 的速度相提并論,很快她的軟體就比我的功能強大多了。然後我所有的客戶都删除了我的應用程式,取而代之的是 Rebecca,即使她能夠提高價格。

高品質的軟體是否值得付出代價?-Martin Flower

可視化内部品質的影響

内部品質的根本作用是降低未來變革的成本。但是編寫好的軟體需要一些額外的努力,這在短期内确實會帶來一些成本。

将這一點可視化的一種方法是使用以下僞圖,其中我繪制了軟體的累積功能與生成它的時間(以及成本)的關系。對于大多數軟體工作,曲線看起來像這樣。

高品質的軟體是否值得付出代價?-Martin Flower

這就是内部品質差的情況。最初進展很快,但随着時間的推移,添加新功能變得越來越困難。即使是很小的改動也需要程式員了解大範圍的代碼,那些難以了解的代碼。當他們進行更改時,會發生意外損壞,導緻測試時間過長和需要修複的缺陷。

專注于高内部品質是為了減少生産力的下降。事實上,一些産品看到了相反的效果,開發人員可以加快速度,因為可以通過利用以前的工作輕松建構新功能。這種愉快的情況很少見,因為它需要一支技術娴熟、紀律嚴明的團隊才能實作。但我們偶爾會看到。

高品質的軟體是否值得付出代價?-Martin Flower

這裡的微妙之處在于,有一段時間,低内在品質比高軌道更有效率。在此期間,品質和成本之間存在某種權衡。當然,問題是:在兩條線交叉之前的這段時間有多長?

在這一點上,我們遇到了為什麼這是一個僞圖。沒有辦法衡量軟體團隊傳遞的功能。由于無法衡量産出,是以無法衡量生産力,是以無法對低内部品質(這也難以衡量)的後果給出可靠的數字。無法衡量産出在專業工作中很常見——我們如何衡量律師或醫生的生産力?

我評估線路交叉點的方法是征求我所知道的熟練開發人員的意見。而答案卻出乎很多人的意料。開發人員發現低品質的代碼會在幾周内顯着降低他們的速度。是以,内部品質和成本之間的權衡适用的跑道并不多。即使是小的軟體工作也受益于對良好軟體實踐的關注,這當然可以從我的經驗中證明。

即使是最好的團隊也會創造出cruft

許多非開發人員傾向于認為 cruft 僅在開發團隊粗心并犯錯誤時才會發生,但即使是最優秀的團隊在工作時也不可避免地會産生一些 cruft。

我喜歡用我與我們最好的技術團隊負責人之一聊天的故事來說明這一點。他剛剛完成了一個被廣泛認為取得巨大成功的項目。客戶對傳遞的系統感到滿意,無論是在功能還是建構時間和成本方面。我們的員工對項目的工作經驗持積極态度。技術負責人大體上很高興,但承認系統的架構并不是那麼好。我的反應是“這怎麼可能——你是我們最好的建築師之一?” 他的回答是任何有經驗的軟體架構師都熟悉的:“我們做出了很好的決定,但直到現在我們才明白我們應該如何建構它”。

許多人,包括軟體行業的不少人,将建構軟體比作建造大教堂或摩天大樓——畢竟我們為什麼要對進階程式員使用“架構師”?但是建構軟體存在于實體世界未知的不确定性世界中。軟體的客戶對他們需要産品中的哪些功能隻有一個粗略的想法,并在軟體建構過程中了解更多資訊——尤其是在向使用者釋出早期版本之後。軟體開發的建構塊——語言、庫和平台——每隔幾年就會發生很大的變化。現實世界中的等價物是客戶通常會在建造和占用一半的建築物後添加新樓層并更改平面圖,

多拉精英團隊研究

品質和速度之間的選擇并不是軟體開發中唯一具有直覺意義的選擇,而是錯誤的。還有一種強烈的想法表明,在快速開發、頻繁更新系統和可靠的系統之間存在雙模式選擇,不會在生産中中斷。開發營運狀況報告中的細緻科學工作證明這是一個錯誤的選擇。

幾年來,他們使用調查的統計分析來梳理高績效軟體團隊的實踐。他們的工作表明,精英軟體團隊每天多次更新生産代碼,在不到一個小時的時間内将代碼更改從開發推向生産。當他們這樣做時,他們的變更失敗率明顯低于速度較慢的組織,是以他們可以更快地從錯誤中恢複。此外,這樣的精英軟體傳遞組織與更高的組織績效相關。

鑒于這種程度的變化,軟體項目總是在創造一些新穎的東西。我們幾乎從來沒有發現自己在處理一個以前已經解決的很好了解的問題。自然地,我們在建構解決方案時對問題的了解最多,是以我經常聽到團隊隻有在他們花了一年左右的時間建構軟體之後才真正最了解他們的軟體架構應該是什麼。即使是最好的團隊在他們的軟體中也會有缺陷。

不同之處在于,最好的團隊不僅建立的垃圾要少得多,而且還删除了他們建立的足夠多的垃圾,以便他們可以繼續快速添加功能。他們花時間建立自動化測試,以便他們可以快速發現問題并花更少的時間來消除錯誤。他們經常重構,這樣他們就可以在多餘的東西堆積到足以妨礙他們之前去除它。持續內建最大限度地減少了由于團隊成員在不同目的下工作而造成的麻煩。一個常見的比喻是,這就像清理廚房的工作台面和裝置。做飯時不能不弄髒東西,但如果不快速清潔東西,污垢就會變幹,更難去除,所有髒東西都會妨礙下一道菜的烹饪。

高品質軟體的生産成本更低

總結所有這些:

  • 忽視内部品質會導緻垃圾快速堆積
  • 這種垃圾會減慢功能開發的速度
  • 即使是一個偉大的團隊也會産生垃圾,但通過保持内部品質的高,能夠控制它
  • 高内部品質将雜物保持在最低限度,使團隊能夠以更少的精力、時間和成本添加功能。

遺憾的是,軟體開發人員通常不會很好地解釋這種情況。我無數次與開發團隊交談,他們說“他們(管理層)不會讓我們編寫高品質的代碼,因為這需要太長時間”。開發人員通常通過證明對适當專業精神的需求來證明對品質的關注是合理的。但是這種道德論點意味着這種品質是有代價的——注定了他們的論點。令人讨厭的是,由此産生的粗糙代碼既使開發人員的生活變得更加艱難,又使客戶付出了代價。在考慮内部品質時,我強調我們應該隻将其作為經濟論證來處理。高内在品質降低了未來功能的成本,

這就是本文開頭的問題沒有抓住要點的原因。高品質軟體的“成本”是負的。成本和品質之間的通常權衡,我們在生活中的大多數決定中都習慣了這種權衡,但對軟體的内部品質沒有意義。(它适用于外部品質,例如精心設計的使用者體驗。)因為成本和内部品質之間的關系是一種不尋常且違反直覺的關系,是以通常難以了解。但是了解它對于以最高效率開發軟體至關重要。

繼續閱讀