排序算法不多會是獨立程序,更多是大項目的一小部分,例如:微軟的Office大約有4000萬行代碼。爲了寫大型程序,程序員用各類工具和方法,全部這些造成「軟件工程」學科程序員
「軟件工程」這個詞由工程師Margaret Hamilton
創造,她幫助NASA在阿波羅計劃中避免了嚴重問題。算法
Margaret Hamilton
曾說過:「有點像牙根管治療:你老是拖到最後才作,但有些事能夠預先作好,有點像預防性體驗,只不過是預防性軟件出錯」。編程
對象,面向對象編程
把大項目分解成小函數,可讓多人同時工做,不用關心整個項目,關心本身的函數就行了。若是接到的任務是寫排序算法,只須要保證高效和正確就能夠了。
然而把代碼打包成函數,依然不夠,若是隻是這樣,微軟Office會有幾十萬個函數。解決辦法是:把函數打包成層級,把相關代碼都放在一塊兒,打包成對象(Objects)瀏覽器
例如:汽車軟件中可能有幾個和定速巡航有關的函數,好比,設定速度,逐漸加速減速,中止定速巡航,由於這些函數都相關,能夠包裝成一個「定速巡航對象」。但不止如此,還能夠作更多,「定速巡航」只是引擎軟件的一部分,可能還有「火花塞點火」,「燃油泵」和「散熱器」。
因此能夠作一個「引擎對象」來包括全部「子」對象。除了子對象,「引擎對象」可能有本身的函數,好比,開關引擎。它也會有本身變量,好比汽車行駛了多少公里,總的來講,對象能夠包其它對象,函數和變量。
固然,「引擎對象」只是「汽車對象」的一部分,還有傳動裝置,車輪,門,窗等。做爲程序員,若是想設「定速巡航」,要一層層向下,從最外面的對象往裏找,最後找到想執行的函數:Car.Engine.CruiseControl.setCruiseSpeed(55)
。緩存
把函數打包成對象的思想叫「面向對象編程」安全
經過封裝組件,隱藏複雜度,以前把晶體管,打包成了邏輯門,如今軟件也這樣操做。服務器
API和IDE
把大型軟件,拆分一個個更小單元,適合團隊合做,在不一樣崗位同時工做,各盡其能。iphone
各個團隊負責不一樣項目,但也有所依賴,因此團隊須要文檔,幫助理解代碼都作什麼,以及定義好「程序編程接口」簡稱「API」編程語言
API
幫助不一樣程序員合做,不用知道具體細節,只要知道怎麼使用就好了。函數
API
控制哪些函數和數據讓外部訪問,哪些僅供內部。「面向對象」的編程語言,能夠指定函數是public
或private
來設置權限。
「面向對象編程」的核心是隱藏複雜度,選擇性的公佈功能。由於作大型項目頗有效,因此廣受歡迎。
代碼在編譯前就只是文字而已,只要編寫出來,就能夠。可是通常來講,現代軟件開發者,會用專門的工具來寫代碼。工具裏集成了不少有用的功能,幫助寫代碼,整理,編譯和測試代碼。由於集成了全部東西,所以叫集成開發環境簡稱IDE。
IDE會定位到出錯代碼,還會提供信息,幫助解決問題,這叫「調試(debug)」,調試很重要,大多數程序員會花70%~80%時間調試,而不是在寫代碼。
給代碼寫文檔,文檔通常放在README
的文件裏,告知其它程序員,看代碼前先看這個文件。文檔也能夠直接寫成「註釋」,放在源碼裏。
註釋存在的惟一做用,就是幫助開發者理解代碼。
源代碼管理,也叫「版本控制」。會把代碼放到一箇中心服務器上,叫「代碼倉庫」。
不但願提交的代碼裏有問題,由於其餘人可能用到了這些代碼,致使他們代碼崩潰,形成困惑並且浪費時間,代碼的主版本(master
)應該是編譯正常,儘量少bug。
寫代碼和測試代碼密不可分,測試通常由我的或小團隊完成,測試能夠統稱「質量保證測試」,簡稱「QA」。
讓軟件在各類狀況下按照預期運行。
bate 版
軟件:意思是軟件接近完成,但不是100%徹底測試過。alpha 版
軟件:很粗糙,錯誤不少常常只在公司內部測試。
重點:晶圓的製做流程:光刻
在大概50年代裏,軟件從紙帶打孔變成面向對象,在集成開發環境中寫程序。但若是沒有硬件的大幅度進步,軟件是不可能作到這些的。
硬件性能的爆炸性增加。
分立元件, Discrete components
電子計算機的誕生年代,大約1940年代~1960年代中期這段時間裏,計算機都由獨立部件組成,叫「分立元件」。而後不一樣組件再用線連在一塊兒。
例如,ENIAC有1萬7千多個真空管,7萬個電阻。1萬個電容器,7千個二極管,5百萬個手工焊點。
若是想提高性能,就要加更多部件,這致使更多電線,更復雜。這個問題叫「數字暴政」。
分立元件:只有一個電路元件的組件,能夠是被動的(電容,電阻,電感)或主動的(晶體管或真空管)
1950年代中期,晶體管開始商業化(市場上買獲得)開始用在計算機裏,晶體管比電子管,更小更快更可靠,但晶體管依然是分立元件。
1959年,IBM把709計算機從本來的電子管所有換成晶體管,誕生了新機器 IBM 7090速度快6倍,價格只有一半。
晶體管標誌着「計算機2.0時代」的到來。
雖然更快更小,但晶體管的出現,仍是沒有解決「數字暴政」的問題,有十幾萬個獨立元件的計算機不但難設計並且難生產。
1960年代,這個問題的嚴重性達到頂點,電腦內部經常一大堆電線纏繞在一塊兒。
解決辦法就是引入一層新抽象,封裝複雜性。
突破性進展在1958年,當時Jack Killby在德州儀器工做,演示了一個電子元件:「電路的全部組件都集成在一塊兒」。
簡單說就是:與其把多個獨立部件用電線鏈接起來,拼裝出計算機。把多個組件包在一塊兒,變成一個新的獨立組件,這就是:集成電路(IC)
幾個月後,在1959年Robert Noyce的仙童半導體讓集成電路變爲現實,Killby用鍺來作集成電路,鍺很稀少並且不穩定,仙童半導體公司用硅,硅的蘊含量豐富,佔地殼四分之一,也穩定可靠。因此Noyce被公認爲現代的集成電路之父。開創了電子時代,創造了硅谷。
起初,一個IC只有幾個晶體管。
例如:早期樣品,由西屋公司製造。
即便只有幾個晶體管,也能夠把簡單電路,邏輯門,能封裝成單獨組件。IC
就像電腦工程師的樂高積木,能夠組合出無數種設計,但最終仍是須要鏈接起來,創造更大更復雜的電路,好比整個計算機。
因此工程師再度創新,印刷電路板,簡稱PCB
。PCB
能夠大規模生產,無需焊接或用一大堆線。它經過蝕刻金屬線,把零件鏈接到一塊兒。
把PCB
和IC
結合使用,能夠大幅減小獨立組件和電線,但作到相同的功能。並且更小,更便宜,更可靠。
許多早期IC
都是把很小的分立元件,封裝成一個獨立單元,例如這塊1964年的IBM樣品。不過,即便組件很小,塞5個以上的晶體管仍是很困難。
光刻
爲了實現更復雜的設計,須要全新的製做工藝:「光刻」。
簡單說就是:用光把複雜圖案印到材料上,好比半導體,它只有幾個基礎操做,但能夠製做出複雜電路。
例子:
用相似步驟,光刻能夠製做其它電子元件,好比電阻和電容,都在一片硅上,並且互相鏈接的電路也作好了。
例子中,只作了一個晶體管,但現實中,光刻法一次會作上百萬個細節。
芯片放大以後,導線上下交錯,鏈接各個元件。
儘管能夠把光掩膜投影到一整篇晶圓上,但光能夠投射成任意大小。就像投影儀能夠投滿熒幕同樣。
能夠把光掩膜聚焦到極小的區域,製做出很是精細的細節。
一片晶圓能夠作不少IC
,整塊都作完後,能夠切割而後包進微型芯片,微型芯片就是在電子設備中,那些小長方體。記住,芯片的核心都是一小篇IC
。
隨着技術的發展,晶體管變小,密度變高。
1960年代初,IC
不多超過5個晶體管,由於塞不下。
但1960年代中期,市場上開始出現超過100個晶體管的IC
。
摩爾定律,Moore's Law
1965年,戈登●摩爾看到了趨勢:每兩年左右,得益於材料和製造技術的發展,一樣大小的空間,能塞進兩倍數量的晶體管。這叫摩爾定律。(它不是定律,只是一種趨勢,但它是對的。)
芯片的價格也急劇降低,1962年平均50美圓,降低到1968年2美圓左右。現在,幾美分就能買到IC
。
晶體管更小密度更高,還有其它好處,晶體管越小,要移動的電荷量就越少,能更快切換狀態,耗電量更小。
電路更緊湊,還意味着信號延遲耕地,致使時鐘速度更快。
Inter 4004 CPU,是個重要里程碑,發佈於1971年,是第一個用IC作的處理器,也叫微型處理器。由於真的很是小。它有2300個晶體管。
驚歎於它的整合水平,整個CPU在一個芯片裏,而僅僅20年前,用分立元件會佔滿整個屋子。
集成電路的出現,尤爲是用來作微處理器,開啓了計算3.0
晶體管數量大幅度增加,1980年三萬個,1990年一百萬個,2000年三千萬個,2010年十億個,在一個芯片裏。
爲了達到這種密度,光刻的分辨率,從大約一萬納米,大概是人類頭髮直徑的1/10。發展到現在的14納米,比血紅細胞小400倍。
固然,CPU不是惟一受益的元件。大多數電子器件都在指數式發展:內存,顯卡,固態硬盤,攝像頭感光元件,等等。
現在的處理器,好比iphone7的A10 CPU,有33億個晶體管。面積僅有1cm * 1cm,比一張郵票小。
現代工程師設計電路時,固然不是手工一個個設計晶體管,這不是人力能作到的。
1970年代開始,超大規模集成(VLSI)軟件用來自動生成芯片設計。用好比「邏輯綜合」這種技術能夠放一整個高級組件,好比內存緩存。軟件會自動生成電路,作到儘量高效。(EDA技術,HDL自動綜合技術)
進一步作小,會面臨2個大問題:
1940,1950年代的電腦,每次只能運行一個程序,程序員在打孔紙卡上寫程序,而後拿到一個計算機房間,交給操做員。等計算機空下來,操做員會把程序放入。而後運行,輸出結果,停機。
之前計算機慢,這種手動作法能夠接受。運行一個程序一般要幾個小時,幾天,甚至幾周。
計算機愈來愈快,指數級增加,很快,放程序的時間,比程序運行時間還長,須要一種方式,讓計算機自動運做。因而「操做系統」誕生了。
操做系統,簡稱OS
,其實也是程序。但它有操做硬件的特殊權限,能夠運行和管理其它程序。操做系統通常是開機第一個啓動的程序,其它全部程序,都由操做系統啓動。
操做系統開始與1950年代,那時計算機開始變得更強大更流行。第一個操做系統,增強了程序加載方式。
以前只能一次給一個程序,如今能夠一次多個。當計算機運行完一個程序,會自動運行下一個程序,這樣就不會浪費時間,找下一個程序的紙卡,這叫: 「批處理」。
電腦變得更快更便宜,開始在出如今世界各地,特別是大學和政府辦公室,很快,人們開始分享軟件,但有一個問題,在哈佛1號和ENIAC那個時代,計算都是一次性的,程序員只需給那「一臺」機器寫代碼,處理器,讀卡器,打印機都是已知的,但隨着電腦愈來愈廣泛,計算機配置並不老是相同的。好比計算機可能有相同CPU,但不一樣的打印機。不只要擔憂寫程序,還要擔憂程序怎麼和不一樣型號的打印機交互,以及計算機連着的其它設備,這些統稱「外部設備」。
設備驅動程序,Device drivers
和早期的外部設備交互,是很是底層的,程序員要了解設備的硬件細節,加劇問題的是,程序員不多能拿到全部型號的設備來測代碼。因此通常是閱讀手冊來寫代碼,祈禱能正常運行。
如今是「即插即用」,之前是「祈禱能用」。這很糟糕,因此爲了程序員寫軟件更容易,操做系統充當軟件和硬件之間的媒介。更具體的說,操做系統提供API來抽象硬件,叫「設備驅動程序」。
程序員能夠用標準化機制,和輸入輸出硬件(I/O)交互。好比,程序員只須要調用print(highscore)
,操做系統會處理 輸到紙上的具體細節。
到1950年代尾聲,電腦已經很是快了,處理器常常閒着,等待慢的機械設備(好比打印機和讀卡器)。程序阻塞在I/O上,而昂貴的處理器則在度假。
50年代後期,英國曼切斯特大學開始研發世界上第一臺超級計算機,Atlas
,他們知道機器會超級快,因此須要一種方式來最大限度的利用它。他們的解決方案是一個程序叫Altas Supervisor
於1962年完成。這個操做系統,不只像更早期的批處理系統那樣,能自動加載程序,還能在單個CPU上同時運行幾個程序。它經過調度來作到這一點。
假設Atlas
上有一個遊戲在運行,而且調用一個函數print(highscore)
。它讓Atlas
打印一個叫highscore
的變量值。
print
函數運行須要一點時間,大概上千個時鐘週期,但由於打印機比CPU慢,與其等着它完成操做,Altas
會把程序休眠,運行另外一個程序,最終,打印機會告訴Altas
打印已完成,Altas
會把程序標記可繼續運行。print
語句以後的下一行代碼。這樣,Altas
能夠在CPU上運行一個程序,同時另外一個程序在打印數據,同時另外一個程序讀數據。
Altas
的工程師作的還要多,配了4臺紙帶讀取器,4臺紙帶打孔機,多達8個磁帶驅動器。
使多個程序能夠同時運行,在單個CPU上共享時間,操做系統的這種能力叫:「多任務處理」。
同時運行多個程序有個問題,每一個程序都會佔一些內存,當切換到另外一個程序時,不能丟失數據。解決辦法是:給每一個程序分配專屬內存塊。
例如:假設計算機一共有10000個內存位置,程序A分配到內存地址0到999。而程序B分配到內存地址1000到1999,以此類推。(開着軟件佔緩存)
若是一個程序請求更多內存,操做系統會決定是否贊成,若是贊成,分配哪些內存塊,這種靈活性很好,但帶來一個奇怪的後果。程序A可能會分配到非連續的內存塊,好比內存地址0到999,以及2000到2999。(解決方法:虛擬內存)
真正的程序可能會分配到內存中數十個地方。這對程序員來講很難跟蹤。
虛擬內存,Virtual Memory
也許內存裏有一長串銷售額,天天下班後要算銷售總額,但列表存在一堆不連續的內存塊裏,爲了隱藏這種複雜性,操做系統會把內存地址進行「虛擬化」。這叫「虛擬內存」,程序能夠假定內存老是從地址0開始,簡單又一致。而實際物理位置,被操做系統隱藏和抽象了。
用程序B來舉例,它被分配了內存地址1000到1999。對程序B而言,它看到的地址是0到999。操做系統會自動處理,虛擬內存和物理內存之間的映射。若是程序B要地址42,其實是物理地址1042。這種內存地址的虛擬化,對程序A更有用。
在例子中,A被分配了兩塊隔開的內存,程序A不知道這點。以A的視角,它有2000個連續的地址,當程序A讀內存地址999時,會恰好映射到物理內存地址999,但若是程序A讀下一個地址1000,會映射到物理地址2000。這種機制使程序的內存大小能夠靈活增減叫「動態內存分配」。
對程序來講,內存看起來是連續的。它簡化了一切,爲了操做系統同時運行多個程序提供了極大的靈活性。給程序分配專用的內存範圍。
另外一個好處是這樣隔離起來會更好,若是一個程序出錯,開始寫亂七八糟的數據,它只能搗亂本身的內存,不會影響到其它程序。這叫「內存保護」。防止惡意軟件(如病毒)也頗有用。
例如:不但願其它程序有能力讀或改郵件程序的內存。若是有這種權限惡意軟件能夠以你的名義發郵件,甚至竊取我的信息。
Multics
Atlas
既有「虛擬內存」也有「內存保護」,是第一臺支持這些功能的計算機和操做系統。到1970年代,計算機足夠快且便宜。大學會買電腦讓學生用,計算機不只能同時運行多個程序,還能讓多用戶能同時訪問。
多個用戶用「終端」來訪問計算機。「終端」只是鍵盤+屏幕,連到主計算機終端自己沒有處理能力,冰箱大小的計算機可能有50個終端,能讓50個用戶使用。
這時操做系統不但要處理多個程序,還要處理多個用戶。爲了確保其中一我的,不會佔滿計算機資源,開發了分時操做系統,意思是:每一個用戶只能用一小部分處理器和內存等。由於電腦很快,即便拿到1/50的資源也足以完成許多任務。
早期分時操做系統中,最有影響力的是Multics
(多任務信息與計算系統),於1969年發佈,Multics
是第一個,從設計時就考慮到安全的操做系統,開發人員不但願惡意用戶訪問不改訪問的數據。這致使Multics
的複雜度超過當時的平均水準,操做系統會佔大約1Mb內存,這在當時不少。多是內存的一半,只拿來運行操做系統。
Multics
的研究人員Dennis Ritchie曾說過:阻礙Multics
得到商業成功的一個明顯問題是從某種方面來講,它被過分設計了,功能太多了。
因此Dennis和另一個Multics
研究員Ken Thompson聯手開發新的操做系統叫Unix
。
他們想把操做系統分紅兩部分:
緊湊的內核意味着功能沒有那麼全面。Multics
的另外覺得開發者Tom Van Vleck回憶說:我對Dennis說,我在Multics
寫的一半代碼都是錯誤恢復代碼。他說:「Unix 不會有這些東西, 若是有錯誤發生,咱們就讓內核‘恐慌’(panic)當調用它時,機器會崩潰,你得在走廊裏大喊,‘嘿,重啓電腦’」。
內核若是崩潰,沒有辦法恢復,因此調用一個叫「恐慌」(panic)的函數,起初只是打印「恐慌」一詞,而後無限循環。
這種簡單性意味着,Unix能夠在更便宜更多的硬件上運行,使Unix在Dennis和Ken工做的貝爾實驗室大受歡迎,愈來愈多開發人員用Unix寫程序和運行程序。工具數量日益增加,1971年發佈後不久,就有人寫了不一樣編譯語言的編譯,甚至文字處理器,使得Unix迅速成爲1970~80年代最流行的操做系統之一,到1980年代早期,計算機的價格降到普通人買得起,這些叫「我的電腦」或「家庭電腦」。這些電腦比大型主機簡單得多,主機通常在大學,公司和政府。所以操做系統也得簡單。
例如:微軟的磁盤操做系統(MS-DOS)只有160KB,一張磁盤就能夠容納操做系統。
於1981年發佈的,成爲早期家用電腦最受歡迎的操做系統。雖然缺乏「多任務」和「保護內存」這樣的功能。意味着程序常常使系統崩潰。雖然很討厭但還能夠接受,由於用戶能夠重啓。哪怕是微軟1985年發佈的早期Windows雖然在90年代很流行,但卻缺少「內存保護」。當程序行爲不當時,就會「藍屏」。表明程序崩潰的很是嚴重,把系統也帶崩潰了。
現在的計算機,有現代操做系統,好比Mac OS X, Windows 10, Linux, iOS和Android。雖然大部分設備只有一我的使用。操做系統依然有「多任務」,「虛擬內存」, 「內存保護」。所以能夠同時運行多個程序:一邊使用瀏覽器,一邊使用PS修圖,播放音樂,同步筆記等。若是沒有操做系統這幾十年的發展,這些都不可能。
操做系統: