我們之所以一遍又一遍地聽到上述問題,背後是有原因的。為了保持競爭力,企業每天都需要新的軟體功能,但隨著時間的流逝,我們交付軟體的速度似乎停滯不前,或者更糟,變得更慢了。
我想解釋為什麼會這樣。不過,為了探討這個話題,需要先了解一個我最關心的話題:本質複雜性和偶發複雜性。
任何時候,當你在解決一個問題,不僅僅是軟體問題,都有兩種型別的複雜性:
- 本質複雜性——這是包含在問題中的複雜性。如果不解決這種複雜性,就無法解決問題。它也被稱為內在複雜性。
- 偶發複雜性——這是用來解決問題的方法和工具所帶來的複雜性。這種複雜性不是你要解決的問題的一部分,而是在解決方案中引入的複雜性。它也被稱為偶然複雜性。
IBM 360 系統之父 Fred Brooks 在經典論文“沒有銀彈:軟體工程的本質性與附屬性工作”中提出了這個概念。可以這麼想,如果你要解決一個數學問題,本質複雜性就是指對數學的瞭解,因為只有懂數學才能解題。如果你想解決這個問題,要麼學習所需的數學知識,要麼找個懂數學的人幫忙。如果你想解決這個問題,就無法逃過學習數學這一關。
我們假設,這是一個頗具挑戰性的數學問題,完全用人腦來解決是徒勞的,所以需要使用計算器。這就是偶發複雜性。還記得第一次使用圖形計算器的情形嗎?在這個時候,偶發複雜性就是學習如何在計算器上輸入所有複雜的數學資訊來幫你解決問題。你不一定要使用計算器,但你知道它對你有用,而且不會太難學。
現在,我們假設你對 Mathematica 很熟悉。Mathematica 是一個非常強大和複雜的軟體,不過既然你已經知道它了,就決定用它來解決問題。你在學習 Mathematica 上投入了很多,所以不需要很多額外的努力,只是增加了解決方案的偶發複雜性。
幾周後,你的一位同事遇到類似情況,他記得你曾經解決過一個類似問題。他們來找你,看你是如何解決問題的,然後你把 Mathematica 發給他們。你認為這個時候會發生什麼?你認為他們會去學習數學嗎?不,他們會想出另一種解決問題的方法,或者試圖讓你替他們解決問題。
正如你所看到的,這兩種複雜性來自不同的地方,但它們之間有著緊密的聯絡。如果不引入一些偶發複雜性,就無法解決問題。即使是一支鉛筆和一張紙也會帶來一些微不足道的偶發複雜性。
如果沒有偶發複雜性,就無法解決問題。
這可能會讓你感到驚訝,在過去 20 年中,軟體領域本質複雜性與偶發複雜性比率在急劇下降。David Heinemeier Hansson(Ruby on Rails 之父)用“概念壓縮(conceptual compression)”這個詞來描述這種趨勢以及它是如何讓我們的行業變得更好的。在過去的 20 年中,開源框架和庫的激增是減少軟體系統偶發複雜性最強大的力量。
與 20 年前相比,解決業務問題所需的程式碼量已經減少了一個數量級,因此你可能會認為開發軟體將比那時快一個數量級。但這種情況似乎並沒有發生,為什麼會這樣?
軟體變得越來越容易開發,但與此同時,其他現象也在發生:
-
我們對軟體的要求越來越高 -
公司內部的軟體數量呈爆炸式增長 -
採用新技術的步伐正在加快
儘管我們正在利用越來越多的外部工具和庫來開發軟體,讓軟體開發變得越來越容易,但我們對軟體的要求也越來越高,僅這一點就抵消了大量的收益。如果我們用現代工具來開發 2000 年代的 Web 應用程式,會看到軟體開發的生產力有十倍 (或更多) 的提升。
但我們的世界並沒有停滯不前,消費者和企業對軟體的期望一直在迅速增長。我們期望軟體能比 20 年前做得更多。當我們開發出這些更大型、功能更豐富的應用程式時,為了保持它們的可靠性、功能性和可理解性,不得不改變軟體的開發方式。
以下是我們在過去 20 年裡看到的幾個行業變化:
- 原始碼控制——原始碼控制一直都存在,但並不像現在這麼普遍。不認為這增加了偶發複雜性?那就去問問第一次使用 Git 的初級工程師,他們是怎麼想的。
- 自動化測試——我們引入了很多測試型別和測試工具。我們需要進行驗收測試、整合測試、單元測試等等……這給專案帶來了大量的偶發複雜性,但有助於確保交付的軟體是高質量的,且功能是符合預期的。
- 拆分系統——隨著系統複雜性的增加,元件之間連線和互動的量會呈二次級數增長。也就是說,在某種程度上,如果軟體設計得不好,互動量將會繼續增長,直到因為自身的複雜性而垮掉。拆分系統,特別是進行分散式拆分,會帶來大量的意外複雜性。
- 專門化——隨著 Web 應用程式變得越來越複雜,出現了大量的專門化。在 2000 年,由軟體工程師負責 UI 設計、UI 構建和應用程式後端構建都是很常見的事,而到了 2020 年,這些工作需要幾個角色分別承擔。開發 Web 應用程式的團隊通常由 UI 設計師、UX 設計師、前端軟體工程師、後端軟體工程師和 DevOps 工程師組成。在較大的組織中,會有更加專門化的角色,如安全、架構、資料管理、資料科學,等等……所有這些額外的角色讓我們能夠開發更大規模的軟體,但所需的工具和流程了引入大量的偶發複雜性。
- 基礎設施自動化——為了構建更大型、更復雜的環境來執行越來越多的應用程式,我們已經開始自動化它們的構建和維護過程。這樣我們就可以更容易地進行大規模的環境管理,但需要一整套工具和知識。這些工具帶來的複雜性是巨大的,導致 DevOps 成為大多數大型團隊的專門角色。
- 頻繁部署——由於應用程式的大小和複雜性都在增長,為了降低風險,我們需要以較小的增量交付軟體。為此,我們引入了持續整合和持續部署的概念。同樣,這對於大規模交付軟體來說是非常好的,但用於構建和操作這些管道所需的工具和技能引入了偶發複雜性。
- 多裝置和形式因素——在以前,我們可以說,我們的軟體執行在一個作業系統上,只有少數的幾種解析度。現在,我們的應用程式需要在桌上型電腦、膝上型電腦和跨平臺的移動裝置上執行。通常,我們會有原生移動應用程式和 Web 應用程式,或許還可以加入一些物聯網應用程式和手錶應用程式。我們在訪問資料的位置和方式上有了巨大的靈活性,改變了我們的社會,但無疑增加了軟體開發過程的複雜性。
在閱讀上一個小節前,你可能已經非常清楚,人們對軟體要求越來越多以及越來越多的軟體開發形式會導致複雜性的增加。但是,從單個應用程式的角度來看,企業擁有更多的軟體會增加開發單個應用程式的複雜性嗎?
答案很簡單:不會,除非你想讓這個軟體與其他軟體發生互動。一家公司使用的軟體越多,系統之間的重疊就越多,不同的系統需要訪問相同的資料才能正常執行,這就需要為更多的系統儲存共享資料,並將所有系統整合起來。
舉個例子,假設在 2000 年,你是一家辦公椅生產商,那個時候你還沒有網路系統。你需要為公司建立一個庫存系統,所以需要開發軟體來完成這件事。庫存系統的使用者是倉庫工作人員,你可以通過生成夜間報告來獲得庫存資訊,這些報告也可以被髮送給整個公司的人。這個系統相對獨立,報告功能對於每一個人來說都沒有什麼問題。
時間快進到 2020 年,你的庫存系統已經不是一個獨立的應用程式。你的合作伙伴可以直接將訂單推送到你的系統中,Web 頁面可以獲得實時的庫存更新,並在下單時更新庫存。你的庫存系統與物流系統直接整合,這樣就可以自動生成物流標籤和取貨時間表。你直接在亞馬遜上銷售你的產品,所以你的庫存系統直接與第三方軟體整合。倉庫的工作人員使用移動裝置定位、掃描、登記和挑選商品,所以你還有一個用來完成這些事情的移動解決方案。
隨著系統的激增,並覆蓋了業務的各個方面,開始出現越來越多的重疊,一直到如果不與其他系統整合就無法滿足需求的地步。雖然這帶來了前所未有的生產力和自動化程度,但也給資料移動和整合引入了大量的偶發複雜性。
Marc Andreesen 提出了“軟體正在吞噬世界”的說法。這個過程正在加速,而且看不到盡頭。
https://a16z.com/2011/08/20/why-software-is-eating-the-world/
在 2000 年,你通常會從單個廠商那裡購買系統,如微軟、Sun 或 Borland,你還可能還會購買一些元件,但不管怎樣,整個生態系統都是由單個廠商提供的。此時,你所採用和整合的外部工具和技術相對較少,你所能完成的任務被限制在廠商所提供的功能上。
為了跟上快速變化的技術格局,公司開始採用更開放的技術。這帶來了巨大的優勢,因為你可以用這些工具完成以前只能在夢中想一想的壯舉。但切換工具通常是有代價的,最終會在流程中引入很多偶發複雜性。
雖然使用前沿的技術可能會在某些方面獲得好處,但技術越新,維護的難度就越大。而且,越早採用一項技術,當它演化成為一項對廣大使用者都有用的技術時,你所經歷的痛苦就越多。如何平衡一項新技術所帶來的收益以及使用它所帶來的痛苦是技術專家們長期以來一直在努力解決的問題。
我們現在發現,挑選有用的工具、框架和技術是一項非常有價值的技能。如果不小心使用了未經驗證的新工具或框架可能會產生有害的影響。它們可能會導致大量的偶發複雜性,更糟糕的是,如果框架在跨越鴻溝之前死亡,就會把你帶入死衚衕。
關於為什麼開發軟體需要的時間越來越長,原因還有很多,比如業務需要更快的迭代速度、企業架構標準或對安全性的重視程度,等等。但關鍵是,我們在 2020 年開發的軟體與在 2010 年開發的軟體幾乎沒有什麼相似之處,更不用說在 2000 年了。在很大程度上,這是一件好事。
但也有不好的地方。我們似乎又回到了 2000 年到 2007 年,那時每個應用程式都是用同樣的工具開發的,而其中有很多工具變得越來越複雜。現在,很多流行的工具和框架都來自於大型企業,但它們解決的很多問題是其他企業不會遇到的。
正因為如此,很多中小型企業,甚至是大型企業的一些部門都發現,他們執行軟體的能力正在迅速下降,而且不知道如何扭轉局面。為了加快開發速度,他們已經開始轉向低程式碼和無程式碼,但在很多情況下,這也破壞了使用這些工具構建的系統的功能和壽命。
原文連結:
https://www.simplethread.com/why-does-it-take-so-long-to-build-software/