一堆土怎麽蓋出高樓大廈的?其實是一個道理,兩個字,工程。
完成一項大的工作,有三個步驟:
- 找到一個可行的理論,這是科學的範疇,也是最困難的一步
- 將理論的可行性轉化為實踐的可行性,這是技術的範疇,同樣需要天才和靈感
- 用這個可行的方法重復一千遍,在這個過程中找到最有效率的執行方案,然後再重復更多次來做出更復雜的套用,這是工程
工程是看上去最神奇最宏偉的一步,但其實是最不復雜的一步,畢竟路都鋪好了,工程師們通常要做的只有:
- 創造出更合理的工具來提高工作效率
- 發明出更合理的分工來提高工作效率
- 總結出更容易學會的經驗來提高工作效率
它無非是對於這件事,要如何把更多的人力投上去、讓這些人力發揮最大效率、從而在最短時間內完成工作的問題,跟前兩步來說,根本沒有什麽困難的。就像研究力學原理最困難,發明大樓的設計方法其次,而設計出大樓並沒有那麽難,照著圖紙施工更是搬磚的活了。
對於電腦科學也是這樣的。提出儲存程式原理的馮諾依曼是天才,提出可計算理論的圖靈是天才,發明出晶體管的肖克利是天才,發明鎖存器、DRAM、總線、作業系統原理、編譯原理、C語言……這些天才的名字我甚至沒法一一叫出,我們這些工程師只是在前人種下的大樹下,用前人發明好的方法重復著自己的工作,同時嘗試著做出一點點微小的貢獻而已。
電腦能進行計算,首先歸功於非線性元件的發現,這個開端還不是半導體晶體管,而是繼電器、電子管等等。在這之前人們已經可以用電阻分壓進行一些計算了,但是很幼稚,得到的結果也不準確;而經過這些元件的研究,人們發現我們可以將資訊表示為數碼訊號,用0-1的二進制來進行運算,這樣就可以透過電路得到精確的結果,這很快就表現出了對手搖電腦的領先。某些電路可以讓一個輸入訊號變成它的相反的值,0變成1,1變成0;某些電路可以讓兩個輸入訊號變成與或者或的關系,與也就是00、01、10都變成0,而11變成1,或則是00變成0,而01、10、11都變成1。布爾代數這個工具告訴我們,以上的邏輯加在一起就足夠表達所有可能的邏輯了,包括加減乘除在內,於是我們可以用二進制進行運算。
曾經對電腦來說,所謂「編程」,指的是把路線板上可變的路線重新插接起來,讓它們連線成可以工作的電路;甚至於debug,指的是有蟲子飛進路線裏被電死了,造成了短路,需要人去把它們取出來,所以叫做de-bug,bug就是蟲子的意思。後來馮諾依曼提出了儲存程式的概念,我們不是用插線,而是用儲存在電子元件中的程式來控制路線之間的連線,這樣就大大提高了我們重新布線的效率;而這樣的機器能完成怎樣的任務,這個問題則由另一名天才圖靈解決了:簡單來說,能完成任何任務。這樣人類就有了第一台通用電子電腦ENIAC,一個龐然大物。雖然不知道細節,但它大概是從穿孔卡片之類的外設中讀入第一個程式的。穿孔卡片的歷史就遠比電腦要早了,甚至可以上溯到十八世紀;IBM最早也是靠它發家的。為了儲存數據,ENIAC甚至用了一個水銀槽,把電轉換成聲波,讓聲波沿著水銀槽傳播來實作延遲,從而暫存數據。不管怎麽說它的確是可以工作的。
程式是如何替代路線來運算的呢?其實並沒有什麽神秘的。我們看繼電器,它通電的時候,就導通一條路線,關閉的時候則斷開;如果我們將所有的可能的連線上都連上線,就可以用繼電器來控制這些線是通還是斷,也就相當於控制了電路。更好的一點是,我們運算的結果可以反過來修改儲存的狀態,於是這個運算可以按照我們設計的步驟連續不斷地運作下去,大大擴充套件了電腦可以進行的任務種類。
如果你想知道第一個程式如何執行的,大概到這裏就結束了;但是離office還遠。
電子管電腦不管是價格還是壽命都有大問題,後來人類發明了晶體管,然後是集成電路,它大大降低了電腦的尺寸和成本,於是小型機甚至個人PC變為可能。再後來,電腦越來越廉價,也就有越來越多的人用得起,為了讓所有人都能用得上,IBM、貝爾實驗室等機構就聯合起來想要開發一個叫做multics的作業系統。
作業系統是什麽呢?以前的電腦一次只執行一個程式,它接受指定好的輸入,完成指定的工作,打印到紙帶輸出,然後就停機。但現在的電腦計算能力很強,僅僅一條紙帶的輸入速度已經滿足不了它了,為了提高效率,它必須能同時輸入多道數據,執行多個任務,從而提高效率。對於以前的電腦來說,計算,然後決定讀取數據,然後等待數據讀進來,這時候電腦完全停轉等待著穿孔卡片(紙帶),這是對電腦的浪費;而有作業系統了之後,電腦會在等待數據輸入的時候,切換到其他計算任務上,直到讀取完成之後再切換回來進行原來的任務,這樣就讓輸入輸出(IO)與計算進行了重疊。
然而這個計劃悲慘地失敗了,大概是因為當時的人們還沒有充分認識到,軟件的開發是一項獨立於硬件的工程,直到認清這件事的時候已經晚了,貝爾實驗室和IBM都因為開發延遲而結束了這項計劃。但透過這個大專案,人們認清了幾件事:
- 軟件開發的復雜度超過了人們的想象,必須用正確的方法來進行;這個正確的方法叫做模組化。將軟件的功能拆分成小的模組,這樣人們才能有效地協同起來共同工作;否則僅僅投入人力是不夠的。
-
工具的重要性。要高效率的開發軟件,我們需要高級語言而不是組譯。
後來,multics的遺跡上,兩個愛玩遊戲的工程師為了玩遊戲,從遺棄的程式碼中開發出了Unix,順便發明了C語言。
從這以後,軟件工程的路上一片坦途。沒過多久,也有了我們熟知的DOS和Windows。
這之後的故事就簡單了,就像我最早說的,我們工程師只是在鋪好的路上重復勞動,再一點點改進原來的方法,從DOS到Windows,從16位元到32位元,從文本模式到圖形模式,從真實模式到保護模式,我們的工具每天都在進步,但我們做的事情其實與幾十年前沒有多大區別。就像是搭積木,我們每個人都學會了怎麽搭上自己的一塊,最終我們搭出了龐然大物,但這其實並沒有什麽可稀奇的。