关于编程语言的思考
编程语言,就是人类使用的计算机能够理解的语言。它介于人类语言(英语)和机器语言之间。
机器语言已经从二进制代码--》汇编语言--》高级语言。
从人类语言的角度,这种语言必须符合人类的思维习惯和表达方法;从机器语言的角度,它必须精确、没有歧义、可执行(数学化)。
一种理想的编程语言,应该能够用简洁的方式直观、精确地表达人类的丰富思想,富有强大的表现力。同时,能够方便地转换为各种计算机都可以理解的机器语言。最理想的状态是:人类通过脑电波把问题告诉计算机,计算机自动编程,解决问题后把答案告诉人类。或者说,想怎么干(如设计一座房子),通知计算机,计算机就这么干了。目前还只能通过语言(编程语言-机器语言)控制计算机,距离真正的人工智能还差得很远。
理想的编程语言的特性:
1-简洁:符号特别少,语法规则特别简单,代码特别短;
2-容易:易于安装,易于编写,易于调试/测试;
3-跨平台:可以在任何硬件和操作系统平台上运行;
4-高度抽象:可以解决任何问题(主流语言);只要把问题描述清楚,解法也就出来了(快速开发原型);
5-逻辑严谨:使产生bug的可能性降到最低;
6-灵活:便于修改,支持持续演进/敏捷开发;
7-提供出色的性能分析器,发现运行瓶颈以便优化;
8-有大量优秀的范例和函数库可以使用:自己只用写很少的代码就可以解决大部分常见问题;
9-开放源代码:可以随意修改编译器;
10-可以方便地同操作系统、其他语言开发的程序对话;
11-代码复用:易于编写/维护大型项目(工业级);
12-有其他人使用,便于交流;
当然,这样完美的编程语言现在还不存在,也许永远也不会存在,但人类向着这个目标不断地努力着。编程语言越来越接近人类语言,主要靠越来越聪明的编译器来翻译。从实用的角度,一门编程语言基本就是一个编译器,它能把你的语言翻译成机器语言。
编程语言的进化史
==============
编程语言是随着计算机本身的发展而发展进化的,这是一件很自然的事。
编程语言的早年
---------------------
在计算机问世的早期,人们将数叠穿孔卡片提交给充斥着整个房间的笨重机器,而这种系统内存可能只有100KB。这些穿孔卡片代表着0和1,就是机器语言。后来,体积更大、运算速度更快的计算机问世了,但计算机仍然只能理解0和1。当然,用这种00010011,10001000,01101001之类的机器语言来编程,对人类来说太痛苦了。后来,随着CPU的问世,这些CPU的指令集成为了人们编程的符号集合,这就是汇编语言。汇编语言提供了一套精简的符号集合,如MOV,ADD之类,使用汇编语言直接面向CPU(特别是操作里面的寄存器)编程比直接用机器语言方便了很多。汇编语言高效直接,能够最充分发挥计算机的性能,至今还用来开发很多对性能要求很高或资源受限的程序。今天,X86指令集和ARM指令集是最常用的汇编指令。但是,汇编语言太底层,一个简单的动作也要写很多很多行,助记符量大难记,而且只能针对特定的硬件体系(不同的CPU指令集不同),移植性太差。于是人们又发明了更加易用的所谓高级语言。在这种语言下,其语法和结构更类似人类语言(特别是普通英文),且由于远离对硬件的直接操作,使得一般人经过学习之后都可以编程。
高级语言程序“看不见”机器的硬件结构,不能用于编写直接访问机器硬件资源的系统软件或设备控制软件。为此,一些高级语言提供了与汇编语言之间的调用接口。用汇编语言编写的程序,可作为高级语言的一个外部过程或函数,利用堆栈来传递参数或参数的地址。当然,现代的操作系统也提供了强大的硬件资源调用接口,开发者更多通过这些接口来调用硬件。
最早出现的高级语言是1958年约翰-巴克斯和他在IBM的同事合作设计的科学编程语言FORTRAN(取自Formula Translation的缩写)。这门语言至今仍然是自然科学界使用最广泛的编程语言。
与此同时,一个研究团队在1956年开辟了计算机的一个崭新领域——人工智能。这门学科的一个目标是创造出具备人类推理能力的计算机。由于人类的大部分推理过程都需要进行抽象,偏重数学运算的Fortran语言对此并不适用。卡内基-梅隆大学的艾伦-纽厄尔和赫伯特-西蒙建议用符号列表(list of symbols)来表现抽象的概念,并且把这种推理过程视为一种符号操作。假如有一块红色积木,一块蓝色积木和一块黄色积木,一个5岁大的孩子也可以告诉我们:如果红色积木在蓝色积木之上,而黄色积木又在红色积木之上,那么黄色积木必然也在蓝色积木之上。将前两个事实用符号表来表示,我们可能会写:above reb block 以及 above yellow block,之后引用符号操作规则,我们便能得出:如果(above x y)和(above z x),则(above z y)。年轻的约翰-麦卡锡对这一想法印象深刻,但他认为纽厄尔和西蒙的想法过于复杂。他简化了设计,加入两个强大的功能,也就是我们所知的递归(recursion)和求值(eval),并且创造了一门称为LISP的语言(取自“list processing”,即表处理的缩写)。LISP不仅是人工智能领域的首选语言,而且自1958年诞生起,和Fortran一起不断为计算机语言的设计提供灵感。LISP也是第一个函数式语言,它的精炼和强大被软件高手和黑客们公认(见《黑客与画家》),其精髓在于最接近数学与逻辑,以至于被麻省理工当做程序设计基础教材(《计算机程序的构造和解释》)。
这一年的夏天,一个国际计算机科学家小组在苏黎世成立,开始设计纳入LISP元素的Fortran语言的继任者。他们的精诚合作产生了里程碑式的Algol 60,它直接催生了Pascal、C和Ada这些语言,同时也是从PostScript到Excel等各种语言的直系祖先。
然而到了20世纪70年代早期,人们逐渐发现由Fortran、LISP、Algol所衍生出来的上百种语言都存在一个共同的弱点:写出来的程序让人很难读懂。在实际工作中,人们发现如果想修改程序的行为,往往需要整个重写。拥有生物学背景的艾伦-凯认为应该把程序构建成像活的生物那样:由独立自主的“细胞”构成,彼此通过信息传递进行合作。他认为通过自主单元来构建程序,将会使这些单元能够融入新的上下文情境。对于这种“细胞”,他使用了“对象”(Object)的称呼,并且将这种方式称为“面向对象”(object-orientation)。对象的行为取决于它得到的讯息。20年代70年代中期,艾伦-凯带领他在施乐公司的团队设计出了首个面向对象的语言Smalltalk。大批年轻人在数年间加入了它的用户群。由此开始,Smalltalk深刻影响了C++等日趋成熟的编程语言,其自身也衍生了一批专业的追随者。
1970年代——C语言诞生
-----------------------
谈到计算机语言,就不能不讲C语言,这是高级语言的里程碑。C语言是70年代早期贝尔实验室的Ken Thompson和Dennis M.Ritchie在开发UNIX系统的过程中创立的。1970年,Ken Thompson,以BCPL语言为基础,设计出很简单且很接近硬件的B语言(取BCPL的首字母)。并且他用B语言写了第一个UNIX操作系统。1972年,Ritchie 在B语言的基础上改造出了一种新的语言,这就是C语言。1973年初,C语言的主体完成。Thompson和Ritchie用它完全重写了UNIX。随着UNIX的壮大,C语言也流行起来。二十世纪八十年代,为了避免各开发厂商用的C语言语法产生差异,由美国国家标准局为C语言订定了一套完整的国际标准语法,称为ANSI C,作为C语言的标准。二十世纪八十年代至今的有关程序开发工具,一般都支持符合ANSI C的语法。2011年12月8日,ISO又正式发布了新的标准,称为ISO/IEC9899: 2011,简称为“C11”。
C语言是一门全能型的通用计算机编程语言,应用广泛,是学计算机者的必学,堪称编程界的普通话。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。C语言也很适合搭配汇编语言来使用(往往可以通过内联汇编语言或与汇编语言目标文件一起连接。对于任何一种操作系统环境,C函数的ABI(Application Binary Interface)与汇编语言的子过程(routine/procedure)的ABI一定是完全兼容的。尽管C语言提供了许多低级处理的功能,但仍然保持着良好跨平台的特性,以一个标准规格写出的C语言程序可在许多电脑平台上进行编译,甚至包含一些嵌入式处理器(单片机或MCU)以及超级电脑等作业平台。
C语言的特点包括:(1)系统级语言,可直接操作硬件底层,可用来编写操作系统;(2)跨平台,可以说是可移植性最强的语言,大到集群,小到单片机,C语言全可以运行;(3)静态语言:需要编译后才能运行;(4)强类型语言:提供了很多数据类型,并有严格要求;(5)面向过程的结构化语言:提供了常见的流程控制结构,如判断、循环、函数等,结构严谨,层次清晰,便于使用、维护以及调试;(6)简洁,但函数库丰富。C语言是所谓的“小内核”语言,就其语言本身来说很小(不多的关键字,程序流程控制,数据类型等),不提供诸如字符串、集合/列表或数组等符合对象的操作,也没有堆和垃圾回收机制等,没有输入输出工具,各种高级功能主要靠库函数提供,其中最基本的是标准库。
C语言直接影响了两大语言:C++和Java。
1980年代——面向对象和C++
------------------------------
C语言最大的问题是:它面向过程的,程序大了之后,各种过程交织在一起,极为复杂。这是面向对象的思想已经开始流行。到了1980年代,C++应运而生。贝尔实验室Bjarne Stroustrup在博士期间深入研究过Simula(一种最早的面向对象语言),非常欣赏其思想,于是就在C语言语法的基础之上,几乎把Simula的思想照搬过来,形成了最初的C++。C++问世以之初,主要用于解决规模稍大的传统类型的编程问题,迅速取得了巨大的成功,也证明了对象范式本身所具有的威力。
C语言是一个结构化语言,它的重点在于算法与数据结构。C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现过程(事物)控制)。C++,首要考虑的是如何构造一个对象模型,让这个模型能够契合与之对应的问题域,这样就可以通过获取对象的状态信息得到输出或实现过程(事物)控制。所以C语言和C++的最大区别在于它们解决问题的思想方法不一样。
C++对C的“增强”,表现在六个方面:
(1) 类型检查更为严格。
(2) 增加了面向对象的机制。
(3) 增加了泛型编程的机制(Template)。
(4) 增加了异常处理。
(5) 增加了运算符重载。
(6) 增加了标准模板库(STL)。
正因为C++具有如此的“集大成”特性,它成为编程界最强大的语言。
大约在同期,Brad Cox根据Smalltalk的思想设计了Objective-C,可是由于其语法怪异,没有流行起来。只有Steve Jobs这种具有禅宗美学鉴赏力的世外高人,把它奉为瑰宝,与1988年连锅把Objective-C的团队和产品一口气买了下来,后来成就了Max OS X和IOS的神话。
就在同一时期,图形用户界面(GUI)成为热门。虽然GUI的本质是对象范型的,但是当时(1980年代中期)的面向对象语言,包括C++语言,还远不成熟,因此最初的GUI系统无一例外是使用C和汇编语言开发的。或者说,最初的GUI开发者硬是用抽象级别更低的语言构造了一个面向对象系统。后来,随着C++的成熟,大量C++图形库的出现,如wxWigets、QT,乃至MFC等,GUI程序大都基于C++了。
C++由于语言本身复杂。C++的编译系统受到C++的复杂性的影响,非常难于编写,即使能够使用的编译器如果存在问题,可能难于被发现。由于本身的复杂性,复杂的C++程序的正确性相当难于保证。据说当年Linux之父Linus Torvalds曾经尝试用C++来开发Linux内核,由于种种原因,很快失败了。自那时起他就不时表达对C++的不满。
当然,这只是一面之词,C++虽然复杂,但掌握好了,功能的强大有目共睹,许多著名的游戏引擎,Google的JS解释引擎V8以及后来大热的Node.js,还有跨平台图形库Qt等大牛之作都是用C++开发的。Windows则定义了自己的C++(Virtual C++)并伴随它成长。
1990年代——Windows系统编程
-----------------------------------------------------------
90年代是Windows崛起的时代。以前编程要么是在小型机和服务器上编程(往往是UNIX环境),要么是IBM PC兼容机上用DOS命令编程。苹果的个人电脑虽然成功,但其封闭性令编程只是少数企业的专利。自从1990年Windows 3.0成功发布以后,Windows以排山倒海之势席卷了全球个人电脑,个人电脑进入千家万户,PC编程基本成为Windows编程的同义词。
由于Windows占领了全球桌面,桌面编程就完全要面向Windows了。由于Windows对底层硬件做了抽象和屏蔽,Windows系统下的软件开发只能基于微软开放的接口(API),虽说这方便了开发者,但也使开发者丧失了直接控制硬件的能力。尤其难受的是,微软的接口策略几经变迁,让Windows开发者只能不断适应。
第一个时代是所谓Win32 API时代。Windows 用汇编(x86)、C和C++编写。内核和很多关键服务都运行于CRT(Windows C/C++ runtime library)上,他们都采用dll技术动态链接。在Windows上用VC编写的程序也依赖于CRT,可以动态链接,也可以静态链接。前者运行时需要系统中已安装CRT的dll,后者不需要。Windows API也是基于CRT开发的(使用的类库就是CRT),离开CRT,Windows API也用不了。在编写操作系统时,你需要一个合适的低层库,以便完成一些基本的、多次重复的工作。于是,就有了CRT。在最低层的时候,根本连DLL这个概念都没有的,所以CRT的源代码只能做成lib,被静态链接。在你的程序(release版)被编译时,VC会根据你的编译选项(单线程、多线程或DLL)自动将相应的运行时库文件(libc.lib,libcmt.lib或Import library msvcrt.lib)链接进来。编译时到底哪个C run-time library联入你的程序取决于编译选项:/MD, /ML, /MT, /LD (Use Run-Time Library) 你可以VC中通过设置选择哪个C run-time library联入你的程序。
然后,随着Windows越做越复杂,Microsoft提出了API的概念,它提供Windows开发者一组接口,可以直接操作Windows,这就是Windows API了。当然,Windows API也是在CRT之上编写的。Microsoft将Windows API的一部分也打包到CRT里(认为这都是在Windows开发程序所需要的),做成CRT产品(扩展CRT)随编译器一起发布,此时CRT里的lib和dll都是Windows格式的,造成Windows上的程序无法跨平台移植。
Win32 API即为Microsoft 32位平台的应用程序编程接口(Application Programming Interface)。所有在Win32平台上运行的应用程序都可以调用这些函数。
使用Win32 API,应用程序可以充分挖掘Windows的32位操作系统的潜力。 Mircrosoft的所有32位平台都支持统一的API,包括函数、结构、消息、宏及接口。使用 Win32 API不但可以开发出在各种平台上都能成功运行的应用程序,而且也可以充分利用每个平台特有的功能和属性。
在具体编程时,程序实现方式的差异依赖于相应平台的底层功能的不同。最显著的差异是某些函数只能在更强大的平台上实现其功能。例如,安全函数只能在Windows NT操作系统下使用。另外一些主要差别就是系统限制,比如值的范围约束,或函数可管理的项目个数等等。
标准Win32 API函数可以分为以下几类:
1、窗口管理
2、窗口通用控制
3、Shell特性
4、图形设备接口
5、系统服务
6、国际特性
7、网络服务
在微软的官方IDE(集成开发环境)——Virtual Studio里,你可以选择用Win32 API来编写程序。这些函数繁多,调用起来也比较复杂,所以后来出现了很多类库来包装这些函数。这其中最有名的就是MFC。
第二个时代——MFC时代。MFC(MicrosoftFoundationClasses)是微软基础类库的简称,是微软公司实现的一个c++类库,主要封装了大部分的windows API函数。微软选择了C++,使得C++成为主流的开发语言,但也用自己的C++(VC++)重塑了C++语言,这就是微软的“帝国风范”了。 MFC除了是一个类库以外,还是一个框架,你应该试过,在vc++里新建一个MFC的工程,开发环境会自动帮你产生许多文件,同时它使用了mfcxx.dll。xx是版本,它封装了mfc内核,所以你在你的代码看不到原本的SDK编程中的消息循环等等东西,因为MFC框架帮你封装好了,这样你就可以专心的考虑你程序的逻辑,而不是这些每次编程都要重复的东西,但是由于是通用框架,没有最好的针对性,当然也就丧失了一些灵活性和效率,但是MFC的封装很浅,所以效率上损失不大。由于MFC对Win32 API封装得很好,很多程序员习惯于在Virtual Studio中用MFC编程,反而忘记了Windows API的用法了。
在这个时代,微软同时推出了COM组件的概念和开发模型,但一直没有成为主流。COM的要义是,软件是由COM Components组成,components之间彼此通过接口相互通讯。这是否让你回想起本文开篇所提出的对象范型的两个基本原则?有趣的是,在COM的术语里,“COM Component ” 与“object ”通假,这就使COM的心思昭然若揭了。Don Box在Essential COM里开篇就说,COM是更好的C++,事实上就是告诉大家,形而上学的“面向类设计”不好使,还是回到对象吧。
用COM开发的时候,一个组件“是什么”不重要,它具有什么接口,也就是说,能够对它发什么消息,才是重要的。你可以用IUnknown::QueryInterface问组件能对哪一组消息作出反应。向组件分派消息也不一定要被绑定在方法调用上,如果实现了 IDispatch,还可以实现“自动化”调用,也就是COM术语里的 Automation,而通过 列集(mashal),可以跨进程、跨网络向另一组件发送消息,通过 moniker,可以在分布式系统里定位和发现组件。如果你抱着“对象——消息”的观念去看COM的设计,就会意识到,整个COM体系就是用规范如何做对象,如何发消息的。或者更直白一点,COM就是用C/C++硬是模拟出一个Smalltalk。而且COM的概念世界里没有继承,就其纯洁性而言,比Smalltalk还Smalltalk。在对象泛型上,COM达到了一个高峰,领先于那个时代,甚至于比它的继任.NET还要纯洁。
COM的主要问题是它的学习难度和安全问题,而且,它过于追求纯洁性,完全放弃了“面向类设计” 的机制,显得有点过。
第三个时代——.Net和C#时代.
在面对Java竞争和互联网大行其道的时代,微软于2000年左右推出了.Net战略。在微软.NET战略中有几大重点,一是将网络作为计算存储中心,二是基于网络的操作系统和开发工具的架构;第三个更加人性化的自然界面。
.NET是 Microsoft XML Web services 平台。XML Web services 允许应用程序通过 Internet 进行通讯和共享数据,而不管所采用的是哪种操作系统、设备或编程语言。Microsoft .NET 平台提供创建 XML Web services 并将这些服务集成在一起之所需。一个.NET应用是一个使用.NET Framework类库来编写,并运行于公共语言运行时Common Language Runtime之上的应用程序。
Web Services是.NET的核心技术。那什么是Web Services呢?正如Web是新一代的用户与应用交互的途径,XML是新一代的程序之间通讯的途径一样,Web Services是新一代的计算机与计算机之间一种通用的数据传输格式,可让不同运算系统更容易进行数据交换。Web Services有以下几点特性:Web services允许应用之间共享数据;Web services分散了代码单元;基于XML这种internet数据交换的通用语言,实现了跨平台、跨操作系统、跨语言。Web services不是微软发明的,同样也不属于微软专有。Web services是一个开放的标准,和HTTP、 XML、SOAP一样。他们是一个工业标准而非微软标准,WS-I是为了促进Web Services互通性的联盟组织,最初是由IBM和微软所发起,其它的成员包括BEA System、惠普计算机(HP)、甲骨文(Oracle)、英特尔(Intel)和SUN 计算机(Sun Microsystem)。如今网络上存在的大多Web services其实没有使用.NET构架,Web services具有互操作属性,你同样可以使用Windows开发客户端来调用运行于Linux上面的Web services的方法。
在.NET中,Web service接口通常使用Web Services Description Language (WSDL)描述。WSDL 使用XML来定义这种接口操作标准及输入输出参数,看起来很像COM和CORBA的接口定义语言(IDLS)Interface Definition Languages。接口定义后就必须使用一些协议调用接口,如SOAP协议,SOAP源于一种叫做XML RPC(XML远程进程调用remote procedure calling)的协议,而Java则根据XML-RPC发展了自己的JAX-RPC协议用来调用Web Services。发布和访问Web Services的接口就用到UDDI了,这里我们只需要知道WSDL使用XML定义Web Services接口,通过SOAP访问Web Services,在internet上寻找Web Services使用UDDI就行了。服务器架构——Microsoft Windows Server System Microsoft提供了最佳的服务器构架—Microsoft Windows Server System—便于发布、配置、管理、编排Web Services。
2014年4月的Build开发者大会上,微软宣布开源一批.NET库和相关技术,成立.NET基金会去管理和引导开源组件的开发。微软还将在Apache 2.0许可证下开源Roslyn编译器堆栈,Roslyn是微软所谓的编译器即服务,包含了C#和 Visual Basic.NET 编译器。.NET基金会由来自微软、GitHub和Xamarin的代表组成,Xamarin由GNOME创始人Miguel de Icaza等人创建,开发.NET开源实现。Xamarin向基金会贡献了它的部分库。de Icaza在接受采访时表示,微软已经变了,不仅仅移除了许可证中的限制,而且与Xamarin合作征求设计反馈,在创作共用许可证下发布文档。2014年11月13日,为了进一步扩大云计算市场,微软将不再把.NET和Visual Studio等关键软件技术局限在Windows平台,今后还将兼容Linux、Mac OS X、iOS和Android。除此之外,微软还宣布将开放.NET核心服务器运行环境和框架的源代码,使得外部开发者也可以对这一软件开发平台做出贡献。作为这一变化的一部分,微软将允许开发者使用.NET运行环境和框架,来为Linux和Mac开发基于服务器和云端的应用。微软还推出了功能齐全的新版Visual Studio 2013,并将免费对独立开发者、学生、小企业等用户开放。
C#是微软公司发布的一种面向对象的、运行于.NET Framework之上的高级程序设计语言。C#看起来与Java有着惊人的相似;它包括了诸如单一继承、接口、与Java几乎同样的语法和编译成中间代码再运行的过程。但是C#与Java有着明显的不同,它借鉴了Delphi的一个特点,与COM(组件对象模型)是直接集成的,而且它是微软公司 .NET windows网络框架的主角。
C#是一种安全的、稳定的、简单的、优雅的,由C和C++衍生出来的面向对象的编程语言。它在继承C和C++强大功能的同时去掉了一些它们的复杂特性(例如没有宏以及不允许多重继承)。C#综合了VB简单的可视化操作和C++的高运行效率,以其强大的操作能力、优雅的语法风格、创新的语言特性和便捷的面向组件编程的支持成为.NET开发的首选语言。C#是面向对象的编程语言。它使得程序员可以快速地编写各种基于MICROSOFT .NET平台的应用程序,MICROSOFT .NET提供了一系列的工具和服务来最大程度地开发利用计算与通讯领域。C#使得C++程序员可以高效的开发程序,且因可调用由 C/C++ 编写的本机原生函数,因此绝不损失C/C++原有的强大的功能。因为这种继承关系,C#与C/C++具有极大的相似性,熟悉类似语言的开发者可以很快的转向C#。
C#所开发的程序源代码并不是编译成能够直接在操作系统上执行的二进制本地代码。与Java类似,它被编译成为中间代码,然后通过.NETFramework的虚拟机——被称之为通用语言运行时(CLR)——执行。 所有的.Net编程语言都被编译成这种被称为MSIL(Microsoft Intermediate Language )的中间代码。因此虽然最终的程序在表面上仍然与传统意义上的可执行文件都具有“.exe”的后缀名。但是实际上,如果计算机上没有安装.Net Framework,那么这些程序将不能够被执行。 在程序执行时,.Net Framework将中间代码翻译成为二进制机器码,从而使它得到正确的运行。最终的二进制代码被存储在一个缓冲区中。所以一旦程序使用了相同的代码,那么将会调用缓冲区中的版本。这样如果一个.Net程序第二次被运行,那么这种翻译不需要进行第二次,速度明显加快。
开源的.Net未来将是一股不可忽视的力量,Xamarin已经推出了使用C#开发移动端APP的工具。但.NetFrame Work 版本太多,基于一个版本开发的程序不能运行在另一个版本上,始终是个问题。
第四个时代——Windows8 时代
Windows 8-style application 又比传统的 .NET Framework 更加轻量且支持更多开发语言,连 JavaScript 都可以用來开发 Windows 8-style application,要有如此大的相容性,Windows 核心中提供给应用程序开发的库就要再次改写,这也是为什么会有 Windows Runtime Library 的原因。
Windows Runtime Library (Windows RT, WRT) 简单来说,就是给 Windows 8-style application 使用的 Windows API,就像 .NET Framework 是给 .NET应用程序用的 Windows API 一样,WRT 封装了 Windows API,並暴露了相关的物件和类别給 Windows 8-style application 的程序语言使用,而其中最令人关注的是 JavaScript,虽然以前在 Windows 2000 時,就有一个被称为HTML application 的应用程序类型,但 HTML application 是封装在浏览器沙箱內的程序,它只能活在浏览器的进程內,而不能访问操作系统的资源。但是在 WRT 中,JavaScript 除了得到 HTML5 和 CSS3 的奧援外,更得到了 WRT 的全力支持,让JavaScript 真的可以用來开发纯 Windows 应用程序了,不像 HTML application 只是个包在沙箱內的玩具而已。
Windows Runtime,或WinRT,是Windows 8中的一种跨平台应用程序架构。WinRT支持的开发语言包括C++(一般包括C++/CX)和托管语言C#和VB,还有JavaScript。WinRT应用程序同时原生支持x86架构和ARM架构,同时为了更好的安全性和稳定性,也支持运行在沙盒环境中。[1-2]
由于依赖于一些增强COM组件,WinRT本质上是一基于COM的API。正因为其COM风格的基础,WinRT可以像COM那样轻松地实现多种语言代码之间的交互联系,不过本质上是非托管的本地API。API的定义存储在以”.winmd"为后缀的元数据文件中,格式编码遵循ECMA 335的定义,和.Net使用的文件格式一样,不过稍有改进。[3] 使用统一的元数据格式相比于P/Invoke,可以大幅减少WinRT调用.NET程序时的开销,同时拥有更简单的语法。[4] 全新的C++/CX(组件扩展)语言,借用了一些C++/CLI语法,允许授权和使用WinRT组件,但相比传统的C++下COM编程,对于程序员来说,有更少的粘合可见性,同时对于混合类型的限制相比C++/CLI也更少。在新的称为Windows Runtime C++ Template Library(WRL)的模板类库的帮助下(就好似ATL之于COM一样)[5] ,规范的C++代码(遵循COM化规范)也同样可以用在使用了WinRT组件的程序里[6] 。不过MSDN建议使用C++/CX而不是WRL。
Windows Runtime (RT)并不是一些新闻网站说的那样微软自废.NET武功,而是恰恰相反,WinRT是Win32API的现代版,其中有很深的.NET的基因,是Metro UI的.NET基础,如果考察Metadata的变化,WinRT的API定义的元数据是基于标准ECMA 335,也就是.NET的标准 ,WinRT也是一个沙箱的环境,针对AppStore环境设计的。微软以推出Windows 8为契机,以解决Windows长期存在的问题,并带来了新的用户界面,使得Windows更加安全和AppStore的商业模式。
WinRT是一个新的API 集合,具有以下特性:
它实现了Metro UI规范的UI库
为Windows开发人员提供一个简单的UI编程模型,你不需要学习Win32API的那些复杂的API了
它使用XAML-base的UI系统
API都设计成了异步的
它和.NET一样是个沙箱的API,自成体系,用于创建AppStore上的应用程序。
API的元数据格式是ECMA335,和.NET一样的标准。这是不是意味着以后Mono也可以在xUnit上去实现这样的API呢?
WinRT包装的新的用户界面系统,和Win32API一样是Com的上层。
之前的新闻中一直在质疑.NET 被微软抛弃了,当然不是了。也不是所有的.NET API 都集成到了WinRT中,只是一个子集。当你使用C#和VB,你使用的是完整的.NET框架。但是他们只暴露了一个较小的子集API给Windows 8的开发者。你可能会想,我可以通过一些技巧使用到整个.NET,如果你的程序不需要提交AppStore上接受微软的审核,这是可以的。这种策略明显是跟苹果学的。借此机会.NET团队也对.NET做了一次清理,mscorlib.dll和System.dll中已被分割在不同的库里头了,随着Win8发布的.NET版本是4.5了,也就是说.NET 4.5不是.NET 4的简单补丁包,里头加了不少东西,ASP.NET的版本号也是4.5,不像.NET 2.0 ~3.5 SP1,ASP.net的版本还是2。0。为了在Win8里开发,开始学习.NET 4.5又是必须的了,这里关注的集中在客户端开发,同样的在服务器端开发方面.NET 4.5也加入大量的干货。
现在的Windows开发就是这样一种百花齐放的局面,用C/C++,Win32 API, COM, MFC, .Net/C#, WinRT哪个都行,取决于你的应用环境和技术基础。
2000年代——奔腾的Java
-----------------------------------------------------------
面向对象思想催生了另一个语言,这就是后来的企业级程序开发中坚力量——Java。
Java诞生于1991年的SUN公司,它原本是为消费类电子产品的嵌入式芯片而设计的。1995年更名为Java,并重新设计用于开发Internet应用程序。2010年Oracle公司收购Sun Microsystems,现在是Java的控制者。与传统程序不同,Sun 公司在推出 Java 之际就将其作为一种开放的技术。全球数以万计的 Java 开发公司被要求所设计的 Java软件必须相互兼容。“Java 语言靠群体的力量而非公司的力量”是Sun公司的口号之一,并获得了广大软件开发商的认同。这与微软公司所倡导的注重精英和封闭式的模式完全不同。Sun 公司对 Java 编程语言的解释是:Java 编程语言是个简单、面向对象、分布式、解释性、健壮、安全与系统无关、可移植、高性能、多线程和动态的语言。Java 平台是基于 Java 语言的平台。这样的平台非常流行。因此微软公司推出了与之竞争的.NET平台以及模仿Java的C#语言。
Java由四方面组成:
●Java编程语言,即语法。
●Java文件格式,即各种文件夹、文件的后缀。
●Java虚拟机(JVM),即处理*.class文件的解释器。
●Java应用程序接口(Java API)。
Java最出名的就是它的纯粹面向对象和虚拟机机制。Java虚拟机(Java Virtual Machine) 简称JVM Java虚拟机是一个想象中的机器,在实际的计算机上通过软件模拟来实现。Java虚拟机有自己想象中的硬件,如处理器、堆栈、寄存器等,还具有相应的指令系统。引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用模式Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。
主要特性
Java语言是易学的。Java语言的语法与C语言和C++语言很接近,使得大多数程序员很容易学习和使用Java。另一方面,Java丢弃了C++中很少使用的、很难理解的、令人迷惑的那些特性,如操作符重载、多继承、自动的强制类型转换。特别地,Java语言不使用指针,而是引用。并提供了自动的废料收集,使得程序员不必为内存管理而担忧。
Java语言是强制面向对象的。Java语言提供类、接口和继承等原语,为了简单起见,只支持类之间的单继承,但支持接口之间的多继承,并支持类与接口之间的实现机制(关键字为implements)。Java语言全面支持动态绑定,而C++语言只对虚函数使用动态绑定。总之,Java语言是一个纯的面向对象程序设计语言。
Java语言是分布式的。Java语言支持Internet应用的开发,在基本的Java应用编程接口中有一个网络应用编程接口(java net),它提供了用于网络应用编程的类库,包括URL、URLConnection、Socket、ServerSocket等。Java的RMI(远程方法激活)机制也是开发分布式应用的重要手段。
Java语言是健壮的。Java的强类型机制、异常处理、垃圾的自动收集等是Java程序健壮性的重要保证。对指针的丢弃是Java的明智选择。Java的安全检查机制使得Java更具健壮性。
Java语言是安全的。Java通常被用在网络环境中,为此,Java提供了一个安全机制以防恶意代码的攻击。除了Java语言具有的许多安全特性以外,Java对通过网络下载的类具有一个安全防范机制(类ClassLoader),如分配不同的名字空间以防替代本地的同名类、字节代码检查,并提供安全管理机制(类SecurityManager)让Java应用设置安全哨兵。
Java语言是体系结构中立的。Java程序(后缀为java的文件)在Java平台上被编译为体系结构中立的字节码格式(后缀为class的文件),然后可以在实现这个Java平台的任何系统中运行。这种途径适合于异构的网络环境和软件的分发。
Java语言是可移植的。这种可移植性来源于体系结构中立性,另外,Java还严格规定了各个基本数据类型的长度。Java系统本身也具有很强的可移植性,Java编译器是用Java实现的,Java的运行环境是用ANSI C实现的。[4]
Java语言是解释型的。如前所述,Java程序在Java平台上被编译为字节码格式,然后可以在实现这个Java平台的任何系统中运行。在运行时,Java平台中的Java解释器对这些字节码进行解释执行,执行过程中需要的类在联接阶段被载入到运行环境中。
Java是性能略高的。与那些解释型的高级脚本语言相比,Java的性能还是较优的。
Java语言是原生支持多线程的。在Java语言中,线程是一种特殊的对象,它必须由Thread类或其子(孙)类来创建。通常有两种方法来创建线程:其一,使用型构为Thread(Runnable)的构造子将一个实现了Runnable接口的对象包装成一个线程,其二,从Thread类派生出子类并重写run方法,使用该子类创建的对象即为线程。值得注意的是Thread类已经实现了Runnable接口,因此,任何一个线程均有它的run方法,而run方法中包含了线程所要运行的代码。线程的活动由一组方法来控制。Java语言支持多个线程的同时执行,并提供多线程之间的同步机制(关键字为synchronized)。
Java语言是动态的。Java语言的设计目标之一是适应于动态变化的环境。Java程序需要的类能够动态地被载入到运行环境,也可以通过网络来载入所需要的类。这也有利于软件的升级。另外,Java中的类有一个运行时刻的表示,能进行运行时刻的类型检查。
Java语言的优良特性使得Java应用具有无比的健壮性和可靠性,这也减少了应用系统的维护费用。Java对对象技术的全面支持和Java平台内嵌的API能缩短应用系统的开发时间并降低成本。Java的编译一次,到处可运行的特性使得它能够提供一个随处可用的开放结构和在多平台之间传递信息的低成本方式。特别是Java企业应用编程接口(Java Enterprise APIs)为企业计算及电子商务应用系统提供了有关技术和丰富的类库。
正是因为拥有众多优点,Java自面世后就对C++语言形成有力冲击。尤其是随着互联网时代的到来,基于WEB的开发日渐流行,Java更是独领风骚。主要的企业级Web服务几乎都是基于J2EE平台的,大量的框架使得Java社区一片繁荣,特别是Spring+Struts+Hibernate这SSH三剑客与MySQL+Tomcat的数据库运行环境堪称绝配,至今仍然是企业级WEB开发的主流。
但是Java也有缺点,首先,编写GUI程序是它的弱项。使用Swing平台编写的带有GUI(图形用户接口)的程序和其他原始程序非常不同,美观度差很多。由于虚拟机运行机制,Java的运行效率一直为人诟病,框架太多带来系统的叠屋架构,并不是所有的工程和环境需要企业级别的复杂性,比如一个简单的个人网站或者独自编程的程序师所写的程序。这些程序师会发现Java的复杂管理对于自己要做的程序来说过于强大了。一些人觉得Java在面向对象上面做的没有Ruby和Smalltalk纯粹。有些程序师不喜欢原始类型(primitive type)和类(class)的分离,尤其是那些曾经使用过Smalltalk和Ruby的程序师。Java的代码相对于其他的代码来说过于冗长,这与它的轻便化声明相违背。而Oracle公司对Java社区的不友好则对Java的未来投下了阴影。另外,Java的版本太多,版本之间差异颇多也是问题。
到了2110年后,随着Android在手机端的兴起,Java又有了新的用武之地,这是后话。
当时在网络编程方面能与Java抗衡的只有PHP。
2010以后 脚本语言的崛起
-----------------------------
PHP(Hypertext Preprocessor,中文名:“超文本预处理器”)是一种通用开源脚本语言。语法吸收了C语言、Java和Perl的特点,利于学习,使用广泛,主要适用于Web开发领域。PHP 独特的语法混合了C、Java、Perl以及PHP自创的语法。它可以比CGI或者Perl更快速地执行动态网页。用PHP做出的动态页面与其他的编程语言相比,PHP是将程序嵌入到HTML(标准通用标记语言下的一个应用)文档中去执行,执行效率比完全生成HTML标记的CGI要高许多。由于与Linux服务器、Apache网络服务器、MySQL数据库可以完美组合成“LAMP架构”,语法简单,又有ZEND这样强大的引擎,PHP在WEB服务器端开发中风靡一时。
其实PHP只是脚本语言的一种。脚本语言是为了缩短传统的编写-编译-链接-运行(edit-compile-link-run)过程而创建的计算机编程语言。它的命名起源于一个脚本“screenplay”,每次运行都会使对话框逐字重复。早期的脚本语言经常被称为批量处理语言或工作控制语言。一个脚本通常是一段文本,也就是它的源代码和可执行程序。
脚本语言是一种解释性的语言,例如Python、vbscript,javascript,installshield script,ActionScript等等,它不象c\c++等可以编译成二进制代码,以可执行文件的形式存在,脚本语言不需要编译,可以直接用,由解释器来负责解释。和系统程序设计语言相比:不同是脚本语言是被解释而系统程序设计语言是被编译。被解释的语言由于没有编译时间而提供快速的转换,通过允许用户运行时编写应用程序,而不需要耗时的编译/打包过程。解释器使应用程序更加灵活,脚本语言的代码能够被实时生成和执行。脚本语言通常都有简单、易学、易用的特性,目的就是希望能让程序设计师快速完成程序的编写工作。由于这种灵活性,脚本语言又被称为“动态语言”。
脚本语言的局限性在于它们的功能不完整,不能开发各种“系统级”程序。目前主要是用作Web服务器的后端语言,包括“开源脚本语言三杰”——perl/python/ruby。但是,Node.js的横空出世,使Javascript异军突起,打破这一局限。
Javascript是浏览器的脚本语言。从某种意义上讲,C是UNIX的脚本语言。是浏览器的流行促使了Javascript的流行。
JavaScript最初由Netscape的Brendan Eich设计,是用来为网页添加各式各样的动态动能的“小语言”,能为用户提供更流畅美观的浏览效果。通常JavaScript脚本是通过嵌入在HTML中来实现自身的功能的。后来ECMA(欧洲计算机制造商协会)以JavaScript为基础制定了ECMAScript标准。完整的JavaScript实现包含三个部分:ECMAScript,文档对象模型(DOM),浏览器对象模型(BOM)。
据说Brendan Eich只用10天时间就把Javascript设计出来了。由于设计时间太短,语言的一些细节考虑得不够严谨,导致后来很长一段时间,Javascript写出来的程序混乱不堪。如果Brendan Eich预见到,未来这种语言会成为互联网第一大语言,全世界有几百万学习者,他会不会多花一点时间呢?
总的来说,他的设计思路是这样的:
(1)借鉴C语言的基本语法;
(2)借鉴Java语言的数据类型和内存管理;
(3)借鉴Scheme语言,将函数提升到"第一等公民"(first class)的地位;
(4)借鉴Self语言,使用基于原型(prototype)的继承机制。
所以,Javascript语言实际上是两种语言风格的混合产物----(简化的)函数式编程+(简化的)面向对象编程。 这是由Brendan Eich(函数式编程)与网景公司(面向对象编程)共同决定的。这倒成了JavaScript的优点:既继承了LISP函数式编程的精髓,又面向对象,同时又有类似C的语法。用JS大牛Douglas Crockford的说法,JavaScript是“批着C外衣的LISP”。JavaScript的精华表现在轻量的函数式编程、弱类型、动态对象、原型继承和富有表现力的对象字面量表示法(JSON)。而它的缺点在于对全局变量的依赖,没有提供块级作用域,对unicode支持不好,没有真正的数组等,但如果在编程中加以注意,完全可以避免错误。
2009年之前,JavaScript只能在浏览器中运行。Node.js的出现打破了浏览器对Javascript的桎梏,使得Javascript可以在服务器端执行,这使它具有了同PHP/perl/python/ruby同样的能力,适合编写后台应用。
Node.js采用C++语言编写而成,是一个跨平台的Javascript的运行环境(解释器),这意味着你可以编写系统级或者服务器端的Javascript代码,交给Node.js来解释执行。node.js是对Google V8引擎的封装和优化。V8引擎执行Javascript的速度非常快,性能非常好。同时还提供了很多系统级的API,如文件操作、网络编程等。浏览器端的Javascript代码在运行时会受到各种安全性的限制,对客户系统的操作有限。相比之下,Node.js则是一个全面的后台运行时,为Javascript提供了其他语言能够实现的许多功能。
node.js使得javascript扩展到服务器端,统一了WEB开发前后端的语言。在此之后,node.js社区蓬勃发展,涌现出大量应用模块,大量前端(客户端)框架也应运而生,使得“前端”成为一门显学。HTML5规范的发布,移动端的兴起,更是大大提升了JavaScript的地位,使得HTML+ CSS + JavaScript编写大型跨平台程序成为流行。
目前,JavaScript显然已统一了Web编程界。由于Web的无处不在和跨平台优势,JavaScript在编程语言排行榜上地位日渐领先。
编程语言进化的哲学
===============
过去的半个多世纪,世界上诞生了成百上千种编程语言,约60种在今天仍然在广泛使用,其中包括科学计算、3D设计、图像处理、动画制作、机器人控制等领域的专业语言。就像工具帮助木匠解决问题一样,一门好的编程语言能够帮助我们解决计算机问题,而且编程人员也正如木匠习惯于自己的工具那样习惯于自己钟爱的语言。
语言学家本杰明-沃尔夫曾经说:“语言塑造了我们思考的方式,决定了我们思考的内容。”他这番话时针对人类语言说的,而计算机语言则进一步印证了这一主张。
编程语言被公认有三个范式:(1)面向过程;(2)面向函数;(3)面向对象。但我认为还应该有第四个范式:(4)面向问题。只要描述清楚问题,计算机就能自动给出算法和答案。关键在于对“问题”的标准化描述。
硅谷创业之父保罗-格雷厄姆的《黑客与画家》中的观点很值得借鉴:越来越多的编程语言涌现出来并进行竞争,在这之中我们要关心几个方向。
抽象性。抽象性越高的语言,越精炼,越便于移植,但也越脱离硬件。
静态语言和动态语言。静态语言在写代码时必须知道每个变量的类型,这样更安全,可以防止BUG,并且帮助编译器生成更快的代码。动态类型语言中,随便什么时候,你都可以把变量设为任意类型的值,最自由,对程序员的限制最少。
面向对象。现在大部分高级语言都支持面向对象,只是程度不同而已。有的语言允许你面向对象,有的要求你必须这样做。后一类不可取。
函数库。有的语言内核设计得并非很好,但有强大的函数库,所以流行了起来。未来函数库比语言本身更重要。
速度。未来的硬件必然会越来越快,所以不要太在意程序的运行速度。
内核。任何一种编程语言都可以分成两大组成部分:基本运算符集合(扮演公理的角色)和其他部分。基本运算符是一种语言能否长期存在的最重要部分。那些内核最小、最干净的编程语言才会存在于进化的主干上,生命力最强。不应该为了提高效率就往内核添加过多的公理,正确的做法是将语义与语言的实现予以分离,在实现上做好编译器优化。
易用性。一百年后的程序员最需要的编程语言就是可以让你毫不费力地写出程序的第一版的编程语言,哪怕它效率低下得惊人。
层次性。使用多层形式开发是一种很强大的技巧。自下而上的编程方法意味着把软件分成好几层,每一层都充当它上边那一层的开发语言。这种方法往往会产生更小、更灵活的程序,它也是通往软件圣杯——可重用性——的最佳路线。采用“自下而上”的编程方法。不用基础语言开发应用程序,而是在基础语言智之上先构建一种自己的语言,然后再用后者开发应用程序。最好再把你的“伪代码”用基础语言实现出来。这样写出来的代码会比用基础语言短得多。
性能分析器(profiler)。应用软件运行速度的提升的关键在于有一个好的性能分析器。
宏。一种语言如果不支持宏,那就不值得使用。
创新语言。设计新语言的方法之一就是直接写下你想写的程序,不管编译器是否存在。不要被当前的编程语言所影响。
数学。一种语言越接近数学和逻辑越不容易过时。因为数学是不会过时的。
形式。程序的形式应该仅仅反映它要解决的问题,代码中任何外加的形式都表明你对问题的抽象还不够深。手工完成的事,应该让代码通过宏的扩展自动实现。
命令行。一种有命令行解释器,可以实时反馈的语言就具有互动性。那些必须先编译后使用的语言就不具备互动性。
最后,我们借用《黑客与画家》的话描述我们梦寐以求的编程语言:
“这种语言干净简练,具有最高层次的抽象和互动性,而且很容易装备,可以只用很少的代码就解决常见的问题。不管是什么程序,你真正要写的代码几乎都与你自己
的特定设置有关,其他具有普遍性的问题都有现成的函数库可以调用。”
这种语言存在吗?是哪一个呢?我想每个人都有自己的答案。