排序算法不多会是独立程序,更多是大项目的一小部分,例如:微软的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修图,播放音乐,同步笔记等。若是没有操做系统这几十年的发展,这些都不可能。
操做系统: