解读面向对象的程序设计(三)

接上一篇>>

接着来看OOP。OOP的未来在未来三年,程序员编写代码的方式会发生那些变化?

Stroustrup:在C++中,假如没有合适的库在背后支撑,完成任何重要的工作都可能是很复杂的。而一旦有了合适的库,任何东西都可以被我们操控于股掌之间。因此,构造和使用程序库的重要性与日俱增。这也暗示我们,泛型程序设计(genericprogramming)将会越来越多地被运用。只有通过GP,我们才能确保库的通用性和高效率。我还预期在分布式计算和“组件(components)”应用领域会出现喜人的增长。就大部分程序员而言,通过使用方便适用的程序库,这些开发工作会变得简单明了。

现在有一个趋势,编译器厂商试图把其特有的“对象模型”和图形界面(GUI)细节推销给用户。比如微软的COM和Inprise的类属性“properties”。对于用户来说,这既不必要,也不情愿。我所希望看到的程序库,应该是用标准C++打造,界面灵活,值得信赖的程序库。

通常,这些界面应该是平台无关的。C++的表达能力极强,即使不使用大量的宏,也应该足以达成这一要求。就算有些地方无法百分之百的遵守这一原则,也应该将对于平台和厂家的依赖性限制起来。这个目标的完成情况,可以反映软件工具产业对于应用程序开发行业的关注程度。我怀疑目前对于那些独立的、跨平台厂商来说,并不存在相应的市场。如果能够建立这样的市场,也许能够促进厂商们为客户做出“真正有用的”产品。

Lindholm:对于编写代码的开发者来说,主要的驱动力量仍将是两个:网络和分布式——也就是设计和开发非单机软件的需求。大部分的应用程序将不会是孤零零地运行在单一设备上,而是运用了类似EJB和JSP之类技术的,平台无关的分布式程序。程序员们将不得不面对分布式计算的重重险阻。这将对许多程序员所依赖的设计模式、技术和直觉构成严峻的挑战。这是选择编程语言之前必须认识到的,尽管不同语言的设计特性可能促进或者阻碍这一转化。

在网络应用的增长中,一个很重要的部分是小型移动设备和特殊Internet设备的爆炸性增长。这些设备各有各的操作系统,或者只在某种特定的设备领域内有共同的操作系统。我们现在还可以一一列举出这些设备——家庭接入设备、蜂窝电话、电子报纸、PDA、自动网络设备等等。但是这些设备领域的数量和深入程度将会很快变得难以估量。我们都知道这个市场大得惊人,PC的兴起与之相比不过小菜一碟。因此在这些设备的应用程序市场上,竞争将会相当残酷。获胜的重要手段之一,就是尽快进入市场。开发人员需要优秀的工具,迅速高效地撰写和调试他们的软件。平台无关性也是制胜秘诀之一,它使得程序员能够开发出支持多种设备平台的软件。

我预期的另一个变化是,我们对于代码(Java)和数据(XML)协同型应用程序的开发能力将会不断提高。这种协同是开发强大应用程序的核心目标之一。我们从XML的迅速流行和ebXML规范的进展中,已经看到了这个趋势。ebXML是一个针对电子商务和国际贸易的,基于XML的开放式基础构架,由联合国贸易促进和电子商务中心(UN/CEFACT)与结构性信息标准推进组织(OASIS)共同开发。

我们能否期望出现一个真正的面向组件(component-oriented)的语言?它的创造者会是谁呢?

Stroustrup:我怀疑,这个领域中之所以缺乏成果,正是因为人们——主要是那些非程序员们——对“组件”这个意义含糊的字眼寄予了太多的期望。这些人士梦想,有朝一日,组件会以某种方式把程序员赶出历史舞台。以后那些称职的“设计员”只需利用预先调整好的组件,把鼠标拖一拖放一放,就把系统组合出来。对于软件工具厂商来说,这种想法还有另一层意义,他们认为,到时候只有他们才保留有必要的技术,有能力编写这样的组件。

这种想法有一个最基本的谬误:这种组件很难获得广泛欢迎。一个单独的组件或框架(framework),如果能够满足一个应用程序或者一个产业领域对所提出的大部分要求的话,对于其制造者来说就是划算的产品,而且技术上也不是很困难。可是该产业内的几个竞争者很快就会发现,如果所有人都采用这些组件,那么彼此之间的产品就会变得天下大同,没什么区别,他们将沦为简单的办事员,主要利润都将钻进那些组件/框架供应商的腰包里!

小“组件”很有用,不过产生不了预期的杠杆效应。中型的、更通用的组件非常有用,但是构造时需要非同寻常的弹性。

