為什么現(xiàn)在開發(fā)一款軟件的時(shí)間越來越長?
為什么開發(fā)軟件這么貴?為什么我的團(tuán)隊(duì)交付軟件的速度這么慢?為什么我的軟件發(fā)布趕不上計(jì)劃?為什么開發(fā)一個(gè)軟件要花這么長時(shí)間?
我們之所以一遍又一遍地聽到上述問題,背后是有原因的。為了保持競爭力,企業(yè)每天都需要新的軟件功能,但隨著時(shí)間的流逝,我們交付軟件的速度似乎停滯不前,或者更糟,變得更慢了。
我想解釋為什么會(huì)這樣。不過,為了探討這個(gè)話題,需要先了解一個(gè)我最關(guān)心的話題:本質(zhì)復(fù)雜性和偶發(fā)復(fù)雜性。
1. 不同類型的復(fù)雜性
任何時(shí)候,當(dāng)你在解決一個(gè)問題,不僅僅是軟件問題,都有兩種類型的復(fù)雜性:
本質(zhì)復(fù)雜性——這是包含在問題中的復(fù)雜性。如果不解決這種復(fù)雜性,就無法解決問題。它也被稱為內(nèi)在復(fù)雜性。
偶發(fā)復(fù)雜性——這是用來解決問題的方法和工具所帶來的復(fù)雜性。這種復(fù)雜性不是你要解決的問題的一部分,而是在解決方案中引入的復(fù)雜性。它也被稱為偶然復(fù)雜性。
IBM 360 系統(tǒng)之父 Fred Brooks 在經(jīng)典論文“沒有銀彈:軟件工程的本質(zhì)性與附屬性工作”中提出了這個(gè)概念??梢赃@么想,如果你要解決一個(gè)數(shù)學(xué)問題,本質(zhì)復(fù)雜性就是指對(duì)數(shù)學(xué)的了解,因?yàn)橹挥卸當(dāng)?shù)學(xué)才能解題。如果你想解決這個(gè)問題,要么學(xué)習(xí)所需的數(shù)學(xué)知識(shí),要么找個(gè)懂?dāng)?shù)學(xué)的人幫忙。如果你想解決這個(gè)問題,就無法逃過學(xué)習(xí)數(shù)學(xué)這一關(guān)。
2. 偶發(fā)復(fù)雜性
我們假設(shè),這是一個(gè)頗具挑戰(zhàn)性的數(shù)學(xué)問題,完全用人腦來解決是徒勞的,所以需要使用計(jì)算器。這就是偶發(fā)復(fù)雜性。還記得第一次使用圖形計(jì)算器的情形嗎?在這個(gè)時(shí)候,偶發(fā)復(fù)雜性就是學(xué)習(xí)如何在計(jì)算器上輸入所有復(fù)雜的數(shù)學(xué)信息來幫你解決問題。你不一定要使用計(jì)算器,但你知道它對(duì)你有用,而且不會(huì)太難學(xué)。
現(xiàn)在,我們假設(shè)你對(duì) Mathematica 很熟悉。Mathematica 是一個(gè)非常強(qiáng)大和復(fù)雜的軟件,不過既然你已經(jīng)知道它了,就決定用它來解決問題。你在學(xué)習(xí) Mathematica 上投入了很多,所以不需要很多額外的努力,只是增加了解決方案的偶發(fā)復(fù)雜性。
幾周后,你的一位同事遇到類似情況,他記得你曾經(jīng)解決過一個(gè)類似問題。他們來找你,看你是如何解決問題的,然后你把 Mathematica 發(fā)給他們。你認(rèn)為這個(gè)時(shí)候會(huì)發(fā)生什么?你認(rèn)為他們會(huì)去學(xué)習(xí)數(shù)學(xué)嗎?不,他們會(huì)想出另一種解決問題的方法,或者試圖讓你替他們解決問題。
正如你所看到的,這兩種復(fù)雜性來自不同的地方,但它們之間有著緊密的聯(lián)系。如果不引入一些偶發(fā)復(fù)雜性,就無法解決問題。即使是一支鉛筆和一張紙也會(huì)帶來一些微不足道的偶發(fā)復(fù)雜性。
如果沒有偶發(fā)復(fù)雜性,就無法解決問題。
3. 它在軟件領(lǐng)域是怎樣體現(xiàn)的
這可能會(huì)讓你感到驚訝,在過去 20 年中,軟件領(lǐng)域本質(zhì)復(fù)雜性與偶發(fā)復(fù)雜性比率在急劇下降。David Heinemeier Hansson(Ruby on Rails 之父)用“概念壓縮(conceptual compression)”這個(gè)詞來描述這種趨勢(shì)以及它是如何讓我們的行業(yè)變得更好的。在過去的 20 年中,開源框架和庫的激增是減少軟件系統(tǒng)偶發(fā)復(fù)雜性最強(qiáng)大的力量。
與 20 年前相比,解決業(yè)務(wù)問題所需的代碼量已經(jīng)減少了一個(gè)數(shù)量級(jí),因此你可能會(huì)認(rèn)為開發(fā)軟件將比那時(shí)快一個(gè)數(shù)量級(jí)。但這種情況似乎并沒有發(fā)生,為什么會(huì)這樣?
軟件變得越來越容易開發(fā),但與此同時(shí),其他現(xiàn)象也在發(fā)生:
- 我們對(duì)軟件的要求越來越高
- 公司內(nèi)部的軟件數(shù)量呈爆炸式增長
- 采用新技術(shù)的步伐正在加快
4. 我們對(duì)軟件的要求越來越多
盡管我們正在利用越來越多的外部工具和庫來開發(fā)軟件,讓軟件開發(fā)變得越來越容易,但我們對(duì)軟件的要求也越來越高,僅這一點(diǎn)就抵消了大量的收益。如果我們用現(xiàn)代工具來開發(fā) 2000 年代的 Web 應(yīng)用程序,會(huì)看到軟件開發(fā)的生產(chǎn)力有十倍 (或更多) 的提升。
但我們的世界并沒有停滯不前,消費(fèi)者和企業(yè)對(duì)軟件的期望一直在迅速增長。我們期望軟件能比 20 年前做得更多。當(dāng)我們開發(fā)出這些更大型、功能更豐富的應(yīng)用程序時(shí),為了保持它們的可靠性、功能性和可理解性,不得不改變軟件的開發(fā)方式。
以下是我們?cè)谶^去 20 年里看到的幾個(gè)行業(yè)變化:
源碼控制——源碼控制一直都存在,但并不像現(xiàn)在這么普遍。不認(rèn)為這增加了偶發(fā)復(fù)雜性?那就去問問第一次使用 Git 的初級(jí)工程師,他們是怎么想的。
自動(dòng)化測(cè)試——我們引入了很多測(cè)試類型和測(cè)試工具。我們需要進(jìn)行驗(yàn)收測(cè)試、集成測(cè)試、單元測(cè)試等等……這給項(xiàng)目帶來了大量的偶發(fā)復(fù)雜性,但有助于確保交付的軟件是高質(zhì)量的,且功能是符合預(yù)期的。
拆分系統(tǒng)——隨著系統(tǒng)復(fù)雜性的增加,組件之間連接和交互的量會(huì)呈二次級(jí)數(shù)增長。也就是說,在某種程度上,如果軟件設(shè)計(jì)得不好,交互量將會(huì)繼續(xù)增長,直到因?yàn)樽陨淼膹?fù)雜性而垮掉。拆分系統(tǒng),特別是進(jìn)行分布式拆分,會(huì)帶來大量的意外復(fù)雜性。
專門化——隨著 Web 應(yīng)用程序變得越來越復(fù)雜,出現(xiàn)了大量的專門化。在 2000 年,由軟件工程師負(fù)責(zé) UI 設(shè)計(jì)、UI 構(gòu)建和應(yīng)用程序后端構(gòu)建都是很常見的事,而到了 2020 年,這些工作需要幾個(gè)角色分別承擔(dān)。開發(fā) Web 應(yīng)用程序的團(tuán)隊(duì)通常由 UI 設(shè)計(jì)師、UX 設(shè)計(jì)師、前端軟件工程師、后端軟件工程師和 DevOps 工程師組成。在較大的組織中,會(huì)有更加專門化的角色,如安全、架構(gòu)、數(shù)據(jù)管理、數(shù)據(jù)科學(xué),等等……所有這些額外的角色讓我們能夠開發(fā)更大規(guī)模的軟件,但所需的工具和流程了引入大量的偶發(fā)復(fù)雜性。
基礎(chǔ)設(shè)施自動(dòng)化——為了構(gòu)建更大型、更復(fù)雜的環(huán)境來運(yùn)行越來越多的應(yīng)用程序,我們已經(jīng)開始自動(dòng)化它們的構(gòu)建和維護(hù)過程。這樣我們就可以更容易地進(jìn)行大規(guī)模的環(huán)境管理,但需要一整套工具和知識(shí)。這些工具帶來的復(fù)雜性是巨大的,導(dǎo)致 DevOps 成為大多數(shù)大型團(tuán)隊(duì)的專門角色。
頻繁部署——由于應(yīng)用程序的大小和復(fù)雜性都在增長,為了降低風(fēng)險(xiǎn),我們需要以較小的增量交付軟件。為此,我們引入了持續(xù)集成和持續(xù)部署的概念。同樣,這對(duì)于大規(guī)模交付軟件來說是非常好的,但用于構(gòu)建和操作這些管道所需的工具和技能引入了偶發(fā)復(fù)雜性。
多設(shè)備和形式因素——在以前,我們可以說,我們的軟件運(yùn)行在一個(gè)操作系統(tǒng)上,只有少數(shù)的幾種分辨率?,F(xiàn)在,我們的應(yīng)用程序需要在臺(tái)式機(jī)、筆記本電腦和跨平臺(tái)的移動(dòng)設(shè)備上運(yùn)行。通常,我們會(huì)有原生移動(dòng)應(yīng)用程序和 Web 應(yīng)用程序,或許還可以加入一些物聯(lián)網(wǎng)應(yīng)用程序和手表應(yīng)用程序。我們?cè)谠L問數(shù)據(jù)的位置和方式上有了巨大的靈活性,改變了我們的社會(huì),但無疑增加了軟件開發(fā)過程的復(fù)雜性。
5. 企業(yè)內(nèi)部的軟件爆炸
在閱讀上一個(gè)小節(jié)前,你可能已經(jīng)非常清楚,人們對(duì)軟件要求越來越多以及越來越多的軟件開發(fā)形式會(huì)導(dǎo)致復(fù)雜性的增加。但是,從單個(gè)應(yīng)用程序的角度來看,企業(yè)擁有更多的軟件會(huì)增加開發(fā)單個(gè)應(yīng)用程序的復(fù)雜性嗎?
答案很簡單:不會(huì),除非你想讓這個(gè)軟件與其他軟件發(fā)生交互。一家公司使用的軟件越多,系統(tǒng)之間的重疊就越多,不同的系統(tǒng)需要訪問相同的數(shù)據(jù)才能正常運(yùn)行,這就需要為更多的系統(tǒng)保存共享數(shù)據(jù),并將所有系統(tǒng)集成起來。
舉個(gè)例子,假設(shè)在 2000 年,你是一家辦公椅生產(chǎn)商,那個(gè)時(shí)候你還沒有網(wǎng)絡(luò)系統(tǒng)。你需要為公司建立一個(gè)庫存系統(tǒng),所以需要開發(fā)軟件來完成這件事。庫存系統(tǒng)的用戶是倉庫工作人員,你可以通過生成夜間報(bào)告來獲得庫存信息,這些報(bào)告也可以被發(fā)送給整個(gè)公司的人。這個(gè)系統(tǒng)相對(duì)獨(dú)立,報(bào)告功能對(duì)于每一個(gè)人來說都沒有什么問題。
時(shí)間快進(jìn)到 2020 年,你的庫存系統(tǒng)已經(jīng)不是一個(gè)獨(dú)立的應(yīng)用程序。你的合作伙伴可以直接將訂單推送到你的系統(tǒng)中,Web 頁面可以獲得實(shí)時(shí)的庫存更新,并在下單時(shí)更新庫存。你的庫存系統(tǒng)與物流系統(tǒng)直接集成,這樣就可以自動(dòng)生成物流標(biāo)簽和取貨時(shí)間表。你直接在亞馬遜上銷售你的產(chǎn)品,所以你的庫存系統(tǒng)直接與第三方軟件集成。倉庫的工作人員使用移動(dòng)設(shè)備定位、掃描、登記和挑選商品,所以你還有一個(gè)用來完成這些事情的移動(dòng)解決方案。
隨著系統(tǒng)的激增,并覆蓋了業(yè)務(wù)的各個(gè)方面,開始出現(xiàn)越來越多的重疊,一直到如果不與其他系統(tǒng)集成就無法滿足需求的地步。雖然這帶來了前所未有的生產(chǎn)力和自動(dòng)化程度,但也給數(shù)據(jù)移動(dòng)和集成引入了大量的偶發(fā)復(fù)雜性。
Marc Andreesen 提出了“軟件正在吞噬世界”的說法。這個(gè)過程正在加速,而且看不到盡頭。
https://a16z.com/2011/08/20/why-software-is-eating-the-world/
6. 采用新技術(shù)的步伐正在加快
在 2000 年,你通常會(huì)從單個(gè)廠商那里購買系統(tǒng),如微軟、Sun 或 Borland,你還可能還會(huì)購買一些組件,但不管怎樣,整個(gè)生態(tài)系統(tǒng)都是由單個(gè)廠商提供的。此時(shí),你所采用和集成的外部工具和技術(shù)相對(duì)較少,你所能完成的任務(wù)被限制在廠商所提供的功能上。
為了跟上快速變化的技術(shù)格局,公司開始采用更開放的技術(shù)。這帶來了巨大的優(yōu)勢(shì),因?yàn)槟憧梢杂眠@些工具完成以前只能在夢(mèng)中想一想的壯舉。但切換工具通常是有代價(jià)的,最終會(huì)在流程中引入很多偶發(fā)復(fù)雜性。
雖然使用前沿的技術(shù)可能會(huì)在某些方面獲得好處,但技術(shù)越新,維護(hù)的難度就越大。而且,越早采用一項(xiàng)技術(shù),當(dāng)它演化成為一項(xiàng)對(duì)廣大用戶都有用的技術(shù)時(shí),你所經(jīng)歷的痛苦就越多。如何平衡一項(xiàng)新技術(shù)所帶來的收益以及使用它所帶來的痛苦是技術(shù)專家們長期以來一直在努力解決的問題。
我們現(xiàn)在發(fā)現(xiàn),挑選有用的工具、框架和技術(shù)是一項(xiàng)非常有價(jià)值的技能。如果不小心使用了未經(jīng)驗(yàn)證的新工具或框架可能會(huì)產(chǎn)生有害的影響。它們可能會(huì)導(dǎo)致大量的偶發(fā)復(fù)雜性,更糟糕的是,如果框架在跨越鴻溝之前死亡,就會(huì)把你帶入死胡同。
7. 還有希望嗎
關(guān)于為什么開發(fā)軟件需要的時(shí)間越來越長,原因還有很多,比如業(yè)務(wù)需要更快的迭代速度、企業(yè)架構(gòu)標(biāo)準(zhǔn)或?qū)Π踩缘闹匾暢潭龋鹊?。但關(guān)鍵是,我們?cè)?2020 年開發(fā)的軟件與在 2010 年開發(fā)的軟件幾乎沒有什么相似之處,更不用說在 2000 年了。在很大程度上,這是一件好事。
但也有不好的地方。我們似乎又回到了 2000 年到 2007 年,那時(shí)每個(gè)應(yīng)用程序都是用同樣的工具開發(fā)的,而其中有很多工具變得越來越復(fù)雜?,F(xiàn)在,很多流行的工具和框架都來自于大型企業(yè),但它們解決的很多問題是其他企業(yè)不會(huì)遇到的。
正因?yàn)槿绱?,很多中小型企業(yè),甚至是大型企業(yè)的一些部門都發(fā)現(xiàn),他們運(yùn)行軟件的能力正在迅速下降,而且不知道如何扭轉(zhuǎn)局面。為了加快開發(fā)速度,他們已經(jīng)開始轉(zhuǎn)向低代碼和無代碼,但在很多情況下,這也破壞了使用這些工具構(gòu)建的系統(tǒng)的功能和壽命。