Donald Knuth(高德納)是一位電腦科學界的著名學者和計算機程式設計的先驅之一。他被譽為電腦科學的“聖經”《計算機程式設計藝術》的作者,提出了著名的“大O符號”來描述演算法的時間複雜度和空間複雜度,開發了TeX系統用於排版科技文獻,獲得過圖靈獎、馮·諾伊曼獎、美國國家科學獎章等多項榮譽。今天要說的就是他所提出的一條軟體設計重要原則 Premature optimization is the root of all evil 過早最佳化是萬惡之源。
為什麼說“過早最佳化是萬惡之源”? 我認為過早最佳化程式碼會讓人陷入到錯誤的目標中去,從而忽視掉了最重要的目標。舉個很簡單的例子,你需要快速構建一個產品來搶佔使用者,你當下最重要的目標是讓這個產品快速上線,而不是把這個產品打造的好用(在中國網際網路下,這樣的事數不勝數),如果你只關注到後者體驗、效能問題而忽視了速度,在當下高度競爭的市場之下,你根本毫無機會。
當然上面這個例子是從感性的層面說的,對很多程式猿來說也可能涉及不到產品層面的內容。我們從軟體設計的層面,理性的來說,過早最佳化可能會導致以下的一些問題:
- 增加程式碼的複雜性:過度最佳化可能會導致程式碼的複雜性增加,從而降低程式碼的可讀性和可維護性。如果程式碼過於複雜,可能會導致開發人員難以理解和維護程式碼,從而增加開發成本和時間。
- 耗費開發時間和資源:過度最佳化可能會導致開發人員花費大量時間和資源在程式碼的效能最佳化上,而忽略了其他重要的開發任務。這可能會導致專案進度延誤和開發成本增加。
- 降低程式碼的可移植性:過度最佳化可能會導致程式碼的可移植性降低。如果程式碼過於依賴於特定的硬體或作業系統,可能會導致程式碼無法在其他環境中執行。
- 降低程式碼的可擴充套件性:過度最佳化可能會降低程式碼的可擴充套件性。如果程式碼過於依賴於特定的演算法或資料結構,可能會導致程式碼無法適應未來的需求變化。
過早最佳化的典型案例
在軟體工程史上由於過度關注軟體效能導致專案最終失敗的案例比比皆是,比如我下面要說的一些專案,在軟體工程史上都是非常知名的專案(當然可能有些新生代程式設計師已經不知道了)。
- IBM OS/360作業系統:在20世紀60年代,IBM公司開發了OS/360作業系統,這是當時最大的軟體工程專案之一。在開發過程中,IBM公司過於關注程式碼的效能問題,導致程式碼的複雜性增加,開發時間延誤,最終導致專案的失敗。我知曉這個專案還是在我最近在閱讀的一本軟體工程經典書籍《人月神話》中,也推薦大家閱讀下,這個專案雖然最終失敗了,但也給整個軟體工程領域留下了寶貴的經驗。
- Netscape Navigator瀏覽器:在20世紀90年代,Netscape公司開發了Navigator瀏覽器,這是當時最流行的瀏覽器之一。在開發過程中,Netscape公司過於關注程式碼的效能問題,導致程式碼的複雜性增加,開發時間延誤,最終導致瀏覽器市場份額嚴重下降。
- Windows Vista作業系統:在21世紀初,微軟公司開發了Windows Vista作業系統,這是當時最大的軟體工程專案之一。在開發過程中,微軟公司過於關注程式碼的效能問題,導致程式碼的複雜性增加,開發時間延誤,最終導致作業系統的使用者體驗不佳,市場反響不佳。話說這個作業系統我還用過呢,使用者介面還是很漂亮的,很多UI設計也被沿用到了Window7中。
如何識別過早最佳化
在軟體開發過程中,如何判斷是否過早最佳化呢?這裡有一些概括性的判斷標準,可以簡單參考下:
- 是否存在效能問題:如果程式碼還沒有效能問題,那麼過早最佳化就是不必要的。因此,在進行最佳化之前,應該先測試程式碼的效能,確定是否存在效能問題。
- 是否最佳化了未來可能發生的問題:如果最佳化的是未來可能發生的問題,而不是當前存在的問題,那麼就可能是過早最佳化。在進行最佳化之前,應該優先考慮當前存在的問題,而不是未來可能發生的問題。
- 是否犧牲了程式碼的可讀性和可維護性:如果最佳化程式碼會導致程式碼的複雜性增加,降低程式碼的可讀性和可維護性,那麼就可能是過早最佳化。在進行最佳化之前,應該優先考慮程式碼的可讀性、可維護性和可擴充套件性。
- 是否浪費了大量的開發時間和資源:如果最佳化程式碼會浪費大量的開發時間和資源,而不是提高程式碼的效能和效率,那麼就可能是過早最佳化。在進行最佳化之前,應該評估最佳化的成本和收益,確定是否值得進行最佳化。
判斷是否過早最佳化需要根據具體情況進行評估。在進行最佳化之前,應該先測試程式碼的效能,確定是否存在效能問題。同時,也應該優先考慮程式碼的可讀性、可維護性和可擴充套件性,避免過度最佳化。
總結
作為一名在IT領域摸爬滾打多年的工程師,我深有體會地認識到過早最佳化是軟體開發中的一大陷阱。在軟體開發的初期,我們可能會過於關注程式碼的效能問題,而忽略了程式碼的可讀性、可維護性和可擴充套件性。這種做法可能會導致程式碼的複雜性增加,降低程式碼的可讀性和可維護性,甚至可能會浪費大量的開發時間和資源。
在軟體開發過程中,我們應該避免過早最佳化,而是優先考慮程式碼的可讀性、可維護性和可擴充套件性。當需要進行效能最佳化時,應該在程式碼的基礎上進行最佳化,透過分析效能瓶頸、最佳化演算法和資料結構等方法來提高程式碼的效能和效率。同時,我們也應該意識到,效能最佳化並不是軟體開發的唯一目標,我們還應該注重程式碼的可讀性、可維護性和可擴充套件性,以便保證程式碼的質量和可靠性。