02 | 架構設計的歷史背景

此爲筆記

課程鏈接

https://time.geekbang.org/column/intro/100006601?utm_source=time_web&utm_medium=menu&utm_term=timewebmenu


理解了架構的有關概念和定義之後,今天,我會給你講講架構設計的歷史背景。我認爲,如果想要深入理解一個事物的本質,最好的方式就是去追尋這個事物出現的歷史背景和推動因素。我們先來簡單梳理一下軟件開發進化的歷史,探索一下軟件架構出現的歷史背景。

機器語言(1940 年之前)

最早的軟件開發使用的是“機器語言”,直接使用二進制碼 0 和 1 來表示機器可以識別的指令和數據。例如,在 8086 機器上完成“s=768+12288-1280”的數學運算,機器碼如下:


 
 

101100000000000000000011

 

000001010000000000110000

 

001011010000000000000101

複製代碼

不用多說,不管是當時的程序員,還是現在的程序員,第一眼看到這樣一串東西時,肯定是一頭霧水,因爲這實在是太難看懂了,這還只是一行運算,如果要輸出一個“hello world”,面對幾十上百行這樣的 0/1 串,眼睛都要花了!

看都沒法看,更何況去寫這樣的程序,如果不小心哪個地方敲錯了,將 1 敲成了 0,例如:


 
 

101100000000000000000011

 

000001010000000000110000

 

001011000000000000000101

複製代碼

如果要找出這個程序中的錯誤,程序員的心裏陰影面積有多大?

歸納一下,機器語言的主要問題是三難:太難寫、太難讀、太難改

彙編語言(20 世紀 40 年代)

爲了解決機器語言編寫、閱讀、修改複雜的問題,彙編語言應運而生。彙編語言又叫“符號語言”,用助記符代替機器指令的操作碼,用地址符號(Symbol)或標號(Label)代替指令或操作數的地址。

例如,爲了完成“將寄存器 BX 的內容送到 AX 中”的簡單操作,彙編語言和機器語言分別如下。


 
 

機器語言:1000100111011000

 

彙編語言:mov ax,bx

複製代碼

相比機器語言來說,彙編語言就清晰得多了。mov 是操作,ax 和 bx 是寄存器代號,mov ax,bx 語句基本上就是“將寄存器 BX 的內容送到 AX”的簡化版的翻譯,即使不懂彙編,單純看到這樣一串語言,至少也能明白大概意思。

彙編語言雖然解決了機器語言讀寫複雜的問題,但本質上還是面向機器的,因爲寫彙編語言需要我們精確瞭解計算機底層的知識。例如,CPU 指令、寄存器、段地址等底層的細節。這對於程序員來說同樣很複雜,因爲程序員需要將現實世界中的問題和需求按照機器的邏輯進行翻譯。例如,對於程序員來說,在現實世界中面對的問題是 4 + 6 = ?。而要用彙編語言實現一個簡單的加法運算,代碼如下:


 
 

.section .data

 

a: .int 10

 

b: .int 20

 

format: .asciz "%d\n"

 

.section .text

 

.global _start

 

_start:

 

movl a, %edx  

 

addl b, %edx  

 

pushl %edx

 

pushl $format

 

call printf

 

movl $0, (%esp)

 

call exit

複製代碼

這還只是實現一個簡單的加法運算所需要的彙編程序,可以想象一下,實現一個四則運算的程序會更加複雜,更不用說用匯編寫一個操作系統了!

除了編寫本身複雜,還有另外一個複雜的地方在於:不同 CPU 的彙編指令和結構是不同的。例如,Intel 的 CPU 和 Motorola 的 CPU 指令不同,同樣一個程序,爲 Intel 的 CPU 寫一次,還要爲 Motorola 的 CPU 再寫一次,而且指令完全不同。

高級語言(20 世紀 50 年代)

爲了解決彙編語言的問題,計算機前輩們從 20 世紀 50 年代開始又設計了多個高級語言,最初的高級語言有下面幾個,並且這些語言至今還在特定的領域繼續使用。

  • Fortran:1955 年,名稱取自”FORmula TRANslator”,即公式翻譯器,由約翰·巴科斯(John Backus)等人發明。

  • LISP:1958 年,名稱取自”LISt Processor”,即枚舉處理器,由約翰·麥卡錫(John McCarthy)等人發明。

  • Cobol:1959 年,名稱取自”Common Business Oriented Language”,即通用商業導向語言,由葛麗絲·霍普(Grace Hopper)發明。

爲什麼稱這些語言爲“高級語言”呢?原因在於這些語言讓程序員不需要關注機器底層的低級結構和邏輯,而只要關注具體的問題和業務即可。

還是以 4 + 6=?這個加法爲例,如果用 LISP 語言實現,只需要簡單一行代碼即可:


 
 

(+ 4 6)

複製代碼

除此以外,通過編譯程序的處理,高級語言可以被編譯爲適合不同 CPU 指令的機器語言。程序員只要寫一次程序,就可以在多個不同的機器上編譯運行,無須根據不同的機器指令重寫整個程序。

第一次軟件危機與結構化程序設計(20 世紀 60 年代~20 世紀 70 年代)

