随笔-15  评论-5  文章-0  trackbacks-0
  2011年3月4日
作者介绍:Brian Peasland,Techtarget网站Searchoracle子站的资深专家,SGT, Inc.公司首席DBA。Oracle7.3,8和8i的OCP,计算机科学硕士学位,专攻数据库方向。Brian 在IT行业从业已有20年,并且是从计算机操作人员到操作分析员、然后成为系统管理员,随后成为应用软件开发人员直至目前的DBA. 可以说,Brian本身的职业历程就是一部完整的DBA成长指南,后来他应美国Techtarget网站之邀,写了一个白皮书——《Grow that DBA Career》并发到了其个人的网站上 Peasland.net.


许多年来,我在不同的新闻组上花费了很多时间与那些想知道如何得到数据库管理员(DBA)的工作或者如何成长为一名DBA的IT人进行交谈,现在他们有了工作。这些年来许多人针对如何达到这个目标提出了不同意见。本文即是那些意见的综合并且能够在如何才能出色的完成DBA的工作方面给出好的建议。这篇文章同样对于如何让一名DBA变得对老板更有价值。假如你已经是一名DBA,那么也许你会希望跳过文章的前几段。

我应该成为一名DBA么?
  我曾问过的一个问题是一个人应该从事DBA这样的职业么。这个问题并不容易回答,因为它因人而异。有的人有成为一名好DBA所需要的天赋。而其他人并不认为能够很容易掌握成为DBA的秘诀。DBA职业需要掌握一定的技能。而且还需要其他IT职业所不必需的要求。因此,为了回答这个问题,我通常给将要成为DBA的人描述DBA职业所必需的要求。下面的段落中,我都将以问题结尾。在继续下一段以前请花一些时间考虑并且回答这些问题。
  许多人因为许多原因而立志要成为DBA。其中一个主要原因是薪水。DBA是IT业中薪水最高的职业之一。其他人想成为DBA是因为喜欢赞扬 DBA是受到的荣誉,或者因为他看上去很酷!我个人认为,成为DBA是很值得的。它是一个很有意思,令人兴奋的职业。那么,你把DBA作为一个可能的职业选择的原因是什么呢?
  除非你已经提前准备好了,否则你可能会发现从事DBA职业充满了挫折和令人头痛。一个数据库存在于操作系统和最终用户应用程序之间。同样地, DBA必须非常精通他的数据库所在的操作系统。DBA并不一定需要知道所有有关操作系统的知识,但是他知道得越多越好。数据库与操作系统联系非常紧密。理解这种关联是十分必要的。DBA还需要知道服务器硬件以及它如何影响与帮助数据库。同时,DBA必须理解应用软件。DBA可能会被要求帮助开发人员创建可靠,健全的数据库应用程序。还有,最重要的也是最明显的,DBA必须十分彻底的理解数据库引擎,它是如何工作的,所有的引擎是如何组合在一起的,以及如何影响数据库引擎向最终用户和应用程序传送数据的能力。我见过的最好的DBA有非常深刻的理解而且不仅仅在数据库本身。他们知道一些系统管理与应用开发。好多时候他们在成为DBA之前有其中一个或两个背景。无论如何,成为一名合格的而不是出色的DBA也需要许多背景知识。你是否已经做好准备开始学习直到你感到已经无法再学下去了?
  许多和我交谈过的,在开始DBA职业时遇到困难的人,在尝试着吸收大量DBA所需了解的信息时实际上都会有一些问题。毕竟系统管理员是全职学习操作系统的细节。应用程序开发人员全职学习如何编写好的程序。DBA不仅要非常了解这两种不同的工作,而且还需要花费更多的时间去理解数据库的体系结构,以及理解每一样东西的每一块是如何组合在一起的!听起来是不是很让人畏缩?有许多人失败后这样想,并且把DBA工作看作一项非常困难的事情。也有那些传播和理解所有这些信息,并且使用这些信息做出好的,听起来具有技术性的决定的人。正如我以前是一名DBA时喜欢说的,所有这些对我来说看上去像一个大谜团。把这些所有的很好的组合在一起就是挑战。你是哪一种人?

  许多DBA是随时侯命的。他们会在白天或晚上的所有时间接到呼叫去解决他们的数据库出现的致命问题。数据库是商业信息技术基础组织的必不可少的组成部分。没有数据,就没有必要拥有一个计算机系统。数据推动商业。假如amazon.com的网站不能在数据库中搜索产品并且假如没有人能够为他们的产品下订单,那么它会变成什么样?它就不会在商业中存在很久。当数据库down掉,即使只是很短的时间,公司也会损失重大。基于这个原因,DBA到达现场后必须尽可能迅速的解决问题。许多公司有自己的DBA团队以便可以轮流待命。这些DBA 24x7小时的维持数据库应用程序。假如工作需要的话,你准备好随时候命了么?

  一些DBA的职责包括为软件打补丁或者对数据库做些改变。通常,这些操作不能在公司职员工作的时候做,因为此时数据库必须运行以便他们能够工作。这意味着DBA经常不得不在很早或者深夜甚至周末,总之,在正常工作时间以外来完成工作。你准备好在非正常时间工作,或者你在找一个朝九晚五的工作?

  对DBA而言,需要掌握的一个重要内容就是通常被称为“软技术”的东西。DBA需要在团队中很好的工作,通常团队是在变化的,如系统管理员,网络管理员,应用程序开发人员,项目经理和其他人。DBA要能够用流利的英语解释复杂的技术概念,让团队中其他人明白。DBA还要能够在数据库相关问题上指挥团队队员。你的软技术怎么样?

  下面不是全部列表,但是包括了DBA的典型职责:

    · 把监视数据库实例当作每日必做工作以保证其可用性。解决不可用的问题。

  · 收集系统统计和性能信息以便定向和配置分析。

   · 配置和调整数据库实例以便在应用程序特定要求下达到最佳性能。

   · 分析和管理数据库安全性。控制和监视用户对数据库的访问。必要时审计数据库的使用。

  · 监视备份程序。必要时提供恢复。测试备份与恢复程序。

  · 升级RDBMS软件并且在必要时使用补丁。必要时升级或者迁移数据库实例。

  · 通过数据库相关动作来支持应用程序开发人员。

   · 跟随数据库趋向和技术。当可应用时使用新技术。安装,测试和评估Oracle新的相关产品。

  · 执行存储和物理设计。均衡设计问题以完成性能优化。

  · 创建,配置和设计信的数据库实例。

  · 诊断,故障检测和解决任何数据库相关问题。必要时联系Oracle支持人员以便使问题得到较好的解决。

  · 确保Oracle网络软件(SQL*Net, Net8, Names, OiD)配置和运行的很好。

   · 与系统管理员(Unix& NT)一起工作以保证Oracle相关事务得到很好的处理。

   · 为有效的,定期的维护数据库创建任何必要的脚本。

  前面各段的问题是为了使你考虑一名DBA该做些什么,帮助你决定这是不是适合你的职业。我并非意味着假如你的目标是成为DBA这些会阻止你。我只是尝试着展现一些事实。我看到过一些DBA一旦被实际工作打击了就一蹶不振。他们花费时间,精力和一些金钱获得了他们的第一份DBA工作。我个人认为这个职业非常有价值。而且我无法想像现在做任何其他的会怎样。所以,这一段帮助你决定这是不是你希望从事的。假如它是,那么尽你所有去得到它!