在C++中,我们综合运用不同共享形式的类体系(classhierarchies),以及使用templates精心打造的接口,在这方面取得了一定的进展。我期待在这个领域取得一些有趣和有用的成果,不过我认为这种成果很可能是一种新的C++程序设计风格,而不是一种新的语言。

Lindholm:编写面向组件的应用程序,好像更多的是个投资、设计和程序员管理方面的问题,而不是一个编程语言问题。当然某些语言在这方面具有先天优势,不过如果说有什么魔术般的新语言能够大大简化组件的编写难度,那纯粹是一种误导。

微软已经将全部赌注押在C#上,其他语言何去何从?

Stroustrup:C++在下一个十年里仍然将是一种主流语言。面对新的挑战,它会奋起应对。一个创造了那么多出色系统的语言,绝不会“坐视落花流水春去也”。

我希望微软认识到,它在C++(我指的是ISO标准C++)上有着巨大的利益,C++是它与IT世界内其他人之间的一座桥梁,是构造大型系统和嵌入式系统的有效工具,也是满足高性能需求的利器。其他语言,似乎更注重那些四平八稳的商用程序。

竞争

C#会不会获得广泛的接受,并且挤掉其他的语言?

Lindholm:通常,一种语言既不会从别的语言那里获利,也不会被挤掉。那些坚定的Fortran程序员不还用着Fortran吗?对于个人来说,语言的选择当然因时而异,但就整体而言,语言的种类只会递增,也就是说,它们之间的关系是“有你有我”而不是“有你没我”。

对于一个新语言的接受程度,往往取决于其能力所及。Java技术被迅速接受,原因是多方面的,Internet和WorldWideWeb接口,在其他技术面前的挫折感,对于Java技术发展方向的全面影响能力,都是原因。另一个重要的原因是Java独立于厂商,这意味着在兼容产品面前可以从容选择。

C#是否会获得广泛接受?视情况而定。总的来说,那些对于平台无关性和厂商无关性漠不关心的程序员,可能会喜欢C#。那些跟微软平台捆在一起人当然可能想要寻找VB和VC的一个出色的替代品。但是对于程序跨平台执行能力特别关注的程序员,将会坚守Java之类的语言。这种能力对于多重访问设备(multipleaccessdevices)和分布式计算模型至关重要,而Java语言提供了一个标准的、独立于厂商运行时环境。

Stroustrup:C#的流行程度几乎完全取决于微软投入的资金多少。看上去C#的兴起肯定会牺牲掉其他一些语言的利益,但是事实上未必如此。Java的蓬勃发展并没有给C++带来衰败。C++的应用仍然在稳定增长(当然,已经不是爆炸性的增长了)。也许其他的语言也还能获得自己的一席之地。

不过,我实在看不出有什么必要再发明一种新的专有语言。特别是微软,既生VB,何需C#?

不同OOP语言各有什么优势和劣势?

Stroustrup:C++的优点自始至终都是这么几条:灵活、高效,而且并非专有语言。现在ISOC++标准的出现,巩固了最后一点。

我认为C++的高效是它最基本的优点。这种高效来自于其特有的数据和计算模型,较之Java和C#,这种模型更加贴近机器。不过,哪些程序才真正地渴望这么高的效率?这是个问题。我认为这类程序非常多。人们对于计算机的期望,永远都超越硬件科技的发展速度。很显然,Java和C#的设计者的想法不同,他们认为,在很多地方效率问题无关紧要。

C++主要的缺点,归罪于糟糕的教育(是那些始终认为C++是个纯粹面向对象语言的人,和那些把C++当成C语言变体的人导致了这种情况),归罪于不同平台上的不一致性,归罪于不完整、不标准的编译器实现,归罪于平台无关的系统级程序库的缺少。

这些问题归于一点,就是缺乏一个卓越的厂商,能够满足整个C++社区的需求,勇于投入大量的资金开发必要的程序库。

Lindholm:Java技术的成功,是因为它在合适的时间,出现在合适的地点,而且合理地选择了语言和计算平台的支持目标。Java并不是在所有场合都优于其他OOP语言,但是对于出现的新问题能够解决得很出色。它面向Internet计算环境,避免了C++中晦涩的结构,成功翻越了继承机制的恼人问题。垃圾收集机制显著地提高了生产率,降低了复杂度。

在网络背景下使用虚拟机,以及有关安全性和动态加载的一系列设计选择,迎合了正在出现的需求和愿望。这些特性使Java不仅成为现有程序员的新武器,而且也为新的程序员创造了繁荣的市场空间。

