大约2个月前,在Herb Sutter的网站上看到了一个链接,内容是Channel9网站对他和其他三名微软架构师就“编程语言发展”进行的采访,架构师中有Anders Hejlsberg。一看之下,就被这个
视频迷
住了。这些大师站在历史的高度,通观全局又不失细节,高屋建瓴,有点有面地谈到了多个语言的发展和语言间的相互关系。看完之后,感到视野得到了不小地开
拓,对于语言、框架、工具的关系;对于静态(动态)类型、函数(命令)型编程;对于“可组合性”、“并发性”、“抽象层次”都有了更多的认识。
说开点,随着互联网的真正深入生活,随着“多核”时代的到来,IT技术领域正在经历一场变革。这场变革和“可组合性”、“并发性”这两个关键词息息相关。围绕着这两个关键词,若干新点子,新技术被提出来,而这些新技术往往与软件产
业生产者所用的工具——编程语言紧密相关。因此,作为一个软件职业者(或爱好者),听听大师的谈话,对于把握这场变革的脉搏,跟上变革的潮流都不无裨益。
看完视频,感到由于语言关系,如此好的材料无法为广大中国程序员所知,实在是个遗憾,于是萌发了编译的念头。水平所限,错误难免,欢迎大家指正!此文在本
人博客上发布后,drdirac和pongba 两位朋友对译文提出了若干补充和修正,在此表示感谢!
Charles:今天的访谈主要
讨论两个相关的论题:可组合性与编程语言。作为程序员,当我们构造系统时,总是要面对这两个问题。你们是创设语法,搭建架构的人。所以,我想讨论的一点
是,你们是如何协调工作的?三个语言——C#、VB和C++都在演进,同时又服务于不同目的,C++更多服务于系统级,C#和VB更多偏向应用层面这一切
是如何形成的?你们一起工作吗?你们是如何决定语言创新的?你们是一起设计,还是想到什么后再与他人共享?
Anders:我想,你说的
两种情况都存在。早在做LINQ之前,Erik就在COmega项目上做了不少工作。LINQ和COmega相互影响,相似之处很多。我和他一直在讨论相
关问题。实际上,Erik也在C#设计组中,我们总是在交换意见。VB组和C++组的人也在一幢楼里,大家经常碰到一起。
Charles:但我的意思是,你们是否也像最终用户一样对自己做出区分?比如,有的事情在VB中能做,C#中就做不了。例如,VB以非常简单的方式实现了完全的晚绑定,而C#中根本没有晚绑定。为什么VB和C#如此不同?你们有意这样设计的吗?
Anders:我认为,影响这个问题更多的是历史原因。VB有其悠久而丰富的历史。VB刚出现时就是晚绑定语言,没有任何类型。很显然,晚绑定对VB来
说有某种核心作用。但是,从那时起,VB已逐步演进为一种更“强类型”的语言,到现在,你甚至可以把VB看作一种支持晚绑定的强类型语言。呵呵。实际的过
程刚好相反。C#从一开始就是强类型语言,而且,直到现在我们都坚持早绑定。这并非说C#未来也不会支持晚绑定,但是,它很可能以不同于VB的方式来做,
而且可能会有所改进。C#是否支持晚绑定其实只是一种选择。对于老式的弱类型对象模型来说,比如OLE,如果我们从晚绑定角度出发,会比从早绑定角度出发
好讨论得多,因为这种对象模型无非就是对象若干方法的交互,反射等。
Herb:在一定程度上,用户造成了语言之间的差异。对于靠近底层
编程的C和C++程序员来说,性能永远都是一个主要问题。你可能发现不同语言有不同特性,但是,更经常的,你会发现这些不同特性想要解决的是同一类问题,
比如,“并发执行”。现在,没人能忽视这个问题。在未来5到10年,一种语言如果想留在主流编程语言的队伍中,这个问题就无法忽视,因为这是硬件的发展方
向。我们正处于一个新时代——50年来,我们首次在非单核的机器上工作。任何人都无法忽视这点。因此,就这点来说,大家面临相似的问题。但是,根据处理方
式、语法的不同,具体特性也会不尽相同。我也相信,不同语言推出相似特性的时间先后顺序也不相同,因为不同语言服务于不同客户群体,客户要求不同。就像
Anders所说,各种情况都有一些。
Erik:我给个具体例子,说明VB和C#的差异。这例子是“无名表达式(或lambda表达
式)”。我们想在VB中加入这种功能。首先就是寻找正确的语法。我们向VB项目组要到了VB的主名称表,名称表中的名字往往对VB和C#都适用。但是,这
次他们想要更像关键字的名字,而不是像C#那样长长的名字,他们觉得像关键字的名字更加“VB化”一些。这里你看到的就是语法上的区别。但在语义上也有区
别。当你查看一个大函数内部嵌套很深的结构,比如for循环时,语言是何时、如何处理变量捕获、如何进行实例保护就非常不同。在C#中,每次循环时实例都
被保护,而VB有点像JavaScript,变量被隐性提升到函数顶部。所以,在变量捕获方面也存在语义上的区别。有时,这些区别极其细微,你必须用非常
变态的程序才能观察到。
Anders:只要你写出依赖这样的特性的程序,我们就能找出成百的Bug。
Brian:你逃不出“作战室”的。(译者注:微软“作战室”,是产品、程序、测试人员一起确认需求、找Bug之所在。)
Charles:这样看来,大家都同意不同语言在相互影响,不断演进。对于VB和C#来说,有相同的核心:处理引擎,你们必须在CLR的基础上出发,随
着CLR的演进而演进。很显然,C++属于另一个世界。但各种语言要互相影响,你们必须在C#中加点什么来吸引用户,让他们用C#而不是VB.NET,是
吧?应该不止是语法的区别,语言中必须还有一些核心的东西来吸引用户。
Herb:你说得对。但是,我不同意你提出的理由,说我们必须在
各自的语言中加点什么特性吸引用户,从而使他们不去使用其他的微软的语言。为什么呢?比如我更加关心使用C++或者C#的用户到底需要什么,怎样才能帮助
他们把工作完成得更好。也许某种语言性能强大,但我的工作是怎样才能使客户的工作更成功?我必须要考虑客户会如何集成,我怎样做才能使客户工作得更好,这
也是CLR的核心所在,因为目前已经不是靠一种语言就能完成整个项目的时代了。我怀疑在稍有点规模的项目中,是否还有人仅仅依靠一种开发语言。
一般说来,你用脚本语言写代码;其他语言写工具和组件;系统语言写核心——不停地在做集成。这就带来了我们所讨论的“可组合性”的问题。因为“可组合性
”本质上就是跨语言的问题。当你写Web浏览器时,你不知道某个插件是用C#、C++,某种CLR扩展,还是其他什么写的。不管如何,这些东西必须一起工
作,这就是主要的挑战。因为,要想使这种“可组合性”成为现实,我们必须时时将CLR和CLR以外的东西当作白盒来考虑。但是,这样做的时候又会碰到“锁
”的问题。“并发执行”已经越来越重要了,但是,“锁”完全不具备可组合性。因此,这是“可组合性”面对的主要障碍。总之,对我而言,这更多的是一个语言
交互的问题,而非语言竞争的问题。
Brian:我在一定程度上代表了用户。我是个物理学家,同时,我也经常写点小程序,进行模拟和仿
真,解决一些数学问题。要想成功,“可组合性”对我的来说非常重要。我可以不在乎编程语言,但是我很在乎该语言是否有我所需要的组件。基本上,我十分愿意
使用任何能使我的工作更简单的编程语言。
这里,我要戴上顶“老人”帽,谈谈历史上非常少的成功软件之一:数值计算库。这些东西是N年以
前用Fortran写的。几十年以来,人们用这些库解决了许多非常重要的科学问题。任何头脑正常的人都不会想重新写一个“线性代数包”或者类似的东西。有
许多数学家终其一生在完善这些软件包。我们需要的是“互操作性”,更是“可组合性”。所有人都知道,Fortran不支持递归,因为变量基于引用传递。这
就带来了包接口的问题:如果你想要集成自身就做集成的东西,你就不能在用这个包来集成自己,这行不通。回到C++、C#和VB上,这些语言我都使用,但更
喜欢C#一些,主要因为它的操作符重载。为什么我喜欢操作符重载?因为我做奇怪的线代计算,如四元数、八元数,此时用一个小加号就能够代表一大堆怪异的计
算。
可能听上去有点像是使用模板,但绝不是这样,我一用模板就会开始想:模板的预处理器是完备的,也许我可以仅用模板就实现出一个链表
处理库来解决。很快,我就会偏离真正的数学思考。在应用程序绝对需要晚绑定的场合,比如,那些小的计算模拟器。此时,我很自然地会选择VB。至于C++,
大多数时候,它被用来实现其他的语言。在用于科学的环境下,我多次实现过Scheme。总之,就是泛谈“可组合性”。
Anders:当
我开始编程生涯时,进入编程这行的学习曲线就是:学习要使用的编程语言本身。各个编程语言几乎在每个方面都不相同。语法是你要学习的很大一部分。但这是以
前的事了,现在你要学习巨大的框架,这个框架正越变越大,语法只是顶上的一颗“小樱桃”,我认为这方面确实进展很大。但是,实际上起作用的东西是学习所有
的API,学习你所基于的,越来越大的平台或者框架。如今,学习曲线的90%都耗费在这上面。掌握了这些,你就可以在C++、C#或者VB.NET什么的
之间,毫不费力地进行语言转换,将部分项目使用这种语言,部分项目使用那种,并且找出组合这些语言的解决方案。相对于以前,实际上是不久之前,这是个主要
的进步。当然,所有这些得以出现,是由于有了通用的类型系统,以及各种语言中的那些抽象。每种语言之间的差别则是细微的,而且这些差别说不上来有什么特别
的理由。
Brian:有时,这些语言必须综合运用。比如,如今的Windows编程就是一大苦事:你必须懂PHP、
JavaScript、HTML、XML、SQL等等,要把这些东西全写到名片上,你就只有小小的一块地方可以写自己的名字了。当然,能够同时使用多种语
言也有好处,至少你可以选择自己喜欢的语法。
Erik:我们的编程语言之所以有差异,还是因为这些语言没有能够统一起来,在语言下面还有若干不一致的地方,我们实际上是被强迫使用不同的东西。CLR就不一样,基于CLR上使用相同的库,这些语言之间的排他性就要少一些,你可以选择,而非被迫使用某种特定的语言。
Brian:目前我们做得很多工作就是减少大家被迫使用某种语言这种情况。我们努力改进平台,增加更多的功能,提供更多的.NET库。
Charles:但是,C++除之外,像VB和C#这样的语言,确实绑定在某个框架上。这样的话,在一定意义上是否有局限性?如函数型程序等将如何融入到我们所谈的巨大的框架中呢?比如Haskell,又比如流行的F#,它们的结构与现在的语言完全不同。
Erik:如果我们用“命令型语言”编程,我们的基本成份是“语句”。“语句”使用并且共享“状态”,从而导致不太好的“可组合性”。你不能拿着两段语
句,然后简单地把它们粘合到一起,因为它们的全局状态不能很好地交互。这就导致“命令型语言”不能很好地组合到一起。如果你看看LINQ,就会发现我们已
经更多地采用“函数型语言”的风格,所有的东西都基于表达式。“表达式”从其定义来说就是可组合的。从一定意义上来说,我认为在C#3和VB9中没有什么
东西是Haskell或F#中没有的。这里面有一些深奥的事情,如果你看看Haskell的类型系统,你就会发现这个类型系统跟踪程序的副作用。这给了你
一定形式的可组合性。现在你虽然不能把有某种副作用的语句组合到有其他副作用的语句上,但是,你可以组合副作用相同的东西。F#有一个非常强悍的类型推断
机制,它从设计之初就考虑了类型推断。我们以前也有类型推断,这并非什么新东西,但是现在的类型推断要考虑很多困难因素,比如,重载,这些东西使类型推断
很困难。如果你从这个角度来看,我认为我们已经在很大程度上采用了浓厚的“函数型”风格,并且以相当“可组合”的方式来使用表达式和lambda表达式。
Anders:我们对“函数型编程”的兴趣并非学院式兴趣。实际上,当编程语言向前推进时,我们面临两类挑战。一是古老的追求——不断提高程序员的生产率,对此将沿用一直以来的方法:提升抽象的层次,给程序员垃圾回收机制、类型安全、
异常处理,甚至是全新的“声明型”编程语言等。在提升抽象层次的过程中,正如Erik指出的,这些“声明型”语言获得了更高层次的“可组合型”。“函数型
”语言之所以有魅力,因此你可以做出“没有副作用”,或者其他承诺,这样一来可组合性就极大地提高了。不仅如此,在如何保证多核处理器、多CPU,
比如,32个CPU始终忙碌,我们也会有所收获。显然,当我们更多地使用“函数型”或者“声明型”风格的编程时,我们更有可能把运行时框架构建得能更好地
发挥多核的优势,更好地处理并发。如果以“命令型”风格来工作,我们能够发挥的余地就很小,因为你无法预见所有动作——这儿拿点东西,那儿放点东西,所有
动作必须串行执行,否则不可预料的事情就会发生。
Charles:作为程序员,使用了如此巨大的一个处理引擎——比如CLR之后,当然认为这些底层的东西应该被抽象掉。你的意思也是,如果我使用了一个4核的机器,运行时引擎应该有能力负责在CPU上的分配分配进程。
Anders:你这样想很正常。但是,CLR以及目前我们工业中绝大多数的运行时,都是“命令型”引擎,其指令集都相当传统,比如,堆栈增长;它们也拥
有易变的状态,包括易变的全局状态等等。在此之上,之所以能进行“函数型”编程,是因为“函数型”编程从本质上来说,是“命令型”编程所具备的能力集的一
个子集。现在我们想做的是最大化这种灵活性,但其实不过也就是让“函数型”能力子集越来越相关,使其越来越主流化而已。
Herb:我认
为有必要将“函数型”编程领域划分成两个部分。我非常同意Anders和Erik的意见。我不太同意的是这样的措辞:我们之所以继续使用“命令型”编程语
言,是因为这是大家目前所能理解的;通用程序开发者目前的工作并未取得巨大的成功;市场对于“所有的东西都是表达式,所有的语言都应该是表达式类型的语言
”这样的理念已经非常接受了;“函数型”语言是“串行执行”病的好药方。我们要想使“函数型”语言运转良好,关键点并不是处理好基本的表达式问题,而是处
理好lambda表达式和副作用的问题,是能够将表达式作为第一级的编程要素来使用——LINQ也是最近才在做,关键是能够指出lambda表达式和
Closure(译者注:函数型编程语言中的一个概念,可以方便地组合函数,返回函数)的副作用。实际上,最后这点目前是缺失的。这些东西在“命令型”语
言中也是要处理的东西。我为什么提这些?因为我觉得说“函数型”语言是方向,目前的“命令型”语言不够好,因此是垃圾,必须要抛在脑后,全面采用“函数型
”语言这样的说法不对。我认为,“函数型”语言到底能够帮助程序员完成哪些工作,目前还不太明了。比如,能够用它写通用代码吗?能够用它系统级代码吗?当
然,“函数型”语言有不少我们能够借鉴的好东西,比如lambda表达式,比如Closure,C#借鉴了,C++也在借鉴,这些语言因此增色不少。关于
“函数型”语言还有另一个问题,那就是,有两种类型的“函数型”语言。一种是没有副作用的,因此就没有共享、易变的状态的问题;一种是人人都在使用的。因
为你不太可能说,“瞧,我是完全并发安全的,因为每次我都从这个“微型像册”向量中得到一个拷贝。”或者说,“我操作这些元素的时候,我都是取得一个拷贝
”。不错,这时是没有共享、易变的状态,但是否能完全并发安全则不一定。
Anders:我的意思是,在类似C#或VB这样“命令型”编
程语言中加入“函数型”结构,能给我们提供“以函数型风格”写程序库的能力,从而我们就能够非常明确地说,如果你能保证传入的lambda表达式是纯粹的
函数,我们就能保证正确地把它分散到若干个线程或者CPU上,最后再把它综合起来,给出一个正确的结果。我们能保证代码运行得更快,同时还不用作任何编码
上的修改。然而,如果你在写一个大大的For循环,我们永远都不可能保证做到前面所说的,此时,“函数型”编程能够提供给你的是一系列表达式,再加上“把
代码当作参数传递”,“类型推断和泛型编程可以正确地绑定所有的类型”等特性,这样你就能更方便地编写“可组合的算法块”。
Charles:这不就削弱了抽象吗?
Herb:我想指出的是当前所有语言都刻意不保证
“没有副作用”。之所以如此的原因是,除非所有的语言都添加一些机制让程序员可以清除副作用,我们这些做语言的人不敢打这个包票。但是,添加这样的机制涉
及到众多参与者,大家必须一起思考、一起讨论什么是最好的方法,这个过程会很漫长。我们所做的是相信程序员,因为我们自己不知道。然而,很多情况下,程序
员也不知道,因为他写的函数要调用其他的库。而程序员根本不知道他使用的库的副作用如何。这里,“可组合性”又浮上水面了。程序员可以增加一个间接层来处
理这个问题,但是,除非他拥有涉及到的所有代码,没有人能够清楚地知道副作用会如何,问题依然存在。这就是难题所在。上面这些讨论对“锁”也适用,因为“
锁”也是全局问题,对“可组合性”是个障碍。
Brian:在这点上Haskell做得很好,Haskell是“永远没有副作用”的范例。
Erik:是的,但做到这点的过程也很痛苦,因为并非所有情况都一目了然。一旦你的库代码有副作用,而且因此使程序员的代码必须按照某种顺序执行,在某
种意义上,你是用汇编语言在编程,因为程序员将不再能用“表达式+表达式”的方式来写代码,他必须先对某个表达式求值,再对另一表达式求值,最后把值相
加。因此,我认为我们在这点上干得还是不够漂亮。
Brian:现在,我们在“流库”上有例子。好消息是,我们已经有Haskell向你展示如何以“可行性”方面的代价,换取绝对纯粹的方式。当然,除Haskell外,我们有各种“杂牌”语言。
Anders:没有纯粹的好或坏,我认为,虽然进展缓慢,我们仍然快到一个令人满意的中间点了。我完全同意说:如果我们确实能够保证函数的纯粹性,生活将会非常美好。最终我们得做到这点。
Erik:但是,副作用也并非全然是坏事,如果函数使用了一个局部变量,这就是使用了一个状态,但是,函数本身还可以是纯粹的。我觉得很难完全避免副作用,一些东西可以是局部不纯粹而整体纯粹的。
Herb:回过头,让我们从整体上看看“可组合性”。让我吃惊的一件事是,很多时候,人们甚至都没有意识到“可组合性”是个问题,以及自己实际上经常碰
到这个问题。其实,整个软件工业乃至整个世界已经基于可组合的软件了。在硬件会议上,我经常对硬件公司提到的是:硬件的并发问题已经被仔细地探索过了,而
且,当前消除共享、易变状态的最好办法就是“锁”;但是,锁是一种全局资源,不能被组合;“被锁”是经常发生的事情,而当拥有“锁”时,我还能调用任何其
他的未知的代码;于是,“可组合性”被破坏了。说到这里,有的听者往往一脸茫然:这有什么问题吗?我于是会问,你们是否上网下载别人刚刚发布的,自己喜欢
的新软件,比如,某个浏览器然后马上使用呢?答案是肯定的。我于是会再问,你们是否意识到了,当你们这样做时,这些软件很可能都是第一次在最终用户的机器
上被组合,被使用?既然如此,你们怎么可能对其进行测试?这时,屋子里有百分之十的人会露出恍然的表情,因为此前他们没有想过这个问题:这些软件是第一次
在最终用户的机器上被组合,我们怎么进行测试?正因如此,“可组合性”是更重要的一个问题。更不用说我们现在有AJAX应用程序,以及众多的插件经常被下
载,而且被要求在同一个用户界面中协调工作。
原文:http://tech.it168.com/a2009/0220/266/000000266178.shtml
国内最棒的Google Android技术社区(eoeandroid),欢迎访问!《银河系列原创教程》发布《Java Web开发速学宝典》出版,欢迎定购
分享到:
相关推荐
1. 技术深度:掌握至少一种或多种编程语言,如C#、Java、Python,并深入理解微软的技术栈,包括.NET框架、Azure服务、Power Platform等。 2. 系统设计:学习如何设计高可用、高性能、可伸缩的系统,包括负载均衡、...
【描述】"09年微软架构师Web Service PPT讲义"可能包含了当年Web Service的最新发展和技术趋势,涵盖了从基础到高级的各种主题,如SOAP、WSDL、UDDI等标准协议的解释,以及如何利用微软.NET框架来开发和部署Web ...
通过上述内容的整理与解读,可以看出这份架构师培训教材覆盖了软件开发与设计的多个方面,包括编程语言、软件工程概念、系统与数据库、设计模式与架构、计算机术语与概念、软件开发与调试工具、编程库与中间件、...
《人人都是架构师》这个主题,暗示了在IT行业中,每个开发者都有可能通过学习和实践提升自己,成长为一名优秀的架构师。在这个过程中,.NET和C#是两个关键的技术栈,它们在构建复杂系统和软件架构中扮演着重要角色。...
TypeScript的作者是安德斯·海尔斯伯格,C#的首席架构师。 [4] 它是开源和跨平台的编程语言。它是JavaScript的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。 [4-7] TypeScript扩展了...
【微软架构资料 asp.net】 本文将探讨微软架构在企业级应用开发中的核心知识点,重点关注ASP.NET技术。首先,我们要理解软件架构的基础知识,这对于构建高效、可扩展和可维护的系统至关重要。 软件架构师的角色不...
2. **C#语言基础**:C#是一种面向对象的编程语言,由微软开发,广泛用于Windows平台和.NET框架。掌握类、对象、接口、继承、多态等核心概念是必要的。 3. **.NET Framework**:这是C#编程的基础平台,包括类库、...
《.NET进阶书籍_人人都是架构师》这个压缩包文件显然聚焦于.NET技术栈的高级主题,特别是针对C#编程语言的学习与实践,旨在帮助开发者提升至架构师的层次。这里,我们将深入探讨.NET框架、C#语言特性和软件架构设计...
Shell脚本编程是Linux/Unix系统中的重要技能,它是一种用于自动化任务、管理系统和实现批处理操作的脚本语言。在Linux环境中,Bash(Bourne-Again SHell)是最常用的Shell,它扩展了原始的Bourne Shell功能,并且在...
《人人都是架构师》是一本深入探讨.NET技术体系和软件架构设计的书籍,它主要针对C#编程语言的开发者和对软件架构有兴趣的IT从业者。这本书籍旨在提升读者的.NET开发技能,帮助他们理解并实践架构设计的核心理念,...
【架构师关键词】涵盖了许多IT领域的重要概念,这些都是架构师在设计和管理复杂系统时需掌握的关键知识。以下是对这些关键词的详细解释: 1. **RUP(Rational Unified Process)**:RUP是一种全面的软件开发过程框架...
《人人都是架构师(0520_)》这个压缩包文件显然聚焦于IT行业的软件架构设计,特别是与C#编程语言相关的主题。架构师在IT领域中扮演着至关重要的角色,他们负责设计和规划复杂的软件系统,确保其高效、可扩展、可维护...
**RAD 10.2.3 Release 3 架构师安装及破解指南** 本文将详细介绍如何安装并破解 RAD Studio 10.2 Release 3 版本,这是专为 Delphi 开发者设计的强大集成开发环境(IDE)。Delphi 是一款著名的面向对象的 Pascal ...
从给定的文件信息中,我们可以提炼出一...通过上述内容,我们可以看到2010年左右的IT行业动态,涉及移动开发、企业战略、软件工程、云计算、开源项目、编程语言、Web技术等多个领域,体现了当时技术发展的趋势和热点。
### 软件架构师培训基础教程核心知识点详解 #### 一、软件架构的重要性与基础知识 **重要性:** - **稳定性和扩展性:** 一个良好的软件架构能够确保系统的稳定性,同时也支持未来的功能扩展。 - **伸缩性和适应性...
- OpenCV支持多种编程语言接口,包括C++、Python和Java,并且可以在多个操作系统如Windows、Linux、MacOS、iOS和Android上运行。 - 该库采用BSD许可证,意味着对研究和商业用途均免费,旨在提高计算效率,并专注于...