我怎样得到第一份DBA工作?

   你已经阅读了前面的段落并且认为成为一名DBA是一个好的职业。祝贺你!我希望你的职业能变成你想像得那么令人兴奋和有意义。那么,你如何找到第一份DBA工作?这个问题我已经听别人问了许多许多遍。

  在90年代早期,因特网急速发展。它使公司象草一般萌芽。公司蜂拥而至并且开始创建他们在网上的形象。几乎所有这些有网站的公司都需要一个数据库作为 web应用的后台。不幸的是,当时在该领域却没有那么多DBA。在IT业,DBA变得奇缺。那段时间里,得到一份DBA工作看上去只要可以拼出 “Oracle”或者可能只是在大学里接触过一学期的数据库就行。为了使生活变得更好,DBA的匮乏促使公司付给有潜力的职员很高的薪水。假如你想要成为一名DBA,很容易,非常容易。你需要做的就是证明你了解什么是数据库然后工作就会比你预期的更早的出现在你面前。ITPUB个人空间!K&d7a

   然后因特网的泡沫破灭了。大量投产因特网的公司破产。许多给公司工作的DBA重新寻找工作。缺少DBA的公司找到一名有DBA经验的人比以前容易得多。在21世纪初期,由于经济并不十分稳固,因此生活并不容易(至少在美国如此)。公司都勒紧了他们的裤腰带。所有这些转化为更少的工作机会和DBA 候选人更少的工作空缺。
  得到第一份DBA工作的最艰难的部分是每一个职位都要求有一些工作经验。如果你从公司的角度出发,你就可以理解为什么对DBA职位而言经验是必需的。假如他没有一点经验,你会付给这个人很高的工资让他去操作,维护和运行你IT基础组织的最大最重要的一部分么?你的公司会付钱给一名没有经验的 DBA么?并且,在等待他成长起来的过程中可能会损失上百万美元的收入。对大多数公司而言,这些问题的答案肯定是‘不’。所以,没有经验,获得你的第一份 DBA工作是很困难的。

   第一份DBA工作现在成了恶性循环的境遇。假如我没有任何经验,我怎样才能得到DBA的工作呢?我没有工作的话又怎么能得到DBA经验呢?这是要战胜的最困难的障碍。最困难的部分是获得第一个DBA工作。这部分的剩下部分将针对实现你第一个DBA工作的目标给你一些建议。

  提示#1:接受教育。--尽可能多的学习有关数据库的知识。这很可能将占用你正常工作以外的部分时间也精力。参加本地大学举办的数据库培训班。许多培训公司都会举办数据库管理员的培训班。假如你的老板不资助你的学习,那么你可能不得不自己支付这笔费用。许多DBA职业要求至少为计算机科学或相关专业本科以上学历,因此你必须至少有那样的文凭。

  提示#2:锻炼成为DBA。--许多数据库供应商都允许你下载他们数据库系统的测试版或评估版。下载一份并且在自己的个人电脑上安装软件。练习使用数据库。故意破坏数据库并且尝试修复它。尝试着履行你所能想到的尽可能多的DBA职责。测试和磨练你在自己的测试平台上的技能这样你就可以证明你的数据库管理能力。

  提示#3:获得认证。 --许多数据库提供商都提供自己的数据库产品的认证。许多公司现在都把认证看作是一种标准。需要记住的一件事是仅获得认证是不够的。通过DBA认证测试并不意味着你知道如何管理一个数据库。它只是告诉你以后可能的老板,现在你拥有了一定的技术。它还告诉你的老板你对DBA工作的态度是很认真的。我看到许多人抱怨他们已经得到了认证但是没有经验,却仍然不能得到第一份DBA工作。认证本身并不能使你得到工作,但它是无害的。即使没有其他的,在你进行认证的时候你也已经学到了许多知识。只是不要依赖认证来给你带来你要找的工作。你需要的比这还要多。但它会在最后帮助你。

  提示#4:利用你现有的技能。--许多DBA具有系统管理员背景。其他的有应用程序开发背景。假如可能,查看你能否利用现有的技能来得到工作。现在的目标就是为你和你的老板创造一个双赢的局面。例如,让我们假设你已经是一名系统管理员而想进入DBA领域。也许你会找到一份工作,这份工作一部分时间里可以用到你的系统管理技能,并且在剩下的时间里可以使你涉及到数据库管理领域。假如你已经是一名某个产品平台上的DBA但你希望转到其他产品平台,那么看看你能否找到一份同时接触两个产品平台的工作。这样,公司和你都得到了想要的。在你定向到了DBA工作后,你可以试着得到一个能让你全职作它的职位,也许还可以在同一个公司中。

   提示#5:利用现在的机会。--有时候,一个人进入DBA领域仅仅需要的是正确的地方和正确的时机。假如你现在的老板有一个机会让你进行任何数据库的项目,抓住这个机会!任何数据库经验就比没有数据库经验要好。让你的管理者知道你十分积极的在寻找任何可能的数据库机会。他们就有可能在下次机会到来的时候想到你。进行这些数据库项目以及看到你要成为一个DBA的渴望以后,他们可能会决定培训你,提拔你。许多许多人都是以这种方式获得他的第一个 DBA工作,在进行了一些数据库相关的项目后不知不觉的成为一名较低级的DBA。通常当一名DBA离开公司后,公司将在内部寻找一个候选人,假如他们认为这名候选人是可训练的话。

  提示#6:寻找较低级的DBA职位。--假如你只是为了一个较低级的DBA工作,看到DBA职位的需求描述说他们正在寻找高级DBA或者其他的。所以,让我们严谨一些。你并没有一个高级方面的经验。我已经讨论过了对于这样的职位为什么公司不会考虑你。但是他们会在低级的职位上考虑你。低级的 DBA在高级DBA的指导下完成工作。他们摸索窍门。一般来说,高级DBA对数据库承担责任,同时也获得所有的荣誉。但是不要焦急。随着你的事业发展,你将会有越来越多的责任和得到越来越多的信任。因为你没有任何经验,你应该从这里开始启航。

   我也听到过一些公司寻找一名高级DBA,但是到最后,他们实际想要雇一名低级的DBA。你或许希望申请这样的职位虽然你也许没有资格。他们可能还是会决定雇佣你。但是提前说明你仍然在摸索阶段并且已经是较低级的DBA水平。不要试图欺骗他们让他们认为你是高级DBA的水平。这只会降低你得到这项工作的机会。

   这些提示将帮助你得到第一份DBA的工作。祝你在寻找工作时有好运气。当你已经找到了第一份DBA工作后,继续下面的部分来学习如何往下走下去。

  我刚得到我的第一份工作!现在该怎样?

  祝贺你!你现在是DBA俱乐部的正式成员了!对于这份梦寐以求的令人激动的职业,你准备好了么?你的工作才刚开始并且你在学习上已经落在后面。你将会发现要成为一名高效的数据库管理员有大量的知识你必须掌握。你的第一年或前两年将花费比以前更多的时间来学习。假如你发现学习知识的数量使你大脑超负荷,那么休息一下,歇口气,然后再回到学习中去。为了帮助你继续走下去,你可以按照下面的方法进行:

  步骤#1: 关系型数据库理论 –这部分我假设你将管理的数据库是一个“关系型”数据库。其他数据库模型也存在,但是关系型模式是近二十年工业上占统治地位的一种数据库模式。假如你的数据库系统是其他的模式,那么学习它的理论。相关数据库理论是十分重要的。它是其他一切的基础。我也看到许多跳到数据库管理职位的人从不想去学习纯粹的关系型数据库理论。不可避免的,在他们的事业中对理论基础的匮乏作为缺点暴露了出来。假如你对关系型数据库理论理解得很好,那么你将非常容易的在任何平台的关系型数据库管理系统(RDBMS)中转变。我使用Oracle数据库,或者IBM的DB2,或者微软的SQL Server是无关紧要的。他们都是关系型数据库系统。他们在最底层都在做着相同的事情。区别在于他们怎样去做相同的事情。纯粹的关系型数据库理论对于较低级的DBA来说并非必需的。但是假如你想要超越低级DBA的水平它就是十分重要的。许多大学的教科书都很好的包含了关系型数据库的理论。其中一本被广泛使用的教科书就是由Elmasri and Navathe编写的数据库系统基础,

  步骤#2: 彻底的学习查询语言 –数据库都有语言让你能够从数据库中得到数据,把数据放到数据库中,以及修改数据库中的数据。对于关系型数据库而言,这种语言就是结构化查询语言 (SQL)。这门语言是你与数据库接触的工具。不能让这个工具成为以后学习的障碍,这一点很重要。在你的测试数据库中练习不同的SQL语句直到他们变成了你的习惯。这方面的一本非常好的书叫做Oracle 9i完全参考(Oracle 9i The Complete Reference)由Loney 和Koch编写,Oracle Press。每一名Oracle DBA都应该在他事业的早期阅读这本书。Oracle 9i参考手册(Oracle 9i SQL Reference manual)是另一个很重要的知识来源。在他们的技术网站TechNet上(http://technet.oracle.com)你可以访...t上有一个账号。

  步骤#3: 开始学习基本的数据库管理工作 –这难道不是你最开始在这里的原因?为什么它在列表的第三位?我们尝试着建造一个知识的金字塔,我强烈的感觉到一个人需要知道关系型数据库理论和SQL,并且在你学习如何进行基本的数据库管理工作时把他们当作工具来使用。这些工作包括启动和关闭数据库,备份和恢复数据库,以及创建/删除/ 修改数据库对象。对于Oracle数据库管理而言,在市面上有大量的书籍可以给你所期望的一个很好的体会。这本书是Oracle 9i DBA手册(Oracle 9i DBA Handbook by Loney on Oracle Press)。我知道的大多数DBA都在他们事业的早期不只一遍的阅读过这本书。这里,你应该同时阅读和理解Oracle 9i 概念指导,Oracle 9i管理员指导,以及Oracle 9i备份与恢复指导(Oracle 9i Concepts Guide, the Oracle 9i Administrator’s Guide, and the Oracle 9i Backup and Recovery Guide)都来自Oracle文档。

   步骤#4: 阅读,阅读,再阅读 –由于你才刚开始你的DBA职业生涯,因此你正在开始为你的技能奠定基础。这需要一段很长的时间去形成,吸收和领会所有你将学到的知识。毫无疑问的,比你资深的DBA由许多工作要做,因此他们可能不会总是腾出大量时间辅导你的学习。你不得不靠自己学习很多东西。这就是阅读的目的。市面上有许多书籍可以解答许多数据库相关的话题。Oracle Press是Oracle公司的官方出版社,有大量的Oracle相关书籍。同时也有其他的出版社,如Wrox Press 和 O’Reilly Press。你也可以找到Oracle文档来阅读。并且还有许多网站和新闻组。尽可能多的读书使你能够继续下去。还有,不只一遍的阅读它们可以使你吸收你第一次阅读时错过的内容。

  步骤#5: 创建测试案例 –我经常看到初学者问一些很基础的问题,其实假如他们花一些时间来考虑,这些问题都是很容易解答的。毫无疑问的,在你开始学习Oracle的时候你会有许多的问题。看看这些问题你能不能自己回答出来。例如,我又一次被问到能不能向有唯一性约束的列中插入空值。最开始,这看上去也许不是很容易回答的问题。但它却是非常容易去试验的!只需要创建一个简单的表。在其中的一列,假如唯一性约束。尝试着在该列插入一个空值。有效么?你应该能够非常容易的回答出这个问题了。那么,为什么要创建这些案例呢?一个原因是这样做可以提高你解决问题的能力。创建这些案例需要的技能就是解决问题用到的技能。解决问题的技能将会对你的DBA事业有很大的帮助。另一个原因是随着你的事业的发展,你将经常需要创建更复杂的测试案例以便保证数据库和应用程序的成功。在将来,甚至简单的测试案例也可以组成更复杂的数据库和应用程序分解。

  步骤#6: 找一个良师 –一个良师能够为你的DBA生涯(或者其它类似的职业)引领方向。他们能够给你指示,回答问题以及在你的DBA的成长过程中帮助你节约一些时间。但愿这篇文章能够在你事业发展的一段时间内起到良师益友的作用。假如你与一名资深的DBA共同工作,那么那个人应该有责任为你的事业进行有益的指导。你也可以同时选择其他的人指导你。

  步骤#7: 参加本地用户群 –许多跨国家的城市有本地用户群,他们定期聚会讨论数据库相关的话题。假如可能,参加其中一个本地用户群。这将给你一个与他人相互交流的很好的方法。

  我如何能够从一名DBA初学者变为一个具有中级水平的DBA?

   你已经成为DBA一段时间了,你现在希望你的技术水平提高一阶么?下一步该怎么做?首先,往回看前面的部分,确认你已经完成了所有的步骤。彻底理解 SQL语言是十分重要的。理解关系型数据库理论和掌握基本的数据库管理任务也是非常重要的。到如今,你应该阅读文档和其他书籍到已经郁闷了。假如没有,那么你还没准备好继续深造,增长你的DBA的技术水平。假如你已经准备好继续了,我已为你的继续深造准备了一些方法。

  步骤#1: 学习操作系统和你的服务器硬件 – 正如我前面所说,数据库存在于操作系统和服务器硬件之上。理解这些组成部分如何工作是很必要的。你应该知道如何与特殊的操作系统相合。你如何删除或者编辑文件?假如你的操作系统是Unix,你应该掌握命令行以及Unix命令如何辅助你工作。对于运行在Windows或其他操作系统上而言也是一样的。你同时需要对服务器的硬件有一定的了解。物理内存和虚拟内存有什么区别?RAID是什么以及不同的级别是如何产生影响的?为什么数据库喜欢更多的物理硬盘而非一个大硬盘卷?你需要知道这些事情以便你能够容易的与系统管理员进行如何配置好你的服务器以便使它能够充分的支持数据库方面的交谈。

  步骤#2: 学习应用程序设计因为它与数据库相关 – 如前面所述,数据库存在于操作系统与数据库应用程序之间。你真的需要这两者。SQL语言是如何帮助创建好的应用程序的?绑定变量是什么并且为什么他们很重要?Tom Kyte 写了一本非常好的书,在Oracle应用程序设计上给出了很好的建议。他的Expert One-on-one Oracle书可在 Wrox Press找到。我强烈推荐阅读此书。他详细的叙述了那些能够生成和破坏Oracle应用程序的东西。你需要知道这些,因为你的应用程序开发人员希望从你这里得到指导和数据库知识。学习任何与应用程序设计有关的知识。也许参加一个关于软件工程,操作系统或数据结构的课程班会有好处。

  步骤#4: 取得认证 – 也许你的工作并不需要,但是取得认证一定对你有益。作为DBA的每一天里,你学到了许多新的和令人激动的事情。也许在你职业生涯的这段时间里,有几天你没学到任何新的东西。但你仍然有很多要学习。成为一名OCP(Oracle Certified Professional) DBA要求你必须已经学到了数据库管理所有方面的基础。我发现在OCP考试的学习过程中,我学到了在我工作中从未接触过的东西。一次我学到了我从未碰到过的一个特殊课题,在后来的日子里我就能够使用那个知识解决问题。假如我从为在 OCP考试中学倒它,那么我永远也不会用那种特殊的方法去解决问题。这已经一次次的发生在我的面前。有的人可能会说认证实际上真的不值得。我要说它只会对你有益无害。所以,去取得认证吧!

  步骤#5: 获得一个资源库 – 在前面的部分中,我指出每个DBA都应该在Technet上有个账号。这是你其中一个主要资源。但是同时还有许多其他资源。很多人共享他们的Oracle 知识。假如你还没有开始,你应该用网络浏览器去搜索并收集很多Oracle资源。愿意的话,你可以从访问我的网站(http: //www.peasland.net)开始。下面是一些Oracle DBA必须了解得网站列表:

  Ask Tom –http://asktom.oracle.com

   Jonathan Lewis web site -http://www.jlcomp.demon.co.uk/ITPUB个人空间/HFcu N

  Ixora (Steve Adams) –http://www.ixora.com.au

   Orapub –http://www.orapub.com

  Metalink (Oracle支持网站) –http://metalink.oracle.com

    国内的:

    ITPUB论坛-http://www.itpub.net

    Oracle技术网 -http://www.oradb.net

    CSDN社区 -http://community.csdn.net

   还有许多其它的好网站

   步骤#6: 开始在不同的新闻组和论坛上交流 – 也许你已经发现了他们,但假如现在你还没有那么是时候去开始了。有许多的新闻组和论坛可以回答你的任何Oracle问题。在Oracle群落里还有许多高手愿意和你共享他们的知识。你所要做的就是提问。下面是一个列表包含了可以开始交流的最好的因特网团体:

  Usenet newsgroups – comp.databases.oracle.server和 comp.databases.oracle.misc 是两个可以交流的非常著名的世界性的新闻组。他们拥有大量的针对Oracle问题的交流卷宗。观看这些组的最好的方法式使用新闻广播员。但是假如你想通过基于web的方式访问,也可以通过Google搜索引擎搜索它。 (http://groups.google.com/groups?hl=...atabases.oracle)

  Quest Pipelines – 当他们在最开始还属于软件提供商RevealNet的时候,被称为the RevealNet Pipelines。现在,Quest购买了RevealNet 并且拥有Pipelines 。因为Pipelines是中等的,所以这些是我最喜欢的。你可以在这里找到Pipelines (http://www.quest-pipelines.com/index.asp)。

  观察别人是如何经历考验和磨难的是一件好事。假如你有问题,可以自由的在群里提出来。假如你要提出问题,通常应该包括一些信息,比如你的 Oracle版本和Oracle运行的平台。这些将会得到有很大的差别的答案。假如你忘记了,会有人提醒你!甚至你不用提问也可以从其他人的答案中学到许多知识。我已经记不得多少次我之所以能够解决问题完全是因为我记得其他人在新闻组里问过相同的问题。
posted @ 2011-03-04 15:38 学习才能进步 阅读(67) | 评论 (0)编辑 收藏
  2008年4月29日

简述:
  作为网页主体内容的BODY部分将直接显示在浏览器的窗口中,它里面的内容直接影响着整个网页的好坏,在网页设计中起着至关重要的作用。

  在开始编写具体页面内容之前,我们需要对页面进行整体的基本规划和设置,如整个页面的背景色、背景图案、前景(文字)色、页面左/上边距大小等等,在HTML中,我们用<body>标签内指定参数来设置:
<body bgcolor="?" background="?"text="?" leftmargin="?" topmargin="?"link="?" alink="?" vlink="?">…..</body>
其中各参数为:
Bgcolor:指定网页背景色,可指定其颜色值;例:bgcolor="#E2E2FF";
Background:指定网页背景图案地址,如background="images/back.gif";
Text:指定网页内文字颜色,如:text="#000000";
Leftmargin:指定网页的左边距,如:leftmargin="0";
Topmargin:指定网页上边距,同上。
Link:指定链接文字的颜色,如:link="blue";
Alink:指定当鼠标移动到链接文字上时文字的颜色,如:alink="red";
Vlink:指定当我们访问过后的链接颜色,如:vlink="#555555";
盗版它人网站的内容可耻,您查看的内容盗版于★点击设计★www.djasp.Net
示例:网页背景为白色,文字为红色,链接色为绿色,访问过的链接也为绿色,网页左边距为10像素,上边距为3像素。
代码如下:
<html>
<head><title>点击设计</title></head>
<body bgcolor="#ffffff" text="red" link="green"vlink="green" leftmargin=10 topmargin=3>
网页正文内容….
</body>
</html>

posted @ 2008-04-29 11:09 学习才能进步 阅读(268) | 评论 (0)编辑 收藏
  2008年4月18日
1、触发器

定义: 何为触发器?在SQL Server里面也就是对某一个表的一定的操作,触发某种条件,从而执行的一段程序。触发器是一个特殊的存储过程。
常见的触发器有三种:分别应用于Insert , Update , Delete 事件。(SQL Server 2000定义了新的触发器,这里不提)

我为什么要使用触发器?比如,这么两个表:

Create Table Student( --学生表
StudentID int primary key, --学号
....
)

Create Table BorrowRecord( --学生借书记录表
BorrowRecord int identity(1,1), --流水号
StudentID int , --学号
BorrowDate datetime, --借出时间
ReturnDAte Datetime, --归还时间
...
)

用到的功能有:
1.如果我更改了学生的学号,我希望他的借书记录仍然与这个学生相关(也就是同时更改借书记录表的学号);
2.如果该学生已经毕业,我希望删除他的学号的同时,也删除它的借书记录。
等等。

这时候可以用到触发器。对于1,创建一个Update触发器:

Create Trigger truStudent
On Student
for Update
As
if Update(StudentID)
begin

Update BorrowRecord
Set StudentID=i.StudentID
From BorrowRecord br , Deleted d ,Inserted i
Where br.StudentID=d.StudentID

end

理解触发器里面的两个临时的表:Deleted , Inserted 。注意Deleted 与Inserted分别表示触发事件的表“旧的一条记录”和“新的一条记录”。
一个Update 的过程可以看作为:生成新的记录到Inserted表,复制旧的记录到Deleted表,然后删除Student记录并写入新纪录。

对于2,创建一个Delete触发器
Create trigger trdStudent
On Student
for Delete
As
Delete BorrowRecord
From BorrowRecord br , Delted d
Where br.StudentID=d.StudentID

从这两个例子我们可以看到了触发器的关键:A.2个临时的表;B.触发机制。
这里我们只讲解最简单的触发器。复杂的容后说明。
事实上,我不鼓励使用触发器。触发器的初始设计思想,已经被“级联”所替代.
posted @ 2008-04-18 16:09 学习才能进步 阅读(91) | 评论 (0)编辑 收藏
  2008年4月17日
使用多层架构进行系统开发是现今系统设计的流行趋势。通过分解业务细节,将不同的功能代码分散开来,更利于系统的设计和开发,同时为可能的变更提供了更小的单元。

以下就是一个典型的多层体系结构图。

uploads/200607/24_142206_mt.png


首先我们以“订单(Order)”为例,进行一个简单的业务分解。

1. 订单自然包括订单的内容(OrderInfo),其中有诸如订单编号、商品名称、数量,以及金额等信息。
2. 有了订单信息,我们还需要一个存储订单的场所,那么自然需要有个操作读写的对象(OrderAccess)。
3. 为了外界能进行相关的订单操作,我们还需要有个业务逻辑对象(Order),它提供创建新订单,向订单插入/删除商品,保存订单等操作。

通过上面的分析,我们基本上可以将一个业务逻辑完整地分割为:

业务实体 ---> OrderInfo
数据访问 ---> OrderAccess
业务逻辑 ---> Order

基于系统架构考虑,我们将这些对象分别放置在不同的逻辑单元中,这些逻辑单元就组成了“多层”。

业务实体层(Model) ---> 业务实体 ---> OrderInfo
数据访问层(DAL) ---> 数据访问 ---> OrderAccess
业务逻辑层(BLL) ---> 业务逻辑 ---> Order

同样以上面订单为例,我们进一步讲述各层对象的实现细节。

1. 客户基本上只依赖于 Order 和 OrderInfo,通过他们就可以操作业务的全部,它并不关心业务存储等细节。

2. 大多数时候我们会将 OrderAccess 设计成 Internal Protected 方式,OrderAccess 可以是一个抽象类或者接口。我更习惯于将其实现为抽象类,因为某些方法是调用其他方法来实现的,抽象类的设计可以减少实现类的代码数量。另外将该抽象类设计成工厂方法模式,通过 IoC 或者 "配置反射" 来获得具体的实现类,可以减少层之间的耦合,也便于数据系统的替换。

3. Order 多数时候可以实现为 Singleton 或者静态类,它只是提供了一系列的方法来操作某些逻辑,通过接受 OrderInfo 参数来获取信息。其本身无需保存任何状态。如果需要实现购物车,只需将 OrderInfo 存储到 Session 之中即可。

通过上面的例子,我们还可以发现多层的另外一个好处就是更利于团队协作开发。架构设计人员无需考虑具体的数据库实现代码,而将设计重点放在业务层面;数据库开发人员自然也可将重心放在数据库访问优化上。团队成员之间不再是一人负责一个业务模块,不再有了 n 个数据访问类,不再有 n 种不同的对象模式等等。从传统的 "瓦罐作坊" 演变为 "工业流水线",更利于根据技术能力和业务熟悉度的差别来划分不同的角色。
posted @ 2008-04-17 17:13 学习才能进步 阅读(104) | 评论 (0)编辑 收藏
使用多层架构进行系统开发是现今系统设计的流行趋势。通过分解业务细节,将不同的功能代码分散开来,更利于系统的设计和开发,同时为可能的变更提供了更小的单元。

以下就是一个典型的多层体系结构图。

uploads/200607/24_142206_mt.png


首先我们以“订单(Order)”为例,进行一个简单的业务分解。

1. 订单自然包括订单的内容(OrderInfo),其中有诸如订单编号、商品名称、数量,以及金额等信息。
2. 有了订单信息,我们还需要一个存储订单的场所,那么自然需要有个操作读写的对象(OrderAccess)。
3. 为了外界能进行相关的订单操作,我们还需要有个业务逻辑对象(Order),它提供创建新订单,向订单插入/删除商品,保存订单等操作。

通过上面的分析,我们基本上可以将一个业务逻辑完整地分割为:

业务实体 ---> OrderInfo
数据访问 ---> OrderAccess
业务逻辑 ---> Order

基于系统架构考虑,我们将这些对象分别放置在不同的逻辑单元中,这些逻辑单元就组成了“多层”。

业务实体层(Model) ---> 业务实体 ---> OrderInfo
数据访问层(DAL) ---> 数据访问 ---> OrderAccess
业务逻辑层(BLL) ---> 业务逻辑 ---> Order

同样以上面订单为例,我们进一步讲述各层对象的实现细节。

1. 客户基本上只依赖于 Order 和 OrderInfo,通过他们就可以操作业务的全部,它并不关心业务存储等细节。

2. 大多数时候我们会将 OrderAccess 设计成 Internal Protected 方式,OrderAccess 可以是一个抽象类或者接口。我更习惯于将其实现为抽象类,因为某些方法是调用其他方法来实现的,抽象类的设计可以减少实现类的代码数量。另外将该抽象类设计成工厂方法模式,通过 IoC 或者 "配置反射" 来获得具体的实现类,可以减少层之间的耦合,也便于数据系统的替换。

3. Order 多数时候可以实现为 Singleton 或者静态类,它只是提供了一系列的方法来操作某些逻辑,通过接受 OrderInfo 参数来获取信息。其本身无需保存任何状态。如果需要实现购物车,只需将 OrderInfo 存储到 Session 之中即可。

通过上面的例子,我们还可以发现多层的另外一个好处就是更利于团队协作开发。架构设计人员无需考虑具体的数据库实现代码,而将设计重点放在业务层面;数据库开发人员自然也可将重心放在数据库访问优化上。团队成员之间不再是一人负责一个业务模块,不再有了 n 个数据访问类,不再有 n 种不同的对象模式等等。从传统的 "瓦罐作坊" 演变为 "工业流水线",更利于根据技术能力和业务熟悉度的差别来划分不同的角色。
posted @ 2008-04-17 17:13 学习才能进步 阅读(111) | 评论 (0)编辑 收藏
  2007年4月9日
二叉树是一种非线性的数据结构,在对它进行操作时,总是需要逐一对每个数据元素实施

     操作,这样就存在一个操作顺序问题,由此提出了二叉树的遍历操作。所谓遍历二叉树就  

     是按某种顺序访问二叉树中的每个结点一次且仅一次的过程。这里的访问可以是输出、比

     较、更新、查看元素内容等等各种操作。

     二叉树的遍历方式分为两大类:一类按根、左子树和右子树三个部分进行访问;另一类按

     层次访问。下面我们将分别进行讨论。


    1、 按根、左子树和右子树三部分进行遍历

遍历二叉树的顺序存在下面6种可能:

    TLR(根左右), TRL(根右左)

    LTR(左根右), RTL(右根左)

    LRT(左右根), RLT(右左根)

     其中,TRL、RTL和RLT三种顺序在左右子树之间均是先右子树后左子树,这与人们先左后右

的习惯不同,因此,往往不予采用。余下的三种顺序TLR、LTR和LRT根据根访问的位置不同分别

被称为先序遍历、中序遍历和后序遍历。

(1)先序遍历

若二叉树为空,则结束遍历操作;否则

访问根结点;

先序遍历左子树;

先序遍历右子树。

(2)中序遍历若二叉树为空,则结束遍历操作;否则

中序遍历左子树;

访问根结点;

中序遍历右子树。

(3)后序遍历

若二叉树为空,则结束遍历操作;否则

后序遍历左子树;

后序遍历右子树;

访问根结点。

例如。以下是一棵二叉树及其经过三种遍历所得到的相应遍历序列

二叉树的两种遍历方法:

(1)对一棵二叉树中序遍历时,若我们将二叉树严格地按左子树的所有结点位于根结点的左

侧,右子树的所有结点位于根右侧的形式绘制,就可以对每个结点做一条垂线,映射到下面的

水平线上,由此得到的顺序就是该二叉树的中序遍历序列

(2)任何一棵二叉树都可以将它的外部轮廓用一条线绘制出来,我们将它称为二叉树的包线,

这条包线对于理解二叉树的遍历过程很有用。

     由此可以看出:(1)遍历操作实际上是将非线性结构线性化的过程,其结果为线性序列,

并根据采用的遍历顺序分别称为先序序列、中序序列或后序序列;(2)遍历操作是一个递归的

过程,因此,这三种遍历操作的算法可以用递归函数实现。

(1)先序遍历递归算法
void PreOrder(BTree BT) {
      if (BT) { Visit(BT);
      PreOrder(BT->Lchild);
      PreOrder(BT->Rchild);
}

(2)中序遍历递归算法
void InOrder(BTree BT) {
      if (BT) {
         InOrder(BT->Lchild);
         Visit(BT);
         InOrder(BT->Rchild);
       }
    }

(3)后序遍历递归算法
void PostOrder(BTree BT) {
     if (BT) {
        PostOrder(BT->Lchild);
        PostOrder(BT->Rchild);
        Visit(BT);
       }
    }

   2 、按层次遍历二叉树

     实现方法为从上层到下层,每层中从左侧到右侧依次访问每个结点。下面我们将给出一棵

二叉树及其按层次顺序访问其中每个结点的遍历序列。

void LevelOreder(QBTree BT) {
     for (i=1;i<=BT.n;i++)
     if (BT.elem[i]!='#') Visite(BT.elem[i]);
}

二叉树用链式存储结构表示时,按层遍历的算法实现

访问过程描述如下:

访问根结点,并将该结点记录下来;

若记录的所有结点都已处理完毕,则结束遍历操作;否则重复下列操作。

取出记录中第一个还没有访问孩子的结点,若它有左孩子,则访问左孩子,并将记录下来;

若它有右孩子,则访问右孩子,并记录下来。

     在这个算法中,应使用一个队列结构完成这项操作。所谓记录访问结点就是入队操作;

     而取出记录的结点就是出队操作。这样一来,我们的算法就可以描述成下列形式:

(1)访问根结点,并将根结点入队;

(2)当队列不空时,重复下列操作:

从队列退出一个结点;

若其有左孩子,则访问左孩子,并将其左孩子入队;

若其有右孩子,则访问右孩子,并将其右孩子入队;

void LevelOrder(BTree *BT) {
      if (!BT) exit;
      InitQueue(Q); p=BT; //初始化
      Visite(p); EnQueue(&Q,p); //访问根结点,并将根结点入队
      while (!QueueEmpty(Q)) { //当队非空时重复执行下列操作
      DeQueue(&Q,&p); //出队
      if (!p->Lchild) {Visite(p->Lchild);EnQueue(&Q,p->Lchild); //处理左孩子
      if (!p->Rchild) {Visite(p->Rchild);EnQueue(&Q,p->Rchild); //处理右孩子
   }
}


   五、典型二叉树的操作算法

     1、 输入一个二叉树的先序序列,构造这棵二叉树

     为了保证唯一地构造出所希望的二叉树,在键入这棵树的先序序列时,需要在所有空二叉

    树的位置上填补一个特殊的字符,比如,'#'。在算法中,需要对每个输入的字符进行判

    断,如果对应的字符是'#',则在相应的位置上构造一棵空二叉树;否则,创建一个新结

    点。整个算法结构以先序遍历递归算法为基础,二叉树中结点之间的指针连接是通过指针

    参数在递归调用返回时完成。

算法:

BTree Pre_Create_BT( ) {
      getch(ch);
      if (ch=='#') return NULL;                     //构造空树
      else { BT=(BTree)malloc(sizeof(BTLinklist)); //构造新结点
      BT->data=ch;
      BT->lchild =Pre_Create_BT( );                 //构造左子树
      BT->rchild =Pre_Create_BT( );                 //构造右子树
      return BT;
    }
}

   2、 计算一棵二叉树的叶子结点数目

     这个操作可以使用三种遍历顺序中的任何一种,只是需要将访问操作变成判断该结点是否

     为叶子结点,如果是叶子结点将累加器加1即可。下面这个算法是利用中序遍历实现的。

算法:

void Leaf(BTree BT,int *count) {
      if (BT) {
      Leaf(BT->child,&count); //计算左子树的叶子结点个数
      if (BT->lchild==NULL&&BT->rchild==NULL) (*count)++;
      Leaf(BT->rchild,&count); //计算右子树的叶子结点个数
    }
}

   3、 交换二叉树的左右子树

     许多操作可以利用三种遍历顺序的任何一种,只是某种遍历顺序实现起来更加方便一  

些。而有些操作则不然,它只能使用其中的一种或两种遍历顺序。将二叉树中所有结点的左右

子树进行交换这个操作就属于这类情况。

算法:

void change_left_right(BTree BT) {
      if (BT) {
         change_left_right(BT->lchild);
         change_left_right(BT->rchild);
         BT->lchild<->BT->rchild;
       }
   }

   4 、求二叉树的高度

     这个操作使用后序遍历比较符合人们求解二叉树高度的思维方式。首先分别求出左右子树

的高度,在此基础上得出该棵树的高度,即左右子树较大的高度值加1。

算法:

int hight(BTree BT) {     //h1和h2分别是以BT为根的左右子树的高度
     if (BT==NULL) return 0;
     else {
         h1=hight(BT->lchild);
         h2=hight(BT->right);
         return max{h1,h2}+1;
        }
   }

   六、树、森林与二叉树的转换

   1、 树、森林转换成二叉树

     将一棵树转换成二叉树的方法:

     将一棵树转换成二叉树实际上就是将这棵树用孩子兄弟表示法存储即可,此时,树中的每

个结点最多有两个指针:一个指针指向第一个孩子,另一个指针指向右侧第一个兄弟。当你将

这两个指针看作是二叉树中的左孩子指针和孩子右指针时,就是一棵二叉树了。

     特点:一棵树转换成二叉树后,根结点没有右孩子。

     将森林转换成二叉树的方法与一棵树转换成二叉树的方法类似,只是把森林中所有树的根

      结点看作兄弟关系,并对其中的每棵树依依地进行转换。

    2 、二叉树还原成树或森林

     这个过程实际上是树、森林转换成二叉树的逆过程,即将该二叉树看作是树或森林的孩子

兄弟表示法。比如,若二叉树为空,树也为空;否则,由二叉树的根结点开始,延右指针向下

走,直到为空,途经的结点个数是相应森林所含树的棵数;若某个结点的左指针非空,说明这

个结点在树中必有孩子,并且从二叉树中该结点左指针所指结点开始,延右指针向下走,直到

为空,途经的结点个数就是这个结点的孩子数目。

posted @ 2007-04-09 16:25 学习才能进步 阅读(1234) | 评论 (0)编辑 收藏
  2007年4月6日

面向对象编程

  面向对象编程Object Oriented ProgrammingOOP面向对象程序设计)是一种计算机编程架构。OOP 的一条基本原则是计算机程序是由单个能够起到子程序作用的单元或对象组合而成。OOP 达到了软件工程的三个主要目标:重用性、灵活性和扩展性。为了实现整体运算,每个对象都能够接收信息、处理数据和向其它对象发送信息。OOP 主要有以下的概念和组件

      组件 - 数据和功能一起在运行着的计算机程序中形成的单元,组件在 OOP 计算机程序中是模块和结构化的基础。
      抽象性 - 程序有能力忽略正在处理中信息的某些方面,即对信息主要方面关注的能力。
      封装 - 也叫做信息封装:确保组件不会以不可预期的方式改变其它组件的内部状态;只有在那些提供了内部状态改变方法的组件中,才可以访问其内部状态。每组件都提供了一个与其它组件联系的接口,并规定了其它组件进行调用的方法。
      多态性 - 组件的引用和类集会涉及到其它许多不同类型的组件,而且引用组件所产生的结果得依据实际调用的类型。
      继承性 - 允许在现存的组件基础上创建子类组件,这统一并增强了多态性和封装性。典型地来说就是用类来对组件进行分组,而且还可以定义新类为现存的类的扩展,这样就可以将类组织成树形或网状结构,这体现了动作的通用性。

  由于抽象性、封装性、重用性以及便于使用等方面的原因,以组件为基础的编程在脚本语言中已经变得特别流行。Python 和 Ruby 是最近才出现的语言,在开发时完全采用了 OOP 的思想,而流行的 Perl 脚本语言从版本5开始也慢慢地加入了新的面向对象的功能组件。用组件代替“现实”上的实体成为 JavaScript(ECMAScript) 得以流行的原因,有论证表明对组件进行适当的组合就可以在英特网上代替 HTML 和 XML 的文档对象模型(DOM)。  


一、oop的基本思想


      OOP的许多原始思想都来之于Simula语言,并在Smalltalk语言的完善和标准化过程中得到更多的扩展和对以前的思想的重新注解。可以说OO思想和OOPL几乎是同步发展相互促进的。与函数式程序设计(functional-programming)和逻辑式程序设计(logic-programming)所代表的接近于机器的实际计算模型所不同的是,OOP几乎没有引入精确的数学描叙,而是倾向于建立一个对象模型,它能够近似的反映应用领域内的实体之间的关系,其本质是更接近于一种人类认知事物所采用的哲学观的计算模型。由此,导致了一个自然的话题,那就是OOP到底是什么?[D&T 1988][B.S 1991] .。在OOP中,对象作为计算主体,拥有自己的名称,状态以及接受外界消息的接口。在对象模型中,产生新对象,旧对象销毁,发送消息,响应消息就构成OOP计算模型的根本。

      对象的产生有两种基本方式。一种是以原型(prototype)对象为基础产生新的对象。一种是以类(class)为基础产生新对象。原型的概念已经在认知心理学中被用来解释概念学习的递增特性,原型模型本身就是企图通过提供一个有代表性的对象为基础来产生各种新的对象,并由此继续产生更符合实际应用的对象。而原型-委托也是OOP中的对象抽象,代码共享机制中的一种。一个类提供了一个或者多个对象的通用性描叙。从形式化的观点看,类与类型有关,因此一个类相当于是从该类中产生的实例的集合。而这样的观点也会带来一些矛盾,比较典型的就是在继承体系下,子集(子类)对象和父集(父类)对象之间的行为相融性可能很难达到,这也就是OOP中常被引用的---子类型(subtype)不等于子类(subclass)[Budd 2002]。而在一种所有皆对象的世界观背景下,在类模型基础上还诞生出了一种拥有元类(metaclass)的新对象模型。即类本身也是一种其他类的对象。以上三种根本不同的观点各自定义了三种基于类(class-based),基于原型(prototype-based)和基于元类(metaclass-based)的对象模型。而这三种对象模型也就导致了许多不同的程序设计语言(如果我们暂时把静态与动态的差别放在一边)。是的,我们经常接触的C++,Java都是使用基于类的对象模型,但除此之外还有很多我们所没有接触的OOPL采用了完全不一样的对象模型,他们是在用另外一种观点诠释OOP的内涵。

      什么是oop的基本思想呢?把组件的实现和接口分开,并且让组件具有多态性。不过,两者还是有根本的不同。oop强调在程序构造中语言要素的语法。你必须得继承,使用类,使用对象,对象传递消息。gp不关心你继承或是不继承,它的开端是分析产品的分类,有些什么种类,他们的行为如何。就是说,两件东西相等意味着什么?怎样正确地定义相等操作?不单单是相等操作那么简单,你往深处分析就会发现“相等”这个一般观念意味着两个对象部分,或者至少基本部分是相等的,据此我们就可以有一个通用的相等操作。再说对象的种类。假设存在一个顺序序列和一组对于顺序序列的操作。那么这些操作的语义是什么?从复杂度权衡的角度看,我们应该向用户提供什么样的顺序序列?该种序列上存在那些操作?那种排序是我们需要的?只有对这些组件的概念型分类搞清楚了,我们才能提到实现的问题:使用模板、继承还是宏?使用什么语言和技术?gp的基本观点是把抽象的软件组件和它们的行为用标准的分类学分类,出发点就是要建造真实的、高效的和不取决于语言的算法和数据结构。当然最终的载体还是语言,没有语言没法编程。stl使用c++,你也可以用ada来实现,用其他的语言来实现也行,结果会有所不同,但基本的东西是一样的。到处都要用到二分查找和排序,而这就是人们正在做的。对于容器的语义,不同的语言会带来轻微的不同。但是基本的区别很清楚是gp所依存的语义,以及语义分解。例如,我们决定需要一个组件swap,然后指出这个组件在不同的语言中如果工作。显然重点是语义以及语义分类。而oop所强调的(我认为是过分强调的)是清楚的定义类之间的层次关系。oop告诉了你如何建立层次关系,却没有告诉你这些关系的实质。
(这段不太好理解,有一些术语可能要过一段时间才会有合适的中文翻译——译者)

      面向对象的编程方法OOP是九十年代才流行的一种软件编程方法。它强调对象的“抽象”、“封装”、“继承”、“多态”。我们讲程序设计是由“数据结构”+“算法”组成的。从宏观的角度讲,OOP下的对象是以编程为中心的,是面向程序的对象。我们今天要讲的OOD是面向信息的对象,是以用户信息为中心的。

二、OOP技术的历史

  面向对象技术最初是从面向对象的程序设计开始的,它的出现以60年代simula语言为标志。80年代中后期,面向对象程序设计逐渐成熟,被计算机界理解和接受,人们又开始进一步考虑面向对象的开发问题。这就是九十年代以Microsoft Visual系列OOP软件的流行的背景。

  传统的结构化分析与设计开发方法是一个线性过程,因此,传统的结构化分析与设计方法要求现实系统的业务管理规范,处理数据齐全,用户能全面完整地其业务需求

  传统的软件结构和设计方法难以适应软件生产自动化的要求,因为它以过程为中心进行功能组合,软件的扩充和复用能力很差。

  对象是对现实世界实体的模拟,因面能更容易地理解需求,即使用户和分析者之间具有不同的教育背景和工作特点,也可很好地沟通。

  区别面向对象的开发和传统过程的开发的要素有:对象识别和抽象、封装、多态性和继承。

  对象(Object)是一个现实实体的抽象,由现实实体的过程或信息牲来定义。一个对象可被认为是一个把数据(属性)和程序(方法)封装在一起的实体,这个程序产生该对象的动作或对它接受到的外界信号的反应。这些对象操作有时称为方法。对象是个动态的概念,其中的属性反映了对象当前的状态。

  类(Class)用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。

  由上分析不难看出,尽管OOP技术更看中用户的对象模型,但其目的都是以编程为目的的,而不是以用户的信息为中心的,总想把用户的信息纳入到某个用户不感兴趣的“程序对象”中。

三、OOP 的优缺点

      · OOP 的优点:使人们的编程与实际的世界更加接近,所有的对象被赋予属性和方法,结果编程就更加富有人性化。

      · OOP 的也有缺点,就 C++ 而言,由于面向更高的逻辑抽象层,使得 C++ 在实现的时候,不得不做出性能上面的牺牲,有时候甚至是致命的 ( 所有对象的属性都经过内置多重指针的间接引用是其性能损失的主要原因之一;不过,笔者的局限性在于未使用过 VC++ 外的面向对象语言,所以不是十分肯定,哈哈,有人笑出来了… )。

      在计算机速度飞速发展的今天,你可能会说,一丁点的性能牺牲没什么大不了。是的,从面向对象的角度,使的编程的结构更加清晰完整,数据更加独立和易于管理,性能的牺牲可以带来这么多的好处,没有理由不做稳赚的生意吧?

      不过,在某些对速度要求极高特殊场合,例如你做的是电信的交换系统,每秒钟有超过百万的人同时进行电话交换,如果,每一个数据交换过程都是一个对象,那么总的性能损失将是天文数字!!

      或者这个例子不够贴身,再举个例子吧。假如你受聘于一个游戏设计公司,老板希望做出来的游戏可以更多的兼顾到更多的电脑使用者,游戏每秒钟的运行的帧可以更多,子弹和爆炸物可以更多、更华丽。那么,你会发现使用 C++ 会使你的程序变得笨拙,无法满足你的需求,除非你非得要你的游戏运行于奔腾四的机器上 ( 如果不是,而你又坚持用 C++ 的对象编程,那么请减少主角的枪的威力吧 )。

      如果你是冥顽不宁的人,你说不相信 OOP 会有性能上的损失,那么,我记得曾看到在 CSDN 上关于 VB 和 VC 执行效率的讨论的文章,讲述的就是使用了 MFC 以后,执行效率甚至低于 VB 开发出来的东西。请各位验证一下:如果使用的是纯粹的 C 语言语法的话,那么一定会比在 VB 编出来的东西要快很多 ( GetTickCount 函数可以查阅 MSDN ,如果想更加精确一些,可以使用 QueryPerformanceCounter 函数 )。

四、OOP的未来(撰文/Bjarne Stroustrup & Tim Lindholm   编译/孟岩)

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

Stroustrup: 在C++中,假如没有合适的库在背后支撑,完成任何重要的工作都可能是很复杂的。而一旦有了合适的库,任何东西都可以被我们操控于股掌之间。因此,构造和使用程序库的重要性与日俱增。这也暗示我们,泛型程序设计(generic programming)将会越来越多地被运用。只有通过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++中,我们综合运用不同共享形式的类体系(class hierarchies),以及使用templates精心打造的接口,在这方面取得了一定的进展。我期待在这个领域取得一些有趣和有用的成果,不过我认为这种成果很可能是一种新的C++程序设计风格,而不是一种新的语言。

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

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

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

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

竞争

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

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

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

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

 

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

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

 

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

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

我认为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上的缺省应用程序平台,Java APIs也成为Internet应用程序开发的天然平台。

 

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

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

 

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

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

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

 

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

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

 

发展 vs. 革新(Evolution vs. Revolution)

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

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

 

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

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

我以为,自从OOP问世以来,可称为“根本”的新型程序设计技术,唯有泛型程序设计(generic programming)和生成式程序设计(generative programming)技术,这两项技术主要是源于C++ templates技术的运用,也有一部分曾经被视为面向对象和函数式语言(functional languages)的次要成分,现在都变成正式、可用和可承受的技术了。我对于目前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++的“危险”。

拥有正式和开放标准的语言主要是为编程工具的使用者和客户服务的,而拥有专属“标准”的语言,主要是为厂商服务的。

posted @ 2007-04-06 17:08 学习才能进步 阅读(118) | 评论 (0)编辑 收藏

真实的C++之父

——Bjarne Stroustrup访谈录

赵玉勇

Bjarne Stroustrup简介

 

 

许多重要人物之所以成名,或者是因为其改变了历史或者是因为其创造了历史,Bjarne Stroustrup先生,C++之父,属于后者;归结个人成功的原因,理由可能有许多,但他只有浅显的两个一点点:他比多数人天真和理想主义那么一点点;比多数人花在解决问题上的时间多一点点。

C++程序设计语言是一种承前启后,被数以百万计的程序员应用在各个领域中的语言,我们正在使用的Windows操作系统,我们上网用的浏览器IE无不是出自C++的手笔。

C++是一种重要的和比较流行的计算机语言之一,也是未来十年内仍然发挥重要作用的语言。C++语言是一种通用的应用广范的程序设计语言,是一种既支持传统的结构化程序设计,又支持面向对象程序设计的系统复杂的语言。C++C语言的扩充首先由 Stroustrup先生于1980年在贝尔实验室提出的,于1983年改名为C++。尽管C++的祖先C语言是世界上最受喜爱和应用最广的专业程序设计语言之一,但C++的发明是必需的。C++的本质就是让程序员理解和管理更大更复杂的程序。而对这种语言有着最大贡献的C++之父又是怎样一个人呢?

Bjarne Stroustrup先生,1950年生于丹麦港口城市奥尔胡斯,1975年在奥尔胡斯大学毕业,1979年获得剑桥大学计算机科学博士学位。他是C++语言的设计者和实现者,现在是得克萨斯州A&M大学计算机系教授。1979年他来到美国的新泽西州并加入贝尔实验室,与C语言之父、1983年图灵奖得主Dennis Ritchie以及大名鼎鼎的Brian Kernighan(两人合著《C程序设计语言》)共事多年,期间参与了贝尔实验室的C语言标准化活动。他的研究兴趣十分广泛,包括分布式系统、操作系统、仿真、设计以及编程,Bjarne还积极推动C++ANSI/ISO标准化。

20世纪90年代以后,Bjarne Stroustrup步入人生的最辉煌时期。

1990年,Bjarne荣获《财富》杂志评选的“美国12位最年轻的科学家”称号。

1993年,由于在C++领域的重大贡献,Bjarne获得了ACM该年度的 Grace Murray Hopper大奖并成为ACM院士(成立于1947年的ACM协会是历史最悠久、目前世界上最大的教育和科学计算协会,成为ACM院士是个人成就的里程碑)。

1995年,BYTE杂志颁予他“近20年来计算机工业最具影响力的20人”的称号。

除了他的专业研究领域外,他对历史,通俗文学,摄影,运动,旅行和音乐等有广泛的兴趣。他对C++语言的推广也做出了极大的贡献,他写的书“The C++ Programming LanguageC++程序设计语言》”已经成为这种语言中最为流行的学习资料,至少被翻译成18种语言。

 

给中国程序员最美好的祝愿

2004128日,杭州,C++之父Bjarne Struostrup先生再次来到中国。我们有幸采访到了这位大师!请看大师给中国程序员的最美好祝愿。

问: 您对中国和中国的程序员有什么认识?您想对他们说点什么吗?

Bjarne Stroustrup中国是个大国,并且她有许许多多有趣的文化。我想和中国程序员说的和对其他国家的程序员说的是一样的,所以我有如下的回答:优秀软件所具有的特点和技术在全世界都是通用的。

 

C++之父给中国程序员最美好的祝愿

 

现在,成为一名电脑高手是许多年轻学生的梦想,面对Stroustrup这样一位大师级人物的出现,最令我们感兴趣的问题莫过于:Bjarne成为大师的历程是什么样子的呢?

Bjarne Stroustrup先生出生的奥尔胡斯市是日德兰半岛东海岸的一个美丽的小城,那里每家都有自己的小公寓,公寓里有个小院,小院是孩子们踢足球的地方,那时,成为一名足球明星比成为一名电脑高手是更可行的想法,做一名电脑名星好象是很遥远的事情,因为个人不太可能拥有一台昂贵的计算机。很幸运,在大学时他就用上了系里的计算机,它叫GIER,是一台旧的丹麦计算机,有一个房间那么大,程序都写在磁带上面,他用它学习Algol 60程序设计。

而对Bjarne生活产生质的变化的事情是什么呢?

他认为在他的发展生涯中,最关键的一个项目是在剑桥大学攻读博士学位时用Simula67计算机做的模拟分布式系统。做这个项目除了使他成为一名顶尖的程序设计高手外,更使他养成了程序员应具有的沟通和交流能力,这为他后来的发展奠定了坚实的基础。

 

 

BC

BjarneC有缘。

Bjarne Stroustrup先生和CChina中国)有缘,对他来说中国是一个神秘、美丽而有趣的国度。

Bjarne两度亲密接触中国,第一次是2002年,曾在中国的几所大学讲学,而第二次是在浙江大学参加ICESS国际会议ICESS 2004, http://www.cs.zju.edu.cn/icess2004/Bjarne Stroustrup先生两年前在中国有过长时间的旅程,而在杭城的日子恰逢阴雨,这次到来对晴天的期望是强烈的,何况有杭州西湖美景。作为丹麦人,也就是卖火柴的小女孩诞生的地方,也就是安徒生童话诞生的国度,和中国有着很深的渊源,安徒生童话里恰巧里面有一篇《夜莺》,那里写到了中国,而Bjarne Stroustrup先生对于C(中国)的认识又是什么呢?

他的回答很微妙,他自然知道安徒生童话,他也很喜欢它们,《夜莺》中描绘的中国纯是虚构,与当时的中国可能有也可能没有任何关系,安徒生创造了那个“中国”来泛指多个国家及其统治者。而作为一个教育者,他对中国的教育老祖师孔老夫子也有自己独到的见解。

作为第二个C,自然就是C++了。勿庸置疑,C++对于IT的分量,和对于Bjarne个人的影响,都是巨大的。还有一个C,就是计算机,且看下面他如何描述自己与计算机的联系。

问: 您的生活是怎样和计算机联系在一起的?

Bjarne Stroustrup我也不晓得自己到底是怎样和计算机联系在一起的。当我上高中时,不知什么原因总觉得计算机科学是数学的某种实用形式。而事实不完全是这样,或者至少从软件的发展上看并不是如此,但正是这种误解使得我在还不知计算机为何物时选择了 “计算机科学数学” ,作为我学习的专业,并获得了我的硕士学位。我写完第一个程序后,就着了迷,曾没有回过头。正象大家所看到的,很幸运,我找到了一个使自己的才能可以很好地发挥的位子。

问:您怎样教育自己的孩子和学生们?

Bjarne Stroustrup多数情况下,我是通过实例来进行教学的。我认为多数人过高的估计了言语的影响力,而过低的估计了这种影响力是怎样达到的过程。我尽量通过把理论和实践相结合起来以更好地达到目的,这样可以比仅用理论或仅用实践示例来教育更能取得事半功倍的成效。我尽量举出实例,从这些活生生的实例中引导归纳出一般的规则和概念。

 

C++是怎样炼成的,是什么促成了C++语言?这象迷一样绕在我们的心头;那什么又是计算机语言呢?后者弄懂了,前者看起来也许就更简单了!且看大师的回答:

问: 您觉得计算机语言和我们人类的语言有什么不同呢?

Bjarne Stroustrup计算机语言要比人类语言简单的多,并且精确的多,那也是它应该具有的方式。我不赞成用自然语言去指令电脑的想法。一种程序语言是专家们的工具,并且和普通人相比,是对所有的专家来说用更加专业、定义的更加精确的符号和术语来表达的工具。

当然两者也有相同之处。那些用的较多的语言比那些使用率较小的语言拥有更多的俗语、表达方式、词汇,这一点无论是计算机语言还是自然语言都是一样的。语言还有一个倾向就是越来越易学,但却很难精通,象C++ 和英语。在两种语言当中,我们都希望能从最初的基本的应用到真正的掌握。另外一个相同之处就是语言的发展都要适应一个群体的需求,并且一个大的群体或者说社区本身就有重要意义,因为作为这个群体的一部分可以让你有更多的人来进行互动并且有更多的机会可以使用。所有鲜活的语言都是通过获得新的术语、俗语和表达方式来得到发展的。在C++中我们已经看到了关于模板技术的迅猛发展,始因是STL(注:STL指标准模板库,后面我们将采访STL之父 Stepanov先生,他确实有许多精彩的言论,和Bjarne Stroustrup先生相比,毫不逊色),也就是经常提到的泛型编程(generic programming和模板元程序(template metaprogramming。以后几年里,我们将会在新的ISO C++标准中看到,比1998年标准中对模板技术更强的支持和更广的应用。

 

那么,究竟是什么促成了C++语言呢?

他的研究生涯给了他很大灵感,他所在的AT&T贝尔实验室是一个光荣的群体,那里有一群非常出色的研究人员,那里有许多著名的IT人物,他们彼此间的影响十分深远。他曾经和C语言之父Dennis Ritchie亲密接触十多年,他们的办公室相距不远,C++语言受C的影响是巨大的。而对于C++来说,尤其值得我们推崇的是:作为一种学术性语言,他是从商业性语言的重围中杀出的。

1979Bjarne在剑桥完成学业后,到了贝尔实验室从事研究工作,20世纪80年代,AT&T曾拔款5000美元作为市场预算,创建一门语言的决心可能由此而始。在那里,开始研究几个与分布式计算有关的项目。可是工作进展得并不顺利,因为那时几乎所有程序设计工具都不适合完成此类工作。所以,他决定自己开发一个名为“带类的C”的工具,它既允许以类似于Simula的方式组织程序(这种方式现在被称为面向对象),同时也支持在硬件层次上进行系统软件开发。从1980年开始,“带类的C”被应用于贝尔实验室的很多应用领域,在应用过程中,他又学到了很多东西,而C++正是以“带类的C”为基础并结合了一些我们学到的新东西发展而来的。1983年夏天,Rick Mascitti给起了C++的名字,这个名字也象征着两种语言之间巨大的渊源。

 

 

生活中更有意义的事情

对于Bjarne来说,生活中更有意义的事情是什么呢?是学习和教育。这看起来象个沉重的话题,而在Bjarne身上却显得如此生动,作为教育家,Bjarne Stroustrup先生本身便是一个成才的典范,他出身于农场和“蓝领工人”家庭,他在专业领域孜孜耕耘,取得了不菲业绩。先是AT&T的研究者,现在又兼任教席,Bjarne从研究室又走进了大学,直接面对大学的新学生!

C++Bjarne生命中最重要的事情,而还有一些更有意义的事情。

他对大学教育情有独衷,他现在是A&M大学的教授,这种行动便是很好的说明,在这里,以一种在AT&T研究所中无法采用的方式将研究和教学结合起来。他认为教学是一种与工业生产不同的能影响世界并使其变得更加美好的方式,而且大学里的研究工作的成果与曾经进行的工业研究的并不相同 - 不是说它更好,仅仅只是不同而已。

他的一些教育观点也非常值得我们深思:

他说,不要只学习计算机和编程,要积累一种或多种领域的经验,要有其他专业知识,这样就能明白什么东西值得我们去编程实现。另外,学习多种语言也是他一再强调的,如果只学一种,容易导致想象力的僵化。他本人爱好广范,精通多种计算机语言。

 

 

 

问:您觉得怎样才是学编程的好方法?学习语言时一种好的工具是不是必需的?

Bjarne Stroustrup 这是过去一年左右里一直占据我大部分注意力的一个问题。我志愿教授电子工程/ 计算机工程专业大学一年级的学生编程,我认为我们目前教编程的传统方法不够严谨也不够广阔。我们社会的文明进步是建立在软件上的,因而必须培养更好的软件专家。我认为已经到了我开始培养新手程序员的时候了,在我此之前我都是把精力放在专家上。我基本的设想是让学生成为专家,使他们最终能够编出可靠并且别人可以信赖的软件,这就意味着在培养新手时要求更高,要将重点放在对程序正确性和处理错误的训练上。既然目标是为了制造现实世界中可用的软件,我也非常重视标准库的应用和设计。对于C++标准库工具的教学,例如向量(vector)和字符(string)从第一周就该开始应用,在第一个月之内类(class)就应该介绍,在第二个月之内介绍图形(graphics)和继承性(inheritance)。这种方法和传统的方法不同,那些教学方法往往花费数周的时间来区分那些令人迷惑的C++基本类型,并且浪费宝贵的时间来处理诸如声明和循环上的一些迷人耳目的语法细节。我称我的方法为“深度优先法”,因为我们首先教我们的学生足够的知识去做一些有用的工作,然后才在这有限的基础上拓宽他们的理解能力和对工具的使用能力。

我所有的教学都是在实例的基础上进行的。我通过典型的例子来使学生理解,用亲身的体会来解释一些规则。自然地,我要求学生写大量代码如果你不读也不写大量代码的话你就学不会编程。第一阶段如下,学生必须经过亲身写代码,体会解题过程中出现的实际问题;第二个阶段必须好好体会亲身所犯的错误,并且学会克服他们。这其中,调试、错误处理,还有学会将大问题分解成小问题,从最小的组件来编程是非常重要的。

 

:数学和计算机科学有什么关系吗?

Bjarne Stroustrup 两者并没有很强的直接联系,但是有一部分编程的实质包含在里面-- -象学数学一样,编程有时也需要很严密的思维。自从古希腊以来,数学就被用来训练人们的逻辑思维,并且我觉得如果不用数学的话很难想象怎样才能编出好程序来。当然也有一些计算机领域,用到高深的数学知识。然而,这些领域通常是非常专业的。数学,特别是数学思维是计算机的一个支柱。经验主义是另一支柱,通过观察和测量来帮助理解实际的发展,用以调整我们的系统和行为。两方面我们都需要。计算机科学不是仅仅用来证明定理的,也不是仅仅用来收集数据的。为了有效地实践计算机科学和发展高质量软件,更同时需要数学和经验的训练。

问: 您以前在欧洲学习而现在在美国工作,您觉得欧美有什么学术传统区别?怎样才算是一种好的大学教育呢?尤其对计算机科学来说。现在的大学有部分学生中途退学,您怎样看待这一现象呢?

Bjarne Stroustrup这很难回答。欧洲和美国都幅员辽阔,而且有很多不同的学术传统。真的不好总结,并且在两地都有一些非常好的大学科系,这不是很容易区别和下结论的。

很少有学生离开学校去开公司,较多的是离开学校去从事一些有较高收入的工作,但大多数人还是完成了学业。我印象中那些放弃了计算机科学学习转而投入业界工作的是会为此感到后悔的。从长期眼光来看学位对一个好工作来说是重要的,特别是学生在他们最后一年或最后几年的学习。当然也确实有些相反的例子,但那些人通常永远不会再从事真正的技术工作,而转为商业管理人员了,如果那是他们想做的,那一个学位并不是必须的。我一直认为:一个学生如果还未获得学位,最好不要离开学校。

问:我们经常批评我们现在的C++教育不够现代、不够科学,您是通过“深度优先法”来教授学生的,您是否觉得在一个学生学习早期有些难吗?我们该如何做呢?

Bjarne Stroustrup这是必然的。传统的教授编程的方法是不行的,学完这些课程的学生写不出很好的代码。说得更激进一点,他们甚至不知道什么是好的代码!我的方法可以避免这种情况发生。我已在300 名学生身上实验成功。对于程序员来说这是非常关键的——包括新程序员——了解基本概念和基本技能。但仅仅了解程序设计语言的基本构造是不够的。另一方面,如果没有一种编程语言我们就不可能教授编程的技能和规则,因此,对一种语言工具充分掌握,做尽可能多的练习是必需的。

很显然,这种教育问题不仅仅局限于C++语言。我的方法可以应用于任何其他语言。

 

面向金钱、面向未来和面向对象

面向对象是个有趣的问题,C++正是和面向对象有着非常联系的语言,作为一种非商业化语言,他已经影响了世界范围数十亿美元的设计决策。而还有许多语言具有这种特点,因而,关于各种语言的争论喋喋不休地进行了几十年。

当有人问Bjarne Stroustrup先生:有人说Java是纯粹面向对象的,而C#更胜一筹,而还有很多人说它们纯粹是面向金钱的。以您之见呢?

Bjarne 的回答非常风趣:我喜欢“面向金钱”这个词 :-) 还有Andrew Koenig的说法"面向大话"我也喜欢。C++可不面向这两个东东。对这点我还想指出,我认为纯粹性并非什么优点。C++的优点恰恰在于其支持多种有效的编程风格(多种思维模型吧,如果你一定要这么说)及其组合。最优雅最有效也最容易维护的解决方案常常涉及到一种以上的风格(编程模型)。如果一定要用吸引人的字眼,C++是一种多思维模型的语言。在软件开发的庞大领域,需求千变万化,起码需要一种支持多种编程的设计风格的通用语言,而且很可能需要一种以上呢。再说,世界之大,总容得下好几种编程语言吧?那种认为一种语言对所有应用和每个程序员都是最好的看法,根本就是荒谬的。

他上面的回答很好地告诉了我们面向对象和面向金钱的关系,也给我们的争论划上了圆满的句号。

问:您对面向对象是怎样理解的?它是不是一种好的可接受的编程思考方式?有没有学习OO必须的有用的工具?

Bjarne StroustrupOO 技术在现在软件发展的扮演了非常重要的角色,但并不是唯一的方法。象泛型程序设计(generic programming),用C++ 模板是另一种方法,这些方法必须通过综合应用来,才能创造出:一流的、最可读的、最易于维护的、最高效的程序。但没有任何一种方法是适合所有要求的。

我主要用C++来编程。我觉得C++是一种学习和实践OO思想很好的编程语言。

 

敢问路在何方

问: 您能对IT的将来做一下预测吗?将来我们最有可能用什么语言

Bjarne Stroustrup一个聪慧的幽默大师曾经说过:预测是困难的,特别是对将来的预测。但是我认为未来十年之内我们用的东西在今天的实验室里是能够看到的。另外我们将用的最主要的语言也是今天最主要的。我们不可能因为一些新东西和一些更好的东西的出现就重组整个工业领域,因此在五到十年之内,我们还是用C, C++, COBOL, Fortran, Java, Perl, Python,也许还有C#,和其它许多种语言。没有一种语言能适合所有用途,并且好的程序员都懂并且都能用好几种语言。懂好多种语言和多种程序设计技术会使我们可以更好地编程。

对于IT我不想说太多,很显然:我们会继续依赖IT并且它会延伸到越来越多的领域。当然,肯定会有失败,通常是因为过度的滥用引起的——但是在十年以后我们受IT的影响肯定要比今天大得多。

 

 

 

人物印象

 

很幸运,通过电邮采访的同时终于有机会和大师面对面。想象中的大师和面对面见到的有太多的意想不到,用一个词来形容是“谦逊”。

Bjarne到杭州下了飞机,便扑向美丽的西湖,同去的是他的好友STL之父Alex Stepanov先生。在未去杭州之前,Bjarne Stroustrup先生通过电邮告诉我杭州城的美;去了之后,少有的好天气让我们碰上了,爽;夜里在旅馆见到了久违的大师,一夜之间见到两位大师,更爽!

我对Bjarne Stroustrup先生有着特殊的感情,觉得他象位慈父,而他正和我的父亲同样的年纪。大师,慈父!接触越多,对Bjarne Stroustrup先生的感触越深。到了杭城,见到大师其人,这种感觉越来越浓厚,他又象海,既有热情,又能包容。

采访大部是通过Email进行的,采访的过程中对我的问题孜孜以求,给我的回答细微备至,Email的好处在此发挥到了极致,大洋这边的我沐着阳光,那边的他在挑灯夜书。

唯有谢谢众多C++程友和非C++朋友对我的支持,唯有大师再来杭城时,到最好的茶馆将上好的龙井泡上,亲手送到大师的手中!

20041219

posted @ 2007-04-06 16:35 学习才能进步 阅读(115) | 评论 (0)编辑 收藏
1  new自动计算需要分配的空间,而malloc需要手工计算字节数
2  new是类型安全的,而malloc不是,比如:
int* p = new float[2]; // 编译时指出错误
int* p = malloc(2*sizeof(float)); // 编译时无法指出错误
new operator 由两步构成,分别是 operator new 和 construct
3  operator new对应于malloc,但operator new可以重载,可以自定义内存分配策略,甚至不做内存分配,甚至分配到非内存设备上。而malloc无能为力
4  new将调用constructor,而malloc不能;delete将调用destructor,而free不能。
5  malloc/free要库文件支持,new/delete则不要。
posted @ 2007-04-06 15:28 学习才能进步 阅读(656) | 评论 (0)编辑 收藏

 如果const关键字不涉及到指针很好理解,下面是涉及到指针的情况:    
  int   b   =   500;  
  const   int*   a   =   &b;                             [1]  
  int   const   *a   =   &b;                             [2]  
  int*   const   a   =   &b;                             [3]  
  const   int*   const   a   =   &b;                  [4]  
   
  如果const位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量。因此,[1]和[2]的情况相同,都是指针所指向的内容为常量(const放在变量声明符的位置无关),这种情况下不允许对内容进行更改操作,如不能*a   =   3   ;[3]为指针本身是常量,而指针所指向的内容不是常量,这种情况下不能对指针本身进行更改操作,如a++是错误的;[4]为指针本身和指向的内容均为常量。  
  另外const   的一些强大的功能在于它在函数声明中的应用。在一个函数声明中,const   可以修饰函数的返回值,或某个参数;对于成员函数,还可以修饰是整个函数。  
  有如下几种情况:  
  A&   operator=(const   A&   a);  
  void   fun0(const   A*   a   );    
  void   fun1(   )   const;         //   fun1(   )   为类成员函数  
  const   A   fun2(   );  
  ----------------------------------------------------------------------------------  
  const的初始化  
   
  先看一下const变量初始化的情况  
  1)   非指针const常量初始化的情况:  
  A   b;  
  const   A   a   =   b;  
   
  2)   指针(引用)const常量初始化的情况:  
  A*   d   =   new   A();  
  const   A*   c   =   d;  
  或者:const   A*   c   =   new   A();  
  引用:  
  A   f;  
  const   A&   e   =   f;       //   这样作e只能访问声明为const的函数,而不能访问一般的成员函数;  
  ----------------------------------------------------------------------------------  
   
  作为参数和返回值的const修饰符  
   
  其实,不论是参数还是返回值,参数传入时候和函数返回的时候,初始化const变量  
  1   修饰参数的const,如   void   fun0(const   A*   a   );   void   fun1(const   A&   a);  
  调用函数的时候,用相应的变量初始化const常量,则在函数体中,按照const所修饰的部分进行常量化,如形参为const   A*   a,则不能对传递进来的指针的内容进行改变,保护了原指针所指向的内容;如形参为const   A&   a,则不能对传递进来的引用对象进行改变,保护了原对象的属性。  
  [注意]:参数const通常用于参数为指针或引用的情况;  
  2   修饰返回值的const,如const   A   fun2(   );   const   A*   fun3(   );  
  这样声明了返回值后,const按照"修饰原则"进行修饰,起到相应的保护作用。  
  const   Rational   operator*(const   Rational&   lhs,   const   Rational&   rhs)  
  {  
  return   Rational(lhs.numerator()   *   rhs.numerator(),  
  lhs.denominator()   *   rhs.denominator());  
  }  
   
  返回值用const修饰可以防止允许这样的操作发生:  
  Rational   a,b;  
  Radional   c;  
  (a*b)   =   c;  
   
  一般用const修饰返回值为对象本身(非引用和指针)的情况多用于二目操作符重载函数并产生新对象的时候。  
  [总结]   一般情况下,函数的返回值为某个对象时,如果将其声明为const时,多用于操作符的重载。通常,不建议用const修饰函数的返回值类型为某个对象或对某个对象引用的情况。  
  原因如下:  
  如果返回值为某个对象为const(const   A   test   =   A   实例)或某个对象的引用为const(const   A&   test   =   A实例)   ,则返回值具有const属性,则返回实例只能访问类A中的公有(保护)数据成员和const成员函数,并且不允许对其进行赋值操作,这在一般情况下很少用到。    
  ----------------------------------------------------------------------------------  
  类成员函数中const的使用  
   
  一般放在函数体后,形如:void   fun()   const;  
  如果一个成员函数的不会修改数据成员,那么最好将其声明为const,因为const成员函数中不允许对数据成员进行修改,如果修改,编译器将报错,这大大提高了程序的健壮性。    
   
  ----------------------------------------------------------------------------------  
  使用const的一些建议  
   
  1   要大胆的使用const,这将给你带来无尽的益处,但前提是你必须搞清楚原委;  
  2   要避免最一般的赋值操作错误,如将const变量赋值,具体可见思考题;  
  3   在参数中使用const应该使用引用或指针,而不是一般的对象实例,原因同上;  
  4   const在成员函数中的三种用法(参数、返回值、函数)要很好的使用;  
  5   不要轻易的将函数的返回值类型定为const;  
  6   除了重载操作符外一般不要将返回值类型定为对某个对象的const引用;  

const * 与 * const

const *表示指向const对象的指针,可以指向一个const的对象,但是并不是指只能指向一个const对象,指向const对象的指针同样可以指向一个非cons类型的对象。但是const的对象只能由const*类型的指针指向,而不能由普通指针指向。const*类型的指针在使用过程中可以其改变,即可以指向其他对象。
const*类型的指针的真正含义是:如果一个指针是const*类型的指针表示该指针指向的对象不能通过该指针进行修改(对象本身可能通过别的方式进行修改)。 
*const expression表示指针(expression)本身是const,即*const类型的指针初始化后不能改变,不能指向别的对象。 
char * point_char = new char('e');
const char char_char = 'f';
const char * const_star_char;                       // 可以不用初始化
char *const  star_const_char = point_char;    // 必须初始化
const_star_char = &char_char;                     // OK
star_const_char = &char_char;                     // 错误,*const 不可改变
const_star_char = star_const_char;              // OK
star_const_char = const_star_char ;              // 错误 ,*const 不可改变
const char* const foo(char const * const str) const

第一个const表示返回类型为const,也就是不能把此函数的返回值当作左值来使用。

第二个const表示指针的不可变性,但在这是可以省略,因为返类型已经是const。

第三个cosnt表示str的常量性,也就其内容是不能改变,可以写在其前面的char的前面。

第四个cosnt表示str的指针的常量性,也就是此指针不能指向别的地址。

第五个cosnt表示此函数的常量性(前提是类的成员函数),不能修改所在类的数据成员。
posted @ 2007-04-06 13:36 学习才能进步 阅读(159) | 评论 (1)编辑 收藏
仅列出标题  下一页