此外,Java拥有一个标准化的、二进制形式的类库,提供了必要的(当然并非充分的)平台与厂商无关性。平台与厂商无关性要求一项技术必须有清晰的规范,摒弃那些阻碍二进制标准实施的特性。C++虽然有一个ISO标准,但其实甚至对于相同系统与相同指令体系的各个平台,也提不出一个实用的、各版本兼容的二进制标准。

历史上很多使用虚拟机的语言饱受责难,是因为其不够出色的性能问题,而这要归过于缓慢的解释器和糟糕的垃圾收集器。Java的早期实现也因为同样的问题受到严厉的批评。但是自那时起,业界向新的虚拟机实现技术投入了大量资金,取得了显著的效果,如今在大部分场合,Java的性能跟常规的静态编译语言相比毫不逊色。这使得程序员在获得平台和厂商无关性的同时,也不必付出性能上的代价。

C++并没有强制使用面向对象方法,因此为了编写出色的面向对象代码,就要求程序员们有相当强的纪律性。很多公司就是因为这个原因放弃了C++。作为语言,Java的一个突出的优点就是强制面向对象方法,不允许非面向对象的结构。

C#介于C++和Java之间,脚踏两只船,因此既不够安全,又失之复杂。

对于公司来说,采用新的语言要付出巨大代价。雇不到好的程序员(没人熟悉这种新语言),培训费用高得惊人,学习过程中生产率和产品质量下降,多年的经验随风消逝,等等。一种语言如何克服这些障碍?

Lindholm:说得很对,采用新东西确实常常开销巨大。不过问题是:这个新东西是否能够节省更多的开支,或者提供巨大的改进,获取合理的回报?很多公司发现,转向Java技术不论在开发的后端(尽快进入市场、快速迭代开发、维护简单性)还是前端(跨平台发布,适用范围从低端设备到高端服务器的技术,安全性),都能节省大笔的开销。

对于新事物的接纳,常常是在痛楚的压力之下。很大程度上,这正是Java所经历的。Java的产生,是对当时很多系统的缺陷所做出的反应。Java技术通过下面的手段减轻了开发者的痛楚:1)顾及了网络计算方面的需求,是应运而生。2)在技术能力的抉择上,保持良好的品位,顾及了大众的心理。3)采用适度强制性策略推行设计决定。此外,Java技术已经成为大学教学中的主流,这同样保证了Java开发者队伍的不断壮大。

但是最重要的一点是,再没有另一种程序设计技术,能够像Java那样允许程序员开发基于Internet的不同平台之上的应用程序。Java平台在这方面的杰出表现,已经被大量的实例证明。Java已经成为Internet上的缺省应用程序平台,JavaAPIs也成为Internet应用程序开发的天然平台。

Stroustrup:微软和Sun把大笔的金钱扔在Java、VB和C#中,并不是因为他良心发现,也不是因为他们真的相信这些语言能够带给程序员更美好的生活,而是利益使然。

有一个说法,认为软件工具厂商如果能够把应用程序开发者的专业技术任务负担起来,将获取巨大的经济利益。我对其背后的经济分析颇为怀疑,我认为这很难成为现实,特别是当应用程序开发者使用开放的、标准化的工具时,他们可以有多种选择,从而使上面的想法更加不可能。

多年以前,C++就已经具有泛型能力(也就是templates和STL),有运算符重载,有枚举类型?我们会不会在Java的未来版本中看到这些特性?Java是不是应该纳入这些特性呢

Strousturp:从1988-89年起,C++就已经有了templates。但是我们花了不少时间来了解如何最好地运用这个工具,早期各厂家对于template的支持在品质上也有很大的差异。有些编译器厂商动作迟缓,至少有一个主要的编译器厂商(好像是指微软,微软在VisualC++4.0才开始支持template,在此之前一直声称template是过于复杂而又没什么用的技术,时至今日,VisualC++对于template的支持在主流编译器中都属于最差的一档——译者注)暗中鼓励声名狼藉的反template宣传,直到他们自己终于学会了这项技术为止。直到今天,对于template的支持在品质上仍然有待改进。