高級語言的出現,解放了程序員,但好景不長,隨着軟件的規模和複雜度的大大增加,20 世紀 60 年代中期開始爆發了第一次軟件危機,典型表現有軟件質量低下、項目無法如期完成、項目嚴重超支等,因爲軟件而導致的重大事故時有發生。例如,1963 年美國(http://en.wikipedia.org/wiki/Mariner_1)的水手一號火箭發射失敗事故,就是因爲一行 FORTRAN 代碼錯誤導致的。

軟件危機最典型的例子莫過於 IBM 的 System/360 的操作系統開發。佛瑞德·布魯克斯(Frederick P. Brooks, Jr.)作爲項目主管,率領 2000 多個程序員夜以繼日地工作,共計花費了 5000 人一年的工作量,寫出將近 100 萬行的源碼,總共投入 5 億美元,是美國的“曼哈頓”原子彈計劃投入的 1/4。儘管投入如此巨大,但項目進度卻一再延遲,軟件質量也得不到保障。布魯克斯後來基於這個項目經驗而總結的《人月神話》一書,成了暢銷的軟件工程書籍。

爲了解決問題,在 1968、1969 年連續召開兩次著名的 NATO 會議,會議正式創造了“軟件危機”一詞,並提出了針對性的解決方法“軟件工程”。雖然“軟件工程”提出之後也曾被視爲軟件領域的銀彈,但後來事實證明,軟件工程同樣無法根除軟件危機,只能在一定程度上緩解軟件危機。

差不多同一時間,“結構化程序設計”作爲另外一種解決軟件危機的方案被提了出來。艾茲赫爾·戴克斯特拉(Edsger Dijkstra)於 1968 年發表了著名的《GOTO 有害論》論文,引起了長達數年的論戰,並由此產生了結構化程序設計方法。同時,第一個結構化的程序語言 Pascal 也在此時誕生,並迅速流行起來。

結構化程序設計的主要特點是拋棄 goto 語句,採取“自頂向下、逐步細化、模塊化”的指導思想。結構化程序設計本質上還是一種面向過程的設計思想,但通過“自頂向下、逐步細化、模塊化”的方法,將軟件的複雜度控制在一定範圍內,從而從整體上降低了軟件開發的複雜度。結構化程序方法成爲了 20 世紀 70 年代軟件開發的潮流。

第二次軟件危機與面向對象(20 世紀 80 年代)

結構化編程的風靡在一定程度上緩解了軟件危機,然而隨着硬件的快速發展,業務需求越來越複雜,以及編程應用領域越來越廣泛,第二次軟件危機很快就到來了。

第二次軟件危機的根本原因還是在於軟件生產力遠遠跟不上硬件和業務的發展。第一次軟件危機的根源在於軟件的“邏輯”變得非常複雜,而第二次軟件危機主要體現在軟件的“擴展”變得非常複雜。結構化程序設計雖然能夠解決(也許用“緩解”更合適)軟件邏輯的複雜性,但是對於業務變化帶來的軟件擴展卻無能爲力,軟件領域迫切希望找到新的銀彈來解決軟件危機,在這種背景下,面向對象的思想開始流行起來。

面向對象的思想並不是在第二次軟件危機後纔出現的,早在 1967 年的 Simula 語言中就開始提出來了,但第二次軟件危機促進了面向對象的發展。面向對象真正開始流行是在 20 世紀 80 年代,主要得益於 C++ 的功勞,後來的 Java、C# 把面向對象推向了新的高峯。到現在爲止,面向對象已經成爲了主流的開發思想。

雖然面向對象開始也被當作解決軟件危機的銀彈,但事實證明,和軟件工程一樣,面向對象也不是銀彈,而只是一種新的軟件方法而已。

軟件架構的歷史背景

雖然早在 20 世紀 60 年代,戴克斯特拉這位上古大神就已經涉及軟件架構這個概念了,但軟件架構真正流行卻是從 20 世紀 90 年代開始的,由於在 Rational 和 Microsoft 內部的相關活動,軟件架構的概念開始越來越流行了。

與之前的各種新方法或者新理念不同的是,“軟件架構”出現的背景並不是整個行業都面臨類似相同的問題,“軟件架構”也不是爲了解決新的軟件危機而產生的,這是怎麼回事呢?

卡內基·梅隆大學的瑪麗·肖(Mary Shaw)和戴維·加蘭(David Garlan)對軟件架構做了很多研究,他們在 1994 年的一篇文章《軟件架構介紹》(An Introduction to Software Architecture)中寫到:

“When systems are constructed from many components, the organization of the overall system-the software architecture-presents a new set of design problems.”

簡單翻譯一下:隨着軟件系統規模的增加,計算相關的算法和數據結構不再構成主要的設計問題;當系統由許多部分組成時,整個系統的組織,也就是所說的“軟件架構”,導致了一系列新的設計問題。

這段話很好地解釋了“軟件架構”爲何先在 Rational 或者 Microsoft 這樣的大公司開始逐步流行起來。因爲只有大公司開發的軟件系統才具備較大規模,而只有規模較大的軟件系統纔會面臨軟件架構相關的問題,例如:

  • 系統規模龐大,內部耦合嚴重,開發效率低;

  • 系統耦合嚴重,牽一髮動全身,後續修改和擴展困難;

  • 系統邏輯複雜,容易出問題,出問題後很難排查和修復。

軟件架構的出現有其歷史必然性。20 世紀 60 年代第一次軟件危機引出了“結構化編程”,創造了“模塊”概念;20 世紀 80 年代第二次軟件危機引出了“面向對象編程”,創造了“對象”概念;到了 20 世紀 90 年代“軟件架構”開始流行,創造了“組件”概念。我們可以看到,“模塊”“對象”“組件”本質上都是對達到一定規模的軟件進行拆分,差別只是在於隨着軟件的複雜度不斷增加,拆分的粒度越來越粗,拆分的層次越來越高。

《人月神話》中提到的 IBM 360 大型系統,開發時間是 1964 年,那個時候結構化編程都還沒有提出來,更不用說軟件架構了。如果 IBM 360 系統放在 20 世紀 90 年代開發,不管是質量還是效率、成本,都會比 1964 年開始做要好得多,當然,這樣的話我們可能就看不到《人月神話》了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章