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

















 
 
 







 
 
 
 