你上面提到的那些特性,我认为Java(还有C#)应该,也肯定会逐渐引入。那些对于程序员来说最有用的语言特性和概念,将会逐渐集中,成为各家主流语言的必然之选。也就是说,我认为类似析构函数和模板特殊化之类的机制,远远比枚举等机制重要得多。

Lindholm:Java技术成功的原因之一,就是很清楚哪些不该做。我们得多问几个为什么:这项特性是不是必不可少?增加它会带来哪些开销?运算符重载是C++中一项极其强大的特性,但是它也大大增加了C++语言的复杂度,很多人都难以招架。Java在各种可能的权衡之中,做出了明智的抉择,找到了能力与需求之间的完美平衡点。

当然,Java也会发展,而且最重要的是,现在是开发者们在推动发展。Java增加泛型能力这件事,很好地展示了Java是如何通过整个开发者社群的参与,在权衡中决定正确的平衡点。关于增加泛型类型(generictypes)的“Java规格申请”(JavaSpecificationRequest,JSR)已经进入JCP(JavaCommunityProcess)程序,而且已经开发了很长一段时间(参见http://java.sun.com/aboutJava/communityprocess/之JSR-014)。现在,在JCP中,有超过80个JSRs正在讨论中,这充分体现了整个体系对开发者的积极反馈和高度合作,这正是驱动Java平台不断进化的动力。

发展vs.革新(Evolutionvs.Revolution)

C++是一种发展型的语言,Java和C#似乎更像是革新型语言(它们是从头设计的)?什么时候,革新型的语言才是必需的呢?

Lindholm:Java技术并非凭空出世,反而更像是发展型的。Java所有的特性,在Java平台推出之前,都至少已经存在于另一种环境之中。Java的贡献在于,在众多的特性和权衡中,做出了合理的选择,使得产品既实用,又优雅。Java技术对于程序员的态度是:抚养,但不溺爱。

Stroustrup:从技术上讲,我并不认为Java和C#是什么“从头设计的”革新型语言。倘若Java是从技术原则出发,从头设计,大概就不会模仿C/C++那种丑陋和病态的语法了(不必惊讶,Stroustrup在很多场合表示过,C++采用C的语法形式,实在是迫于兼容性。他本人更偏爱Simula的语法——译者)。

我认为,只有当程序员们面对的问题发生了根本的变化的时候,或者当我们发现了全新的、极其优越的程序设计技术,又完全不能为现存语言所支持的时候,我们才需要全新的语言。问题是,我们恐怕永远也碰不到那些“根本”、“全新”的情况。

我以为,自从OOP问世以来,可称为“根本”的新型程序设计技术,唯有泛型程序设计(genericprogramming)和生成式程序设计(generativeprogramming)技术,这两项技术主要是源于C++templates技术的运用,也有一部分曾经被视为面向对象和函数式语言(functionallanguages)的次要成分,现在都变成正式、可用和可承受的技术了。我对于目前C++模板(template)程序设计的成果非常兴奋。例如,像POOMA,Blitz++和MTL等程序库,在很多地方改变了数值计算的方式。

Java和C#的一个“卖点”,就是它们的简单性。现在Java是不是快失去这个卖点了?

Stroustrup:新语言总是宣称自己如何如何简单,对老语言的复杂性颇多非议。其实这种所谓的“简单性”,简单地说,就是不成熟性。语言的复杂性,是在解决现实世界中极为烦琐和特殊的复杂问题的过程中逐渐增加的。一个语言只要活的时间够长,总会有某些地方逐渐复杂起来,或者是语言本身,或者是程序库和工具。C++和Java显然都不例外,我看C#也一样。如果一种语言能够度过自己的幼年时代,它会发现,自己无论是体积还是复杂性都大大增加了。

Lindholm:Java技术的的功能在增加,需要学习的东西也在增加。不过功能的增加并不一定带来复杂性的增加。Java技术的发展,并没有使学习曲线更加陡峭,只是让它继续向右方延展了。

标准

标准化语言和开放型语言各自的优点和缺点何在?

Lindholm:对于一个开放、不允许专有扩展、具有权威的强制性标准语言或者运行环境来说,不存在什么缺点。允许专有扩展就意味着允许厂商下套子绑架客户。特别重要的是,必须让整个平台,而不只是其中一部分完全标准化,才能杜绝厂商们利用高层次的专有API下套子。客户要求有选择厂商的自由,他们既要有创造性,又需要兼容性。

Stroustrup:对于一个语言,如C/C++来说,建立正式标准(如ISO标准)最大的好处,在于可以防止某一个厂商操纵这种语言,把它当成自己的摇钱树。多个厂商的竞争给用户带来的是较低的价位和较好的稳定性。

专有语言的好处,一是流行,二是便宜(不过等你被套牢了之后,情况就会起变化),三是对于商业性需求可以做出快速的反应。

标准化语言的特点之一是,它不能忽略特殊用户的需求。比如我在AT&T中所考虑的东西,其规模、可靠性和效率要求,跟那些普通厂商关注的大众软件相比,根本不可同日而语。那些公司很自然只关注主要的需求。

然而,多数大机构和身处前沿的公司,都有着特殊的需求。C++的设计是开放、灵活和高效的,能够满足我所能想象的任何需求。跟其他的现代语言相比,C++的家长式作风可谓少之又少,原因就在这。当然,不能赞赏这一点的人会诟病C++的“危险”。

相关推荐