代码大全_cc31-33


第三十一章 个人性格 501 第三十一章第三十一章第三十一章第三十一章 个人性格个人性格个人性格个人性格 目录目录目录目录 31.1 个人性格是否和本书的主题无关 31.2 聪明和谦虚 31.3 好奇心 31.4 诚实 31.5 交流和合作 31.6 创造力和纪律 31.7 懒惰 31.8 不是你想象中那样起作用的性格 31.9 习惯 31.10 小结 相关章节相关章节相关章节相关章节 软件技术主题:见第 32 章 控制结构和复杂性:见第 17.7 节 在软件开发中人们很少注意个人性格问题。自从 1965 年 Edsger Dijkstra 的有里程碑意 义的文章“程序开发是一种人类活动”发表以来,程序员性格被认为是合理的和有成效的研究 领域,虽然有些题目如“大桥建筑者的心理”和“对律师行为的研究实验”看起来可能是荒唐 的,而在计算机领域,“计算机编程中的心理”和“对程序员行为的研究实验”等题目则是常见 的。 每个领域的工程人员都知道工具和他们所用材料的局限性。如果你是一位电机工程师,你 就应明白各种材料的导电性和使用电压表的各种方法。如果你是一位建筑师,你就应明白木材、 混凝土、钢材的性能。而如果你是一位软件工程师,你的基本建筑材料是人的聪明才智,并且 你的主要工具是你自己。建筑师是将建筑物结构进行详细的设计,然后将设计蓝图交给其它人 去建造,而你则是一旦当你从细节上对软件作出设计后,软件生成过程也就结束了。 编程的整个工作就如建造空中楼阁一样——它并不是纯粹的人工活动。于是,当软件工程师 研究工具和材料的必需性时,他们发现自己正在研究人的智力、性格,不像木材、混凝土和钢 材等可见的东西。 31.131.131.131.1 个人性格是否和本书的主题无关个人性格是否和本书的主题无关个人性格是否和本书的主题无关个人性格是否和本书的主题无关 编程工作极强的内部特点使得个人特点异常重要,你想想一天全神贯注地工作八小时有多 么困难,你可能有过由于精力过份集中而今天无精打彩的体验。或由于上个月过份投入而本月 没有一点精神,你也可能在某一天从上午 8 点工作到下午 2 点,以致于精神快要坍塌了。有时 你从下午 2 点拼命于到 5 点,然后花费一周的时间修改你在其间所写的东西。 第三十一章 个人性格 502 人们难以对编程工作进行检查,因为没有人知道你真正干些什么,我们经常有过这样的体 验,我们花费 8O%的时间进行我们所感兴趣的 20%的工作,同时花费 2O%的时间生成其余 80 %的程序。 你的老板并不能强迫你成为一个好的程序员,甚至过了很长一段时间你的老板也无法判断 你是否是一个称职的程序员,如果你想成为一个高手,你得全靠你自己下功夫。它和你个人性 格有关。 一旦你自己决定成为一个高级程序员,你发展的潜力是很大的,各种研究发现,创建一个 程序所需的时间比可达到 10:1,同时也发现调试一个程序时间,程序实现长度、速度、错误 率和所发现错误数对不同的程序员其差别可达 10:1。 你无法改变自己的聪明程度,但是你可在一定程度上改变自己的性格,已发现在程序员成 为高级程序员的过程,性格是更有决定意义的因素。 31.231.231.231.2 聪明和谦虚聪明和谦虚聪明和谦虚聪明和谦虚 聪明看起来似乎不是个人性格的一个贡献。它也的确不是。恰巧的是,好的智力是和成为 一个好的程序员有着并不严密关系的因素。 为什么?难道这并不要求你有一个好的智力吗? 不,你不需这样,没有人真正同计算机一样迅速敏捷。完全理解一个一般的程序需要你有 吸收细节的很强的能力,并能同时理解所有细节,你很好地利用你的聪明要比你有多聪明更为 重要。 在 1972 年,Edsger Dijkstra 发表一篇论文,名字叫作“谦虚的程序员”。他在此文中主 张所有的程序员都应尽力弥补他们很有限制的智力。那些最精通编程序的人往往是那些认为自 己的头脑是多么有限的人,他们是谦虚的。而那些最为糟糕的程序员往往是那些拒绝承认自己 的能力不适应工作任务的程序员。他们的自我妨碍自己成为优秀程序员,你学到越多的东西来 弥补你的大脑,你就越能成为一个好的程序员,你越谦虚,你取得的进步也就越快。 许多良好的编程风格的目的是减少你大脑的负担,以下是一些例子: “分解”一个系统的目的是为了使其更为简单易懂。人们往往易于理解几条简单的信 息而不是一条复杂的信息。所有软件设计方法的目的是将复杂的问题分解为简单的几 部分,不论你是否使用结构化、自顶向下或是面向对象的设计,以上目标都相同。 进行评审、检查和测试是弥补人的错误的一种方法,评审方法部份源于“无错编程”, 如果你没有任何错误,你就用不看评审你的软件,但是当你知道自己的能力是有限时, 你就应和别人讨论以提高你的软件质量。 将子程序编短一些有助于减少你的工作量。你根据问题而不是计算机科学术语编写程 序并使用尽可能高级的抽象思维,有助于减少你的工作量。 使用各种交谈方式可将你从编程的死胡同中解放出来。 你也许认为靠聪明能更好地开发人的智力活动,所以你无需这些帮助。你也可能认为使用 智力帮助的程序员是走弯路。实际上,研究表明那些使用各种方式弥补其错误的谦虚的程序员 们所编写的程序既易为自己也易为别人所理解,并且其程序中所含错误也少。实际的弯路是出 现错误和影响进度的路。 第三十一章 个人性格 503 31.31.31.31.3 3 3 3 好奇心好奇心好奇心好奇心 一旦你认为自己理解程序的能力是有限的,而且你意识到,进行有效的编程是补偿自己能 力的方法时,你就开始了你生涯中漫长的探索过程。 在变成高级程序员的过程中,对技术的好奇心是很重要的。有关的技术信息变化迅速。许 多 PC 程序员没有在什么机器上编过程,而许多程序员还没有用过电脑的穿孔卡片。技 术 环境的 特定特征每隔 5 到 10 年就发生变化。如果你跟不上这种变化,你将面临落伍的威胁。 程序员往往很忙碌,以致于他们没有时间对更好地工作或对工作发生兴趣。如果你真是这 样,你也不必在意大多,因为许多人都同你一样,以下是一些培养你的好奇心的方法,你真应 该好好学一学它。 在开发过程中建立自我意识在开发过程中建立自我意识在开发过程中建立自我意识在开发过程中建立自我意识。你对开发过程越了解,不管你是通过对开发过程的阅读或自 己的观察得来的,你就越能了解各种修改,并使你所在开发组向一个更好的方向前进。如果分 配你的工作任务很少而不能提高你的技能,你也应对此满足。如果正在开发有良好市场前景的 软件,你所学的一半知识将会在今后三年内过时,如果你不再学习新知识,你将会落伍。 在1988 到 200O 年中,美国平均工作人数可增加 11%到 19%,计算机系统分析员可增长 53%。程序员可增长 48%,计算机操作员可增长 29%——在现有的 1,237,000 份工作的基础 上再增加 556,000 份新工作。如果你在工作中学不到什么,你可试着找一份新工作。 实验实验实验实验。了解编程的一个有效途径是对编程和开发过程进行实验,如果你对所用语言的工作 过程不甚了解,你可编写一个短程序以检查此特征并看其是如何工作的,你可在调试器中观看 程序的执行,你用一个短程序而不是一个不甚了解的大程序来测试一个概念是很好的。 如果短程序的运算表明程序运行结果并不是你所期望的,这时你应怎么办?这正是你所需 要的,最好用一个短程序在有效编程的一个关键方法上迅速制造错误,每 次你可从中有所收益, 制造错误并不是罪过,没有从中学到什么才是罪过。 阅读阅读阅读阅读解决问题的有关方法解决问题的有关方法解决问题的有关方法解决问题的有关方法。解决问题是软件开发中的一个重要活动,Herbert Simon 曾报 道过人工解决问题的一系列例子。他们发现人们自己通常不能发现解决问题的方法,即使这种 方法很容易学到。这意味着即使你想自己创造车轮,你也不能指望成功,你可能设计出方车轮。 在你行动之前进行分析和计划在你行动之前进行分析和计划在你行动之前进行分析和计划在你行动之前进行分析和计划。你将会发现在分析和行动之前存在着矛盾,有时你不得不 放弃的数据和行动,对大多数程序员来说,问题并不在于过分分析和过分使用。 学习成功项目的开发经验学习成功项目的开发经验学习成功项目的开发经验学习成功项目的开发经验。学习编程的一种非常好的方法是向一些优秀程序员学习。Jon Bentley 认为你应静心坐下来,准备一杯白兰地,一枝好雪茄烟,然后如同读小说一样阅读程 序。实际上可能并不是这样,许多人往往不愿牺牲其休息时间来阅读——500 页的源程序,但是 许多人往往乐意研究一个高级程序的设计,并有选择地研究一些具体细节。 软件工程领域很少利用过去成功或失败的例子。如果你对建筑学有所兴趣,你可能会研究 Louis Sullivan,Frank Lloyd Wright 和 I.M.Pei 的设计图,你也可能会参观他们的建筑物, 如果你对结构工程有兴趣,你可以研究 Broolyn 大桥,Tacoma Narrows 大桥以及其它混凝土、 钢铁和木材建筑,你应研究你所在领域中成功或失败的例子。 Thomas Kuhn 指出,任何成熟的科学,实际上是通过解决问题而发展起来的,而这些问题 通常被看作本领域良好工作的例子,并且可用作将来进行工作的例子。软件工程是刚入成熟阶 第三十一章 个人性格 504 段的一门科学,在 1990 年,计算机科学和技术委员会曾指出,在软件工程领域很少有对成功和 失败的例子进行研究的文件,在 1992 年 3 月的“ACM 通信”中有一篇文章主张对别人编程中出 现的问题进行研究,总之,学习别人的编程是有重要意义的。 其中一个最受欢迎的栏目是“编程拾萃”,它专门研究编程过程中出现的问题,这对于我们 是有启发的。 你可能有或没有一本研究编程的书,但是你可阅读高级程序员所编写的代码,阅读你所尊 敬的程序员的代码,或阅读你并不喜欢的程序员的代码,再将他们的代码和你自己的代码比较。 它们之间有何异同?为什么会有差异?哪一个更好?为什么? 除了阅读他人的代码之外,你也应让其它高水平程序员评价你的代码质量,找一些较高水 平的程序员评论你的代码,从他们评论中,你可剔除那些带个人色彩的东西而着重于那些重要 的东西。这样可提高你的编程质量。 阅读手册阅读手册阅读手册阅读手册。手册恐惧症在程序员中很流行。一般来说,手册的编写和组织都不好,但是程 序员对手册的恐惧也和他们对书本的过分恐惧有很大关系。手册含有一些重要的东西。所以花 费时间阅读手册是值得的,忽视手册中的信息正如忽视一些常见的首字母简略词。 现代语言产品一般都带有大量程序库,这时,你花费时间查阅参考手册是值得的,通常提 供语言产品的公司,已经编写了许多你可以调用的子程序。如果是这样,你应弄懂有关手册, 每隔一段时间阅读一下手册。 阅读有关书籍和期刊阅读有关书籍和期刊阅读有关书籍和期刊阅读有关书籍和期刊。你应为自己阅读本书感到幸运。你 已经学到了软件工程的许多知识, 因为一本书每年都要被许多程序员所阅读,读一些东西可能使你的专业知识向前迈进一步,如 果你每二个月阅读一本好的计算机书籍,你的知识将会大大提高并能在同行中脱颖而出。 31.431.431.431.4 诚诚诚诚 实实实实 编程生涯成熟的部分标志是不折不挠地坚持诚实,诚实通常表现在以下几个方面: 不假装你是一个编程能手 乐于承认自己的错误 力图理解编译器警告信息而不是对其置之不理 对你的程序有一个清晰的了解,而不是进行编译看其是否有错 提供实际状态报告 提供实际方案评估,在你的上司面前坚持自己的意见 前二个方面——承认你不知道一些事情或承认你犯了一个错误是你谦虚的反映。如 果 你 不懂 装懂你又怎么能指望学到新东西呢?你最好是假装自己知之甚少,听别人的解释,向他们学习 新的东西,并评估他们是否真正了解其正在谈论的东西。 你应对自己的能力作某种程度的估计,如果你对自己的评价很完美,这可是一个不妙的信 号。 拒绝承认错误是一个令人讨厌的习惯,如果 sally 拒绝承认错误,她看起来相信自己没有 错,可能会使其它人相信她确实是无辜的,但是事实证明 sally 出错误了,这样,每个人都知 道她犯了错误。错误正如潮流一样是一种复杂的活动,如果她在过去没有发生过错误,谁也不 第三十一章 个人性格 505 会将错误归咎于她。 如果她拒绝承认错误,到头来她只能自食其果。其它人都知道他们在同一个不诚实的人工 作。这比仅犯一个错误更令人反感。如果你犯了一个错误,你应迅速主动地承认错误。 对编译器错误信息不懂装懂是另外一个常见错误。如果你不理解某一编译警告信息或你认 为时间太紧迫来不及检查,你想想这是不是真正浪费时间?编译器将问题明白无误地向你展示 出来,而你却不试图解决问题,我碰到过不少人在调试过程中请求帮助的事,我问他们是否有 一个完好的编译器,他 们回答是。于是开始解释问题的症状,我说:“这看起来像是未对指针进 行初始比。但是编译器应对此给出了警告信息。”他 们 就 说:“哦,编 译器确实给出了警告信息, 我们以为它是指其它事情。”你自己所出的错误难以蒙蔽别人,也更难以愚弄计算机,所以你用 不着浪费时间这样作。 另外一种疏忽是当你并不完全了解程序时,你“编译它看是否能运行”。在这种条件下,其 实并不意味着程序能运行,因为连你自己都不清楚程序的有关情况。请记住,测试仅能发现错 误的存在,而不能保证一定不存在某种错误。如果你不理解程序,你就不能进行深入的测试, 你如果觉得应编译一下程序以便了解程序的运算情况的话,这可是一个不妙的信号,这可能意 味着你不清楚在干些什么。在将你的程序编译之前你应对其有一个深刻的理解。 状态报告也同样是一个令人反感的领域。如果程序员在最后 50%的项目时说,程序中 90 %是完整可靠的,他们将声名狼藉。问题在于你对自己的进度缺乏了解,你应对你的工作加强 了解。但是,你为了迎奉上司而不愿说出真实情况的话,可就不同了。一般来说上司都愿意听 到对项目状态的真实报告,即使不是他们所希望听到的,如果你的观察和见解是中肯的,你应 客观地将其说出来,上司需要有准确的信息以便协调各种开发活动,而充分的合作是必需的。 和不准确的状态报告有关的一个问题是不正确的估计。典型的情况是这样:上司问 Bert 要花多少时间才能开发出一个新的数据库产品。Bert 和一些程序员交谈了一下,讨论了一些问 题,最后认为需 8 个程序员和 6 个月的时间,但是他的上司说:“这并不是我们所需要的,你能 不能使用较少的程序员在短时间内完成工作?”Bert 考虑了一段时间,并认为可以通过削减培 训时间和假期以及让每个人的工作时间稍微延长一点来达到上司的要求。他于是作出了需 6 个 程序员和 4 个月时间的估计,他的上司说:“这就行了。这是一个相对较为低优先级的项目。你 应及时完成它,因为预算不允许你超时。”Bert 所犯错误在于,他没有认识到评估是不可商量 的,他可以将估计作得更为准确,但是他和老板的商量结果并不能改变开发一个项目所需的时 间。 IBM 公司的 Bill Weimer 说;“我们发现技术人员一般都能准确地估计项目。问题在于他 们能否坚持自己的决定;他们需要学会坚持自己的意见。”Bert 许诺在 4 个月里交付产品而实 际上 6 个月才交付产品,肯定会使他的老板不高兴的。时间一长,他可能会因妥协而失去信任 的。否则,他会因坚持自己的估计而得到尊敬的。 如果上司施加压力要改变你的估计,你应认识到决定要怎样作是上司职权范围内的事。你 可以说:“看,这是项目的开销,我无法说此开支对本公司是否值得——这是你的工作。我不能 和你‘商量”项目所花的时间,这正如我们不能协商确定一里究竟有多少英尺一样——这是不 可变更的。你不能商定自然界的规律,我们只能商定本项目中影响进度的各方面,然后重新评 估。我们能减少一些特征,降低性能,分阶段开发项目。或者是使用更少的人但时间延长一点, 或者是使用稍多的人,而相应地减少一些时间。” 第三十一章 个人性格 506 我曾在一次软件开发管理讨论会上听到一个奇怪的说法。主讲者是一本销售很好的软件工 程管理书籍的作者。一听众问:“你的上司让你评估某一项目,你知道当你得出准确的评估时你 的上司可能认为代价太高而放弃项目开发。这时你认为应怎么办?”主讲者回答说,你说服你 的上司作出开发项目的决定时,他们就对整个情况了如指掌了。 这是一个错误的回答。你的上司是负责整个公司的运转的。如果开发某一软件需 10O000 美元而你的估计是 200000 美元,你 的公司就不会开发软件。这是要由上司作出决定的。上面这 位主讲者对项目的开支说假话,告诉上司将比实际的要少,他这是在损害上司的权威,如果你 认为项目是有前途的,它能为公司带来新的重大突破,或能提供有价值的培训,你应将其说出 来。你的上司也会考虑这些因素的。你哄骗上司作出错误的决定将会使公司蒙受损失。如果你 失去了你的工作,你将会明白你最终得到了什么。 31.5 31.5 31.5 31.5 交流和合作交流和合作交流和合作交流和合作 真正优秀的程序员应学会怎样和别人工作和娱乐,编写可读代码是对程序员作为组中一员 的要求之一。 计算机也就同其它人一样能读懂你的代码,但是它要比其它人更能阅读质量差的代码。作 为可读性原则,你应将修改你的代码的人时刻记在心上。开发程序首先应同程序员交流,其次 则是和计算机交流。 绝大多数高水平程序员喜欢使自己程序的可读性强,并抽出充足的时间这样作。虽然只有 一些人能坚持到底,而且其中一些人还是高水平的代码编写者,对开发中程序员级别的了解, 有助于解释什么地方适合于此原则: 级别级别级别级别 1111:初学者:初学者:初学者:初学者 初学者是能使用一种语言基本能力的程序员,这样的人能够使用子程序、循环、条件语句 和其它许多语言特征。 级别级别级别级别 2222:中间者:中间者:中间者:中间者 中间级程序员有使用多种语言的能力,并且至少非常熟悉某一种语言。 级别级别级别级别 3333:专家:专家:专家:专家 编程专家对其语言或环境或对这二者有着很深的造诣,这种级别的程序员对公司有价值的, 而且有些程序员往往就停留在这个水平上。 级别级别级别级别 4444:大师:大师:大师:大师 大师有着专家那样的专业知识,并 能 意 识到编程只是15%和计算机交流,其余 85%是和人 打交道。一般程序员只有 30%的时间甚至更少。大师所编写的代码与其说是给计算机看倒不如 说是给人看的。真正的大师级程序员所编写的代码是十分清晰易懂的,而且他们注意建立有关 文档。他们也不想浪费其精力去重建本来用一句注释就能说清楚的代码段的逻辑结构。 一位不强调可读性的高水平代码者可能停留在级别 3 的水平上,但是问题还不止此。依作 者本人的经验,人们编写不可读代码的主要原因在于他们所编代码质量较差。他们并不是自言 自语地说:“我所编代码不好,所以我要使其难以读懂”,而是他们并不能完整地理解自己的代 码以致于不能使其是可读的,这就使他们只能停留在1或 2 级的水平上。我所见的最差的代码 是由一个任何人看了她的程序后都会望而生畏的人所编写的。最终,她的上司威胁说如她再不 第三十一章 个人性格 507 改正就要解雇她。她的代码是不作注释的,并且其程序中充满了如 x,xx,xxx,xx1和xx2 这 样的全局变量。她的代码给了她大量的机会显示她的改错能力。 你不必为自己是初学者或中间者而内疚,你同样不必为自己是专家而不是大师自愧,在你 知道怎样提高自己的水平后,你倒是应为自己停留在初学者或专家的水平上有多长时间而内疚。 31.631.631.631.6 创造力和纪律创造力和纪律创造力和纪律创造力和纪律 当我走出校门时,我自认为是世界上最好的程序员。我会编辑令人容忍的井字游戏程序, 也能用 5种不同的计算机语言编写一个 1000 行的 WORKED 程序。然后我进了 Real World 公 司。我在 Real World 公司的第一个任务是阅读和理解一个 200000 行的 Fortran 程序,然后我 使其运行速度提高了 2 倍。任何真正的程序员将会告诉你所有结构化编码将无助于你解决问题。 “Real Programmers Don’t write Pascal” 向一位刚走出校门的计算机科学毕业生解释为何需要约定和工程纪律是困难的。当我还是 一个大学生的时候,我所编写的最大的代码是 5O0 行的可执行代码,作为一个专业程序员,我 也已编写了许多小于 500 行的实用工具,但是一般项目的长度为 5000 到 25000 行,并且我参加 过超过 50 万行的项目的开发工作,这种类型的工作不是需要较高的技巧,也不需要使用新的技 巧。虽然一些有创造性的程序员将各种标准和约定视为对其创造力的阻碍,但是,对大项目来 说,如果没有标准和约定,项目的实现是不可能的,而此时要发挥创造性也是不可能的。不要 在一些无关紧要的领域建立约定,这样你就可在你认为值得的地方集中发挥你的创造力。 McGarry 和 Pajerski 在对美国宇航局的软件工程实验室过去 15 年的工作回顾中说,强调 纪律的方法和工具是非常有效的。许多有很高创造力的人都能很好地遵守纪律,高水平的建筑 师在材料的物理性能、时间和代价的限定范围内进行工作,艺术家同样如此,许多看过 Lenoard 的设计的人,都为他在细节上对约定的遵守产生由衷的敬重。当 Michelangelo 设计天花板时, 使用了各种均衡的几何形式如三角形、圆周和正方形,他按一定层次将以上三种图形安排在三 个区域,如果没有自我约束和结构,这 300 个人物的排列将是混乱的而不是有机地结合在一起 的艺术杰作。 一个杰出的程序员需要遵守许多规则。如果你在开始编码之前不分析需求就进行设计,你 将在编码过程中学不到关于项目的许多东西,你工作的结果看起来更像一个三岁小孩的手指画, 而不是一件艺术作品。 31.731.731.731.7 懒惰懒惰懒惰懒惰 懒惰表面形式有以下几种:拖延自己讨厌的工作 迅速地将自己讨厌的任务作完以摆脱任务 编写一工具来完成自己讨厌的工作以解脱自己 当然,有一些懒惰形式要比其它方式好一些。第一种方式是没有任何益处的。你可能有这 样的体会:你常常花费几小时来作一些没必要作的工作,而不愿面对自己所无法避免的次要的 第三十一章 个人性格 508 工作,我讨厌数据输入,但是许多程序需要少量的数据输入。别人都知道我已拖延了数天的工 作仅因为为了拖延无法摆脱的用手工输入几个数据的任务,这种习惯是“真正的懒惰”,你 编译 某一子程序以检查有关情况,这样你可以避免人工检查程序同样也是一种懒惰行为。 这些小任务并不像看起来那样令人反感,如果你养成马上完成这些任务的习惯你就能克服 拖延这种懒惰。这种习惯叫“明懒惰”——懒惰的第二种方式,你仍然是懒惰,但是你是通过 在自己所讨厌问题上花费尽量少的时间来避开问题的。 第三种选择是编写工具来作这令人讨厌的工作。这是“长期懒惰”。它 无疑是懒惰中最有积 极性的一种形式,只要你通过编写工具最终节省了时间,通过讨论可知,一定程度的懒惰是有 益的。 当你不是透过玻璃看问题的时候,你就看到了懒惰的另一方面。“赶着做”或“努力”并不 能发出炫目的光芒。赶着做是一种多余和没有必要的努力。它只是说明你的焦急而不是你进行 工作的努力程度,在有效编程中最为重要的思考是人们在思考中往往显得并不忙。如果我和一 位看起来一直很忙的程序员一起工作,我将认为他并不是一位好的程序员,因为他并不是在使 用对他来说是最有价值的工具和自己的头脑。 31.831.831.831.8 不是你想象中那样起作用的性格不是你想象中那样起作用的性格不是你想象中那样起作用的性格不是你想象中那样起作用的性格 “赶着做”并不是唯一的一种看起来可能受敬重而实际上并不起多大作用的性格。 坚持坚持坚持坚持 依赖于环境,“坚持”可能是一笔财富也可能是一种不利条件,和其它许多多义概念一样, 对它有不同的解释,这取决于你认为它是一种好的特性或坏的。如果你想将坚持定义为坏的性 质,你可能说它是“顽固”,如果你认为是一种好的品格,你可称其为“坚强”或“坚持”。 在大多数情况下,软件开发中的坚持是顽固的意思,在你碰到某段新代码时,你再固执己 见并不是什么好事。你应试着用另一个子程序,用另一种编码方法,或返回原来的地方,当某 种方法并不起作用时,你应换用另一种方法。 在调试中,当你终于发现一个烦扰你达 4 小时之久的错误时,你一定感到非常满意。但是 如果你在一段时间——通常为 15 分钟没有取得任何进展时,你应放弃找错。用你的潜意识去思 考问题,尝试用别的方法解决问题,重写全部令人厌烦的代码段。当你的精神有所恢复时重新 回到原来的问题上。和计算机错误作斗争是不明智的,你应尽量避免它们。 知道在什么时候放弃是困难的,但是这是你必须面对的一个问题。当你觉得自己受挫折时, 你可向自己提出这个问题,你问问自己并不意味着放弃,但可能意味着是对自己的行动设置规 范的时候了:“如果我不能用这种方法在 30 分钟时间内解决问题,我将用几分钟时间考虑不同 的方法,并在下一小时内尝试不同的方法。 经验经验经验经验 和书本知识比起来,软件开发中经验的价值要比其它领域小,这有几种原因。在许多其它 领域中,基本知识变化缓慢,以致于10 年前毕业的某人所学到的知识在现在仍没有什么变化。 而在软件开发中,即使基本的知识也发展迅速,在你以后 10 年毕业的某个人可能学到了二倍 第三十一章 个人性格 509 于你的有效编程方法,一些老的程序员往往被另眼相看,不是由于他们对某些特定方法缺乏接 触,而由于他们在走出校门后对一些闻名的基本编程概念缺乏了解。 在其它领域中,你今天在工作中学到的东西可能对你明天的工作有所帮助,在软件开发中, 如果你不改变你在使用从前的编程语言中的思维方式或你在你的旧机器上得出的代码调试方式 的习惯,你的经验将不值一文。许多进行软件开发的人往往花费时间准备上一次的战斗而不是 下一次,如果你不因时间而作出应变,你的经验与其说是帮助倒不如说是一个阻碍。 除了软件开发中的迅速变化外,人们常从其经验中得出错误的结论,客观地对自己进行检 查是困难的,你也可能忽视经验中使你能得出不同结论的重要之处,阅读其它程序员的研究材 料是有益的,因为研究材料揭示了其它人的经验——它们都经过充分的精炼,你可客观地对其进 行检查。 人们也往往荒唐地强调程序员的经验。“我们需要有五年以上 C 语言编程经验的程序员”就 是其中一例,如果一程序员在头一、二年没有学 C 语言,第三年学也不会产生很大区别。这种 类型的经验和其工作能力没有多大区别。 在程序开发中,知识更新迅速使此领域中“经验”处在一种奇怪的地位上,在其它许多领 域,过去有着成功历史的专业人员,往往令人放心,并且因其一串成功的事情而得到尊敬。退 步很快的人将很快和潮流格格不入。为了使自己有所价值,你必须紧跟潮流。对年青的、求知 欲旺盛的程序员,他们往往在这点上有优势,而有些老的程序员认为自己有所资格了而讨厌一 年接一年都要证实自己的能力。 最后一个问题是:如果你已工作了 10 年,你得到了10 年的经验应当是真正的经验,你如 能坚持不断地学习,你就能得到经验,如果你并不想学到什么,不管多少年你也学不到什么。 计算机迷计算机迷计算机迷计算机迷 如果你还没有至少在一相同的项目上花费一个月的时间——一天工作 16 个小时;为了发 现你的程序中最后一个错误睡眠中你也念念不忘它,你接连几天没日没夜地工作——即使你所 编的程序并不复杂,那么你可能不会意识到编程中有某种令人兴奋的东西。 Edward Yourdon 这种对编程的痴迷纯粹是胡闹,并且几乎注定要失败。但是那些通宵程序员使你觉得他们 是世界上最好的程序员,但是随后你不得不花费几周的时间来修正你在这短时间的辉煌中所带 来的错误,你可能对编程非常热爱,但是你应能冷静地处理这个问题。 31.931.931.931.9 习惯习惯习惯习惯 好的习惯起作用是由于你为一个程序员所作的大部分事情是你在无意识中所完成的,例如, 有时你可能会感到以前爱采用缩进循环,但是现在每当你编写一个新的循环时你不会这样想了。 这种情况确实在建立程序格式时存在。你最后一次向自己提出这个问题是在什么时候?如果你 已经有五年实际编程经验,你就存在较多的机会,如果你最后一次向自己提出疑问的时间在 4 年半之前,剩下的便是受习惯的支配时间了。 你在许多地方都存在习惯。例如,程序员往往爱仔细地检查循环变量而少检查赋值语句, 这就使得发现赋值语句中的错误要比发现循环变量的错误困难一些。你能对别人的批评作出 第三十一章 个人性格 510 友好或不友好的反应。你一直在寻找使代码可读或编码速度更快的方法,也可能你无意寻找它 们,如果你不得不在可读性和编码速度方面作出选择,你每次都会作出相同的选择,当然,你 并不是在真正选择;你是在习惯性地作出反应。 成为某方面好的或差的程序员,主要是靠你自己的所作所为,建筑师要通过建筑而程序员 要通过编程。你所作成为习惯,决定了你的编程品行,最终,你的习惯好坏决定了你是否能成 为一位好的程序员。 微软公司的 Bill Gates,Chairman 和 CEO 曾说过,任何好程序员在开始的几年都做得很 好。从那以后,程序员的好坏便基本定型了。在你进行编程很长一段时间后,很难见到你突然 说“我怎样才能依循环进行得更快呢? " 或“我怎样才能使代码更可读呢?”这些都是好的程 序员一开始便养成的习惯。 当你开始学某一件事时,你应按正确的方式学好它,当你开始学时,你已对其进行了思考, 并且你可在正确或错误的途径间作出轻易的选择,在你作过一段时间后,你对你所作的不太注 意,此时“习惯的力量”会开始起作用。确保起作用的习惯是你所希望的。 如果你没有养成最有效的习惯你应怎么办?对这些问题没有一个明确的答案,以 下是对此 问题的部分回答,你无法用没有习惯取代坏的习惯,这就是为什么突然停止抽烟或节食的人如 果不用一些别的什么替代的话会存在很大困难的原因。用一种新习惯代替旧习惯比完全戒除旧 习惯要容易一些,在编程中,应尽力养成良好的习惯。你应养成在编写代码之前编写 PDL(流 程图)和在编译之前阅读代码的习惯,你不必为失去坏习惯而多虑。在用新习惯取代后坏习惯 会自然而然消失的。 31313131....10101010 小结小结小结小结 你的个人性格直接影响你编写计算机程序的能力。 最有明显作用的性格为:谦虚、好奇心、诚实、创造性和纪律,还有文明的“懒惰”。 高级程序员的发展和生成与天才并无多大联系,任何事情都和个人的发展有关。 令人吃惊的是,小聪明、经验、坚持和欲望既可帮助你也能妨碍你。 许多程序员不主动去吸收新信息和新技术,而是靠偶然地上获得一些新信息,如果你 抽出少量时间学习别人的编程经验,过一段时间后,你将在你的同行中脱颖而出。 好的性格对养成良好习惯有很大影响,为了成为一位高水平的程序员,你应养成良好 的习惯,其余的就会随之而来。 第三十二章 软件开发方法的有关问题 511 第三十二章第三十二章第三十二章第三十二章 软件开发方法的有关问题软件开发方法的有关问题软件开发方法的有关问题软件开发方法的有关问题 目录目录目录目录 32.l 克服复杂性 32.2 精选开发过程 32.3 首先为人编写程序,其次才是计算机 32.4 注重约定使用 32.5 根据问题范围编程 32.6 当心飞来之祸 32.7 重复 32.8 不要固执己见 32.9 小结 本书着重于软件创建的细节:高质量子程序、变量名、循环、代码设计、系统综合等等, 本书不着重于抽象的讨论而是强调有关具体的主题。 一旦你对本书以前各部分的基本概念有了一定的了解,你只需从各章中选取不同的主题并 了解它们之间的联系,以得到对抽象概念的了解,本章是为了明确一些抽象主题:复杂性、抽 象、过程、可读性、重复等等,这些内容对软件开发有较大的影响。 32.1 32.1 32.1 32.1 克服复杂性克服复杂性克服复杂性克服复杂性 计算是唯一可将某一种思想用 1 比特到几百兆比特来度量的领域,其所用比特数比可达 1 到 109,这样庞大的数字是令人惊讶的。Edsger Dlikstra 这样表达:“和这样级别的数相比,一 般的数学方法是无能为力的。通过激起对更深的概念等级的需求,计算机向我们提出了以前从 没遇到过的挑战。” 计算机科学的核心是减少复杂性,尽管谁都希望成为一个英雄并能自如地解决各种计算机 问题,但没有人真正能有处理 109 级数的能力,计算机科学和软件工程已经开发了许多工具以 处理这样的复杂问题,本书的其它部分也或多或少的触及了这样的问题。 减少复杂性的方法减少复杂性的方法减少复杂性的方法减少复杂性的方法 在软件结构级上,问题的复杂性可以通过将系统分成子系统而得到降低,子程序越独立, 复杂性就越得以降低,你应仔细定义模块,这样你才能在某一时间集中于某一件事情,而将代 码组装成目标有许多好处。 使用全局数据是有害的,因为它可以削弱某一时刻你集中于某事的能力,使用相同的标记 符对模块数据是无害的,因为它不会使你的注意力分开。 如果你所设计的子系统间有全局变量共享或粗糙定义的接口,你也会遇到许多复杂的问 第三十二章 软件开发方法的有关问题 512 题,其结果是冲淡了因将系统分成许多子系统所带来的好处。 复杂性应可通过好的设计得到最大程度的降低,降低复杂性也是促使代码质量提高的动机。 将控制结构限制在对 if 和 for 语句的使用,以及使用无循环代码可以降低程序的复杂性。使用 goto 语句也是非常有害的,因为这些语句并不遵循特定的模式,你 不 能 简化运算而降低复杂性, 在子程序尽量写短一点。限制循环的嵌套和 if 语句的使用,限制传送给子程序的变量数都是降 低复杂性的有效方法。 当你对一个布尔函数进行复杂的测试并抽象化测试的目的时,你就降低了代码的复杂性, 当你将复杂的逻辑链用查询表替代时,你同样降低了复杂性,为主要的数据结构编制具体实现 细节,从而可简化了工作。 编码约定在某种程度上同样可降低复杂性、标准化程序的格式、循环和变量名时,你就可 省下你的精力处理有关程序编制中更富挑战性的有关问题,对代码约定有争议的原因是,其中 选择是有限的并且约定有时是武断的。即使是对最细微的情节人们也往往有着最热烈的争论。 在使你免受作出并武断决定方面,约定是最有用的。在一些有意义性领域,约定限制的价值有 所降低。 使用层次结构对大部分人来说是很自然的,当他们画一个复杂的物体如房子时,他们也是 分层画出来的。首先画房子的轮廓,然后是窗户和门,最后是其它细节,他们并不是将房子一 块砖一块砖、一块瓦一块瓦、一个钉一个针地画出来的。 在一典型的计算机系统中,将有以下几种递升的层次结构:机器指令、操作系统运行、高 级语言程序编制和用户接口操作。对于高级语言程序员,你仅需知道高级编程和用户接口即可。 它可使你免受与机器指令打交道以及对最底层的操作系统调用的痛苦。 如果你擅长设计软件系统,除了现成可用的层次之外,你也可以通过编写高级语言程序创 建你自己的层次。 抽象和复杂抽象和复杂抽象和复杂抽象和复杂 抽象是另一种通过在不同的层次上处理不同的细节来降低复杂性的。当你使用集合时,你 也就使用了抽象,如果你称某物体为房子,而不是玻璃、木材和钉子的混合体时,你也是用的 抽象。同样,你将许多房子的集合体称为“小镇”时你也用到了抽象。 抽象是比层次更为一般的概念。层次意味着阶梯式、结构化的组织,抽象并不就是层次的 结构化组织。抽象是通过将细节分布在各部分之间而不是层次的各级上来降低复杂性的。 通过对程序的各部分的抽象可以大大提高程序编制的质量。 Fred Brook 曾说过计算机科 学取得的最大进步是从机器语言向高级语言的进化——它使程序员从对硬件的很大依赖环境 中解放出来,以便于集中精力进行程序开发。子程序的使用也是一个大的进步。DBMS 的使用 同样是一个飞跃,因为它们本质是抽象数据,使你能对记录和表而不是单个数据项进行处理。 按作用给变量取相应的名字,正如对计算机的问题是使用“What”而不是使用“how”一 样,也可以提高抽象的级别,如果你说:“哦,我正在弹出堆栈,这意味着我最近得到了某个职 位。”你当然可以不说:“我正在弹出堆栈”而只需说:“我最近得到了某个职位。”使用命名常 量要比直接使用常量更具有抽象性,抽象数据类型也可以降低复杂性因为它们允许你使用和实 际数据特性有关的数据类型而不是计算机的数据结构类型。面向对象的程序编制能同时对算法 和数据进行一定的抽象——这种类型的抽象是功能分解所不能提供的。 第三十二章 软件开发方法的有关问题 513 概括地说,软件设计和编码的主要目标是克服复杂性。许多编程风格的目的也就是降低的 复杂性。对程序员来说,降低复杂性是一个很关键的问题。 32323232....2 2 2 2 精选开发过程精选开发过程精选开发过程精选开发过程 本书的第二个主要观点是,软件开发和相应的过程有很大的关系。 对于一个小的项目,程序员的才能对软件质量有着最大的影响。程序员对过程的选择对自 身的成功有一定影响。 对有多个程序员的项目,整个组织的特征要比单个程序员的技能更起作用,即使你所在开 发组规模很大,集体能力也不是个人力量的简单相加,人们在一起工作的方式,决定了其所在 集体力量的大小。整个组的工作过程决定了一个人的工作对组内其它人的影响是有益的还是 起阻碍作用。 过程起作用的一个例子是在开始设计和编码之前,没有使要求稳定所产生的后果。如果你 不知道自己究竟在创建些什么,你就不能得到一个较好的设计,如果在软件开发过程中,需要 对要求和随之而来的设计进行修改,代码也必须作修改,这就势必降低整个系统的质量。 “当然”你说,“在现实中没有真正一成不变的要求,所以这只能分散人的注意力”。反过 来,你所采用的过程也决定了要求的稳定性,如果你想对要求更有灵活性,你可以计划分阶段 交付软件而不是一次交付完毕。这是你在开发过程中应注意的。你所用过程最终决定了项目的 成功或失败,在 3.1 节中的表 3.l 清楚地表明了改正分析错误要比改正设计或代码错误费事得多, 所以对项目中某部分的强调也影响总代价和进度。 以上原则对设计同样适用,在你开始建造之间应有一个牢固的基础。如果你在创建完成之 前就急着编码的话.以后再对结构进行重大的修改是困难的,人们将会对其进行感情投资,将 会继续为自己设计编写代码。一旦你已经开始建造房子后,要想再改变基底是困难的。 过程起作用的主要原因,是由于在软件中从一开始便应牢牢控制质量,有时你可能认为自 己可随心所欲地编码,然后再测试以检查出所有错误,这是十分错误的。要知道,测试仅仅告 诉你软件中的错误,测试不能使你的程序更有用、运行更快、长度更短、更可读或者更广泛。 不成熟的乐观是另一种类型的处理错误。在有效开发过程中,你在刚开始可能会作出粗糙 的调整而在最后会作出好的调查。如果你是一个雕刻师,你可先在对细节进行修饰之前,粗糙 地雕刻出大概轮廓。不成熟的乐观是对时间的浪费,因为你花费时间修饰了其实不必修饰的代 码。你可能对较短和运行较快的代码段进行了修饰,你也可能修饰了今后将弃之不用的代码, 你应常这样想:“我这样作是否正确?改变顺序是否会产生差别?”这样你就能有意味地遵循好 的过程。 低级过程同样如此。如果你采用 PDL 流程图,并围绕 PDL 设计代码,你将会因采用自顶 向下的设计过程而受益匪浅。你也应及时对代码进行注释。 对大、小过程的观察意味着你停下来留神自己是怎样创建软件的,这是值得你花费时间的。 认为“代码才是真正有作用的,你应侧重于代码的质量,而不是某些抽象的过程”是缺乏远见 的,它忽视了许多实际的证据。软件开发是一种创造性的活动,如果你并不理解这是一个创造 性的过程,你就不能很好地利用你进行软件创建的工具——你的大脑。坏的过程浪费你的脑力, 而好的过程则能很好地利用你的脑力。 第三十二章 软件开发方法的有关问题 514 32323232....3 3 3 3 首先为人编写程序,其次才是计算机首先为人编写程序,其次才是计算机首先为人编写程序,其次才是计算机首先为人编写程序,其次才是计算机 你的程序好似迷宫一样,你的程序充满了自作聪明的东西和不相关的评论。 我的程序算法精确,结构紧凑,有效率并且注释得体。 Stan Kelly ──Bottle 另外,本书一直强调代码的可读性。和其它人交流是自我检查代码好坏的真正动机。 计算机当然不会在意你的代码是否可读,对计算机来说,它更能“阅读”二进制机器指令 而不是高级语言程序,你之所以编写可读的代码是为了帮助别人阅读你的代码,可读性对程序 的以下几个方面有着积极的影响: · 可理解性 · 可检查性 · 错误率 · 调试 · 可修改性 · 开发时间—一受以上各种因素的影响 · 外部质量——受以上各种因素的影响 在程序开发的启蒙时期,程序通常被认为是程序员的私人财产。人们对未经同事的允许就 查看其程序这类事的看待如同是你私拆别人的情书一样,这也正是程序的实质之所在,程序如 同是程序员写给硬件看的情书一样,其中亲密的细节只有当事者自己清楚。于是,程序员们便 为亲昵的称呼所笼罩,程序员们对极乐抽象世界的情人是如此着迷,以致于只意识到它们的存 在,这样的程序员在局外人看来是不可理解的。 ──Michael Marcotty 可读代码的编写并不费时,并且编写可读代码最终对你是有益的,如果你的代码可读性好, 你也就能更容易地弄清楚你的代码情况。但是在评审过程中也需阅读代码,在你或别人改正错 误时同样需要读代码,而当其它人试图利用你的某部分代码时,他也需要阅读你的代码。 在软件开发过程中代码的可读性并不是可有可无的。你应力争一次就编写出好的代码,而 不再费神去阅读较差的代码,否则你可能得返工好几次。 “我所编的代码是为自己而写的,为什么要使它可懂?”,有人说。因为你这一、二周一直 在开发另一个程序,“Hey!我上周已编写了这个子程序,现在我需看看这已受过测试和调试的代 码以节省一些时间”,如果代码是不可读的,那么就够你受的了。 如果你所编的代码是不可读的,你就好比是本项目中的 Lone Ranger,是令人厌烦的。 你的母亲肯定这样对你说过:“你为何一脸愁情?”习惯影响你的工作,你是不能随意控制 习惯的。所以你应确信你应在作的事情有助于你养成良好的习惯。 区分别人所编的代码是否是有争议对你是有益的。Douglas Comer 曾为私人和公用程序提 出了一个有用的区分标准:“私人程序”是程序员自己使用的程序,它们不为其它人所使用,也 不应被其它人所修改,通常都是琐碎的。“公用程序”是可为其它人而不仅是编写者本人所使用 和修改的程序。 公用和私人程序的标准是不同的。私人程序可随意编写并且可充满各种限制——并不影 第三十二章 软件开发方法的有关问题 515 响其它人而仅影响制作者本人。而公用程序则应该更为仔细地编写:对它们的限制应进行说 明,它们应该是可靠的和可修改的,而尾部往往正是这样,在其进入一般流通之前,你应将子 程序转换成公用于程序,并且应注意子程序的可读性。 即使你认为只有你自己才阅读代码,实际上却存在其它人需修改你的代码的许多机会。一 项研究发现在维护程序员重写某一程序之前往往需仔细研究程序 10 次,维护程序员通常要花费 50%到 60%的时间理解他们将维护的代码,他们真希望你能对其进行有关文档工作。 以前各章提供了使程序可读性好的方法:好的变量名、良好的格式、好的子程序名、小的 子程序,在布尔函数中隐含复杂布尔条件测试、在复杂计算中加中间变量等等。没有一种简单 的方法能得出可读性较好和不可读程序的差别。 如果你认为你没有必要使你的代码可懂,因为没有任何人读你的代码,你 应 确信你没想错。 32.4 32.4 32.4 32.4 注意约定使用注意约定使用注意约定使用注意约定使用 约定是复杂性管理的一种有效工具,以前各章曾提到了一些特殊的约定。本节使用许多例 子讨论约定所带来的好处。 程序开发中的许多细节在某种程度上是武断的,在一循环中你应缩进多少格?你怎样使用 注释格式?你怎样安排子程序变量?以上大部分问题都有几种正确的回答,约定可使你免于回 答这个问题,它是反复使用相同的武断决定,对有许多程序员的项目来说,使用约定可以防止 由于不同的程序员的决定不同所引起的混淆。 约定能精确地传递重要的信息,在 命名约定中,单一字符可区分局部和全局变量、模块等; 字母的大小写可以准确地区分排序型、命名常量和变量。缩进约定可精确地显示程序的逻辑结 构,对齐约定可准确地表明相关的语句。 约定可防止一些已知的危害,你可通过建立约定排除危险的习惯,限制危险习惯在一定场 合的使用,或者弥补其带来的危害,例如,通过禁止全局变量和在一行中写多条语句的使用, 排除这些并不正确的用法。你也可以限制 goto 语句只在其转移到子程序末尾时才能使用,你还 可要求复杂表达式中使用括号,或要求在一指针被释放后马上将其清除掉以防止悬挂指针的出 现。 约定可提高低级任务的预测性。对处理存储器请求、错误处理、输入/输出和子程序接口 使用约定可使你的代码结构良好,并使其它程序员易于理解你的代码——只要这些程序员了解 你的约定。正如前几章中所指出的那样,不用 goto 语句使你能排除一种非约定的控制结构。想 来读者都对 for、if 或 case 语句有一个粗略的了解吧。但是你很难知道 goto 语句是向上或向下 跳转。goto 语句的使用增加了读者的不确定感。有了好的约定,你和你的读者就能想到一起了。 需优化的细节有所减少,这反过来会提高程序的可读性。 约定可以弥补语言的不足,对于不支持命名常量的语言,约定可以区分可读写变量和只读 变量,限制 goto 语句和指针的使用也是约定弥补语言缺点的例子。 大项目的程序员有时对约定似乎是使用过分了,他们建立了许多标准和原则以致要想记住 它们是要费不少力气的,但是小项目的程序员又似乎对约定使用不够,他们并没有完全认识到 约定所带来的益处。你应能了解约定的真正价值并能正确地利用它们,使用约定以提供所需 第三十二章 软件开发方法的有关问题 516 要的结构。 32.5 32.5 32.5 32.5 根据问题范围编程根据问题范围编程根据问题范围编程根据问题范围编程 处理复杂性的一个特定的方法是在最高可能的抽象级上工作。而在最高抽象上编程的一种 方法是根据问题而不是计算机进行编程。 高级代码不应被以下细节所填满:文件、堆栈、队列、数组和一些字符如 i、j、k 等。高级 代码应是对要解决问题的描述,它应由确切表明程序功能的描述性子程序封装而成,而不是充 斥,诸如打开一个文件之类的细节。高级代码也不应包含如:i 在此处代表雇员记录变量,以后 它将用作顾客帐目文件变量…这类注释。 以上都是笨拙的编程作法。在程序的顶层,你无需知道雇员数据是来自记录或作为文件存 储。在这种级上的信息应是隐含的。在最高级上你不必知道数据是如何存储的。你也无需阅读 一条解释 i 在这儿是什么意思和 i 用作两个目的注释。如 果 i 被用作了两个目的,你就应看到为 这两个目的而设置的两个不同变量,它们应是两个有特色的名字:EmployeeIdx 和 ClientIdx。 将问题分解成不同的抽象级将问题分解成不同的抽象级将问题分解成不同的抽象级将问题分解成不同的抽象级 很明显,你不得不在计算机科学范围的某些级上工作,但是你可将你的程序分为计算机科 学范围和问题范围这两方面的工作。 如果你使用高级语言编程,你无需担心最低级——你的高级语言会自动地考虑这个问题的。 你应考虑较高级的情况,但是大部分的程序员没有做到这点,如果你在设计一个程序,你应 至少将其分成以下抽象级: 第一级:高级语言结构第一级:高级语言结构第一级:高级语言结构第一级:高级语言结构 高级语言结构是原始数据类型,控制结构等等,你使用高级语言是很自然的,因为没有它 们你就无法编写高级语言程序。许多程序员从来不在此抽象级之上工作,这就使他们遇到不少 困难。 第二级:计算机科学结构第二级:计算机科学结构第二级:计算机科学结构第二级:计算机科学结构 计算机科学结构级别比高级语言结构级稍高一些。它们往往是你在大学课程中所学到过 4 高级问题范围 3 低级问题范围 2 计算机科学结构 1 高级语言结构 0 操作系统操作和机器指令 第三十二章 软件开发方法的有关问题 517 的操作和数据类型——堆钱、队列、链表、树、索引文件、顺序文件、排序法、搜索算法等等。 虽然本级比高级语言结构级要高,仍有许多的细节工作要作,以克服复杂性。 第三级:低级问题领域第三级:低级问题领域第三级:低级问题领域第三级:低级问题领域 在本级中,你需要对问题的原始描述。为了在这级上编写代码,你应清楚问题的专业术语 和积木块,以便能解决问题。在本级中,子程序还不能直接解决问题,但是它们可以用来生成 更高级的子程序以便直接解决问题。 第四级:高级问题领域第四级:高级问题领域第四级:高级问题领域第四级:高级问题领域 本级提供了在本问题上的抽象能力。你在本级上的代码在某种程度上应是可读的——一般 的应用人员即可读懂。本级代码并不完全依赖于你编程所用高级语言的某些特征,因为你创建 了自己处理问题的工具。因此,在本级上你的代码更依赖于工具而不是你使用语言的能力。 细节的实现隐藏在两层外壳下面,在计算机科学结构层中,硬件或操作系统的变化对其不 会有什么影响,本级上也包含用户的见解。因为当程序变动时,它将接受用户的见解而作修改 的。问题范围的变化对这层有较大影响,但是通过编制问题领域的积木块,此变化应是容易协 调的。 在问题领域采用低级方法在问题领域采用低级方法在问题领域采用低级方法在问题领域采用低级方法 即使没有一完整的有组织的方法能适用于问题领域,你可以使用本书中的有关方法以解 决实际问题而不是对计算机科学问题。 · 在问题领域使用抽象数据类型以实现有实际意义的结构。 · 隐含有关计算机结构和实现细节的有关信息。 · 在面向对象的程序中,设计和问题有直接关系的成员,压缩问题领域中的有关信息。 · 对有意义的字符串和数字使用命名常量。 · 对中间计算结果使用中间变量。 · 使用布尔函数以净化复杂布尔测试。 32.6 32.6 32.6 32.6 当心飞来之祸当心飞来之祸当心飞来之祸当心飞来之祸 程序编制既不是完全的一门艺术也不是一门科学,更不是二者的神圣的结合。在某种程度 上它是介于二者之间的一门技艺。在创建某一软件产品过程中,它仍然需要大量的个人判断, 在程序编制中,作出好的判断,也要求微妙问题的警告信息作用反应。警告信息提醒你程序中 的可能错误,但是它不会像路标上那样醒目地提示:“当心飞来之祸”。 当你或其它人说到“这真是一个棘手的程序”时,这通常是对不好的代码的警告信号。“棘 手的程序”是“坏程序”的代名词,如果你认为某子程序是棘手的,你可以考虑重写它。 比一般子程序含更多错误的子程序是一种警告信号,少数一些出错的子程序含有更多的错 误,你可能还会出现错误,此时你应重写它。 如果程序编制是一门科学,每条错误信息就表明一特定明确的改错方法,因为程序编制只 是一门技艺,警告信息仅指出了你应考虑的问题,这并不意味着你一定要重写子程序才能提高 其质量。 正如某子程序所出现的反常错误数,警告你子程序的质量低,而程序中所出现的反常错误 第三十二章 软件开发方法的有关问题 518 数则说明你的整个过程中存在问题的。好的开发过程中不允许出现有错误的代码,在结构评审 后应对结构进行检查和平衡,设计评审后应修改设计,代码评审后应进行代码修改。但代码接 受测试之前,绝大多数代码应得到检查,除了工作努力以外,你还应认真仔细对项目检查多次 调试意味着欠缺认真,在一天中编写许多代码然后花费二周的时间调试也是不细心认真的表现。 你也可将设计度量用作一种警告,大多数设计度量在给出设计质量上颇有启发性的:某一 占二页多长打印纸的子程序并不就意味着设计得不好,但是它说明子程序是复杂的,同样,在 子程序中有 10 个以上判决点、三层以上逻辑嵌套、不 寻常的变量数目和其它子程序的异常耦合 或内部代码欠紧凑也都是警告标志;但是这并不意味着子程序编得不好。只是其出现会使你以 怀疑的眼光看待你的子程序。 任何警告信息都可能使你怀疑你的子程序的质量。正如 Charle Saunder 所说的:“怀疑使我 们不舒服和不满意,从而难以自我解脱”。将警告信息视为对“怀疑的激励”这样就促使你追求 更完美的境界。 如果你发现自己老在编制相同的代码或作相似的修改,你 将 会“不自在和不满意”,并怀疑 子程序或宏所使用的控制是否合适,如果你因不能自如地实现对子程序的调用,而发现要创建 测试事例的骨架是困难的,你将会产生怀疑并问自己本子程序是否和其它子程序耦合过紧,当 你因子程序的缺乏独立性而不能重新利用其它程序中的代码时,这也是子程序耦合过于紧密的 警告信号。 当出现警告信息时,你应对此有所注意,因为意味着你的设计并不是很好,以致不能自如 地编码,当你在编写注释、命名变量、分解问题将其各方面分给良好定义的子程序等方面存在 困难时,这就说明在编码之前你需更深入地考虑设计,平凡的子程序命名和使用一行注释发生 困难也同样是不好的信号,当你心中对设计有一个清晰的了解时,在低级细节上进行编码是很 容易的。 如果你的程序让人难以理解的话,你对此应有所警觉,任何不安都是暗示。如果你自己都 难以理解,别的程序员就不用提了。他们是希望你努力提高可理解性的。如果你不是通过阅读 来理解代码的,这也是太复杂了。真是这样的话,你应简化它。 如果你想充分利用警告信息,你应在程序编制中创建自己的错误警告。这是相当有用的, 因为即使你知道此警告,你也很易忽视它。 Glenford Myers 在错误改正的研究中发现,没发现 错误的最常见的原因只是因为忽视了它们,这些错误在测试输出中是可见的,但是未引起注意。 在你编程时不应忽视有关问题。其中的一个例子是在释放指针后将其置为 NULL 或 NIL, 否则你误用它们后可导致糟糕的问题。即使在释放后,指针也可能会指向有效的存储单元。将 其设置为 NULL 或 NIL 可确保它指向一无效的存储单元,这样可避免错误。 编译警告是文字警告,它们也往往易被忽视,如果你的程序出现了警告或错误,你应改正 它们,当你对印有“WA RN IN G”这类警告信息都忽视时,你不大可能注意到其它微妙的错误。 为何注意警告错误在软件开发中这般重要?你在程序开发中的仔细程度在很大程度上决定 了程序的质量,所以对警告信息的注意程度对最终产品有所影响。 第三十二章 软件开发方法的有关问题 519 32.732.732.732.7 重复重复重复重复 在许多软件开发活动中,重复是合适的。当你开始系统的开发时,你会同用户商量需求的 各种形式直到你满意为止,这就是一个重复的过程,如果你想通过升级获取更大的灵活性,你 将分阶段交付系统,这也是一个重复过程。如果在制作最终产品之前你迅速而又廉价地开发出 了几种不同的方法,这也是另外一种重复,在最初阶段,重复可能同开发过程的其它任何方面 一样重要,在开始研究不同的方法之前,局限于某种解决方法,项目就会失败,在你开始创建 之前,重复可使你对产品有所了解。 正如第二十二章对创建管理的讨论所指出的那样,在初始计划阶段,由于所使用方法的不 同,进度评估的结果会有很大差别,使用重复方法比单一方法更能得出精确的估计。 软件设计和其它所有开发过程一样,是要经过逐步修改和提高的,软件往往是被确证有效 而不是被证明,这意味着它将被重复测试和开发直到能正确地回答问题为止。高级和低级设计 都应被重复,第一次尝试所产生的结果也许是可行的,但并不就是最好的。使用不同的方法重 复进行就能加深对问题的了解。 重复方法对代码调整同样有益。一旦软件是可运行的,你可重写小部分代码以提高整个系 统的性能。然而,许多优化并不会对原来的代码有益而只会降低其性能。这并不是一个凭直觉 就能把握的过程。有些方法看起来使系统较小和运行速度较快,而实际上使系统更大和运行速 度更慢。对任何优化方法的效果不确定性往往要求反复地调整和度量。如果它是整个系统性能 的瓶颈,你应对代码进行多次调整,你最终的几次尝试可能比最初的几次更为成功。 至少,重复有助于提高产品的描述、计划、设计、代码质量和其性能。 评审可使开发过程少走弯路,在评审过程的任何阶段都可插入重复,评审的目的是检查在 特定时间内的工作质量,如果产品在评审中未通过的话,它将会返工。如果通过了,也就不需 要重复了。当然如果你走向重复的极端的话,你将如 Fred Brook 所说的那样,创建一个你将废 弃不用的东西,工程学的一个任务,是其它人用 1 美元来完成的,你用一角钱来完成它。将整 个系统废弃不用就是别人用一美元能完成的事你得用二美元才能完成。在软件工程中,你应尽 可能迅速地将要报废的事情处理掉。 第三十二章 软件开发方法的有关问题 520 32.8 32.8 32.8 32.8 不要固执己见不要固执己见不要固执己见不要固执己见 偏执在软件开发过程中有着各种变种:顽固地地坚持某种设计方法,执着于某种特定格式 或注释风格,一味地不用 goto 语句,它都是不正确的。 判断判断判断判断 不幸的是,一些专业优秀人员往往更容易偏执。在新方法开始流行之前应得到充分的证 实,研究结果向最初者的传播称为“技术转移”,它对提高软件开发的最初状况有着重要的影响, 忧而传播一种新的方法和卖狗皮育是不同的两回事。人们对于一种方法的传播往往是这样理解 的。叫卖者向人们兜售自己的东西时,极力鼓吹他的东西是如何灵验、试图以此来说服别人、 这些叫卖者要人们忘掉过去已学的一切,因为本方法能将你的效率提高 100% 。 当你碰到这样的人时,应问问他使用新方法工作了多长时间,他 可 能 会说。“很好我已经使 用了 15 年,许多客户都已证明了我这种方法的有效性”。废话,他不会说许多人采用他的成果 而浪费了 800 美元。你可继续追问他自己亲自使用了本方法有多久、通常地不仅没有使用此新 方法开发某一系统,甚至也没有用他提出要抛弃的旧方法开发过系统! 你不应对流行的时尚充耳不闻。应取其之长,补己之短,但是应保留好原来的一切。 选择选择选择选择 对某种方法的盲目迷信,会阻碍你对编程问题最有效解答,如果软件开发是一个确定的。 精确过程,你可按一套僵化的方法以寻求问题的解决。实际上,软件开发是靠经验的,此时僵 化的过程是不合适的,其成功的希望更是微乎其微。例如,在设计中,有时自顶向下分解法有 效而有时面向对象的方法,自底向上分解法或数据结构方法更有效。你应有尝试几种途径的愿 望,知道有时会成功或失败,但是在你对其尝试之前是不会知道结果的。 对某一种方法的固执己见也是有害的因为它只能使你勉为其难地解决问题。如果你在充 分了解问题之前,就得出解决问题的方法的话,这是不明智的,你因此而限制了各种可能的解 决方法并且有可能排除了最为有效的方法。 刚开始你可能对任何新方法感到不安,让你不要过于偏执的建议并不是让你在用新方法 解决问题遇到困难时就停止采用新方法。参考本书和其它途径所提供的各种方法你也应抱有 选择的态度、对几方面问题的讨论已经得出了许多你不能同时使用的方法。每一特定问题你应 选择一种或几种方法。你也应将方法视为工具盒中的工具,并在工作中利用自己的判断选择最 好的工具。在大部分时间内工具的选择是无关紧要的。而有些场合,工具的选择是重要的,所 以你应仔细地作出选择,工程学在某种程度上是对各种方法作出综合评估,如果你早早就将自 己的选择限制在单一工具上,你就无法作出衡量。 工具箱比喻是有用的,因为它使具体的选择抽象化了。在高级层次上,你有几种选择方法, 你可选择几种不同的数据结构之一以代表任何给足的设计。而在更具体的级上,你可在格式、 释、代码、命名变量、子程序参数传送方面选择几种不同方案。 顽固的态度和可选择软件创建工具箱方法是矛盾的,也和创建高质量软件所需的态度是不 相容的。 第三十二章 软件开发方法的有关问题 521 实验实验实验实验 选择和实验有着密切的联系,在整个开发过程你应坚持实验,但是偏执可能会阻止你这样 作,为了有效地进行实验,你应能随机应变。否则,实验只徒然浪费你的时间。 在软件开发过程中,许多人的偏执往往是由于害怕发生错误,试图避免发生错误是最大的 错误。设计正是一个仔细地计划小错误而达到避免大错误的过程。软件开发中的实验是创建测 试的过程,这样你便能知道一种方法是失败或成功——实验本身就是一个成功地解决问题的过 程。 在许多级上,实验和选择一样合适,在你准备作出选择的每一级上,你都能提出对应的实 验,以决定哪一种方法最佳。在结构设计级上,实验包括使用不同的方法勾画出软件的结构。 在细节设计级上,实验可能包括使用不同的低级设计方法,遵循高级结构的有关规定。在编程 语言级上,实验包括编写一短的实验性程序,以检查你并不很熟悉的语言的部分功能。这种实 验可能会调试代码并度量它,以确证它是真正变短了或运算速度加快了。在软件开发过程中, 实验可能是收集质量和效率数据,以了解检查是否比普查要能发现更多的错误。 重要的是你应对软件开发的各方面都保待开放的思想,这样你就能在开发过程中学到不 少技术。开发性实验和对某种方法的顽固坚持是不相容的。 32.9 32.9 32.9 32.9 小小小小 结结结结 · 程序编制的一个主要目的复杂性管理。 · 编程过程对最终产品的影响比人们想象中的要大。 · 合作程序开发要求各成员之间进行广泛的交流,其次才是和计算机的交流,而个人则 主要是和你自己而不是和计算机交流。 · 当被乱用时,约定好比是雪上加霜,而使用得当的话,约定可增加开发环境的有用结 构,并有助于管理复杂性和交流。 · 面向问题而不是解答的编程有助于对复杂性的管理。 · 注意警告信息是相当重要的,因为编程几乎是纯智力活动。 · 在开发过程重复越多,产品质量也就越高。 · 武断的方法和高质量软件开发是不相容的。你应知道各种程序编制的方法,并能从中 挑选出适合你工作的方法。 第三十三章 从何处获取更多的信息 522 第三十三章第三十三章第三十三章第三十三章 从何处获从何处获从何处获从何处获取更多的信息取更多的信息取更多的信息取更多的信息 目录目录目录目录 33.1 软件领域的资料库 33.2 软件创建信息 33.3 创建之外的主题 33.4 期刊 33.5 参加专业组织 当你读到这里后,你应对软件开发过程很有了一些了解。人们可以获取很多信息,也许, 你现在所遇到的错误是别人早期碰到过的。除非你是想自讨苦吃,你应阅读他们所写的书以避 免他们所犯过的错误并找出解决问题的新方法。 33.1 33.1 33.1 33.1 软件领域的资料库软件领域的资料库软件领域的资料库软件领域的资料库 由于本书涉及了许多文章和其它书籍,想知道先读什么是困难的。 软件开发资料库由几类资料组成:解释有效编程基本概念的书,解释在程序开发中技术管 理、知识背景的书,还有关于语言、操作系统、环境和硬件等一些对特定项目较为有用的参考 书籍。 在所有其它书籍中,你有一些集中讨论主要软件开发活动的书籍,它们主要是关于分析、 设计、创建、管理和测试等方面的书籍。 作者推荐的作者推荐的作者推荐的作者推荐的 10 种书种书种书种书 以下一些书理构成了软件开发活动中基本的资料库: 1.The Psychology of Computer Programming(1971 年)Gerald Weingerg,本书包含许多程 序开发中的趣闻轶事。 2.Programming Pearls(1986)作者是 Jon Bentley。本书对程序开发进行了生动有趣的讲 义,其对各种原因的生动阐述会使许多人觉得程序编制是一件有趣的事情。 3.Classics in Software Engineering (1979)作者是 Ed Yourdon,本书收集了软件工程的许 多研究论文。 4. Principles of Software Engineering Mangemment(1988)作者是 Tom Glib,本书主要讨论 管理,并有助于你加强对项目的管理。 5.Structured desigen(1979)作者是 Yourdon 和 Constantine。,本书主要讨论结构设计的有 关方法和思想。 6. The Art of Software Testing(1979)作者是 Glenford。 7. 一本关于需求分析的书。 第三十三章 从何处获取更多的信息 523 8. 项目计划和效率进行宣分析的书。 9. 本关于数据结构和算法分析的书。 10.一本从整体上讨论软件开发过程的书。 33.2 33.2 33.2 33.2 软件创建信息软件创建信息软件创建信息软件创建信息 作者之所以写这本书是因为作者当时还没有发现一本对软件创建进行详细讨论的书,当作 者正在编写此书时,Prentice Hall 出版了 Michael Marcotty 所编的 Software Implememtation 一 书(1919 年)。Marcotty 侧重于抽象、复杂性、可读性和修改,对创建进行了讨论。读者也可 看 Prentice Hall 的 Practical Software Engineering 一书。 33.3 33.3 33.3 33.3 创建之外的主题创建之外的主题创建之外的主题创建之外的主题 以下是似乎和软件创建无关的一些书籍。 软件创律的一般书籍软件创律的一般书籍软件创律的一般书籍软件创律的一般书籍 l.Classics in Software Engineering(1979),Ed Yourdon 2. Writings of the Revolution:selected Readings on Software Engineering(1982),Ed Yourdon 3. Tutorial:Programming Producitivity:Issues for the Eighties(1986),Capers Jone 4. Software Conflict: Essays on the Art and science of Software Engineering(1991)Robert L.Glass 软件工程总览软件工程总览软件工程总览软件工程总览 计算机程序员和软件工程师都应有一本关于软件工程的高级参考书。这样的一本书应是对 基本方法的总览,而不是对具体细节的讨论了。它们应是对有效软件工程的概括,并总结了软 件工程的有关技术。以下是有关书籍。 l. Software Engineering(1989 年),Ian Sommerville 2. Software Engineering:A practitioner's Apporoach(1987),Roger S. Pressman 3. Practical Handbook for Software Development(1985),N.D.Birrell 和 M.A.Ould 4. Making Software Engineering Happen: A Guide for Installing the Technology(1988),Roger Pressman 用户界面设计用户界面设计用户界面设计用户界面设计 这类书籍主要讨论用户界面设计中颜色、响应时间,命令行结构、菜单设计等有关工程原 则、参考书籍如下: 1. Design the User Interface: strategies for Effective human-Computer Interaction(1987)Ben Shneiderman 2.The Elements of Frieldly Software Design:the Mew Edition(1991),Paul Hechel 3.The Art of Human-Computer InterfaceDesign(1990),Brenda Laurel 第三十三章 从何处获取更多的信息 524 4.The Psycholoss of Everyday things(1988),Donald A. Norman 数据库设计数据库设计数据库设计数据库设计 不管你的程序的是大还是小,是否使用数据库,你知道数据库都是有益的,如果你的程序 中用到了文件,你就是在用数据库。以下是二本参考书籍。 1.An Introduction to Database System(1977),Chris Date 2. Fundamentals of Database Systems(1989),Ramez Elmasri 和 Shamkant B. Navathe 正规的方法正规的方法正规的方法正规的方法 正规的方法是通过逻辑变量而不是运行测试证明程序的正确性。正规方法还只被应用在少 数项目中,但是其中一些已在质量和效率方面给人留下了难忘的印象,以下是一些参考书籍。 1. Software Engineering Mathematics(1988),Jim Woodcock 和 Martin Loomes。 2. Structured Programming: Theory and practice(1979),Richard C. linger,Harlan D, Mills 和 Bernard I. Witt 3. Social Process and proofs of Theorems and programs(1979),Richard A.DeMillo,Richard J. Lipton 和 Alan J. Perlis。 4. Program Verification:The Very Idea(1988),James H. Fetzer 33.433.433.433.4 期刊期刊期刊期刊 初级程序员杂志初级程序员杂志初级程序员杂志初级程序员杂志 以下杂志可在本地书报摊下发现: BYTE Computer Language Datamation Dr Dobb's Journal 高级程序员杂志高级程序员杂志高级程序员杂志高级程序员杂志 这类杂志在当地书报排难以买到,你可去大学图书馆去查询或预订它们; IEEE Software IEEE Computer Communication of the Acm 精装出版物精装出版物精装出版物精装出版物 American Programmer The Software Practitioner Software Practice and Experience 第三十三章 从何处获取更多的信息 525 专题出专题出专题出专题出版物版物版物版物 1. 专业出版物 可向 ACM 或 IEEE 等组织去信联系 2. 通俗出版物 The C Users Journal DBMS:Developing corporate Applications Embedded systems Programming LAN Techndogy:The Technical Resource for Network Specialists LAN:The Local Area Network Magazine MacWorld PC Techniques Personal Workstation:Configuring Windowed Networked Computers UNIX Review Software Management News Windows Tech Journal 33.533.533.533.5 参加专业组织参加专业组织参加专业组织参加专业组织 学习程序编制的最好方法是和其它程序员进行接触和交流。你可加入本地有关组织。你也 可加入 ACM 和 IEEE 等国际性专业组织。 致谢 1 代码大全代码大全代码大全代码大全中文电子版的诞生中文电子版的诞生中文电子版的诞生中文电子版的诞生来源于来源于来源于来源于 4444 个月来下面列表中近个月来下面列表中近个月来下面列表中近个月来下面列表中近 100100100100 位网友出色的志愿工作。位网友出色的志愿工作。位网友出色的志愿工作。位网友出色的志愿工作。 全书扫描:Sequoia 项目组织:Bear OCROCROCROCR 及及及及校对进程校对进程校对进程校对进程 (2001 (2001 (2001 (2001----04040404----05 18:42:00 100% 05 18:42:00 100% 05 18:42:00 100% 05 18:42:00 100% 完成完成完成完成)))):::: 序号 志愿者 校对范围 送出日期 送回日期 状 态 备注 0 Bear 序言目录 01-01-04 01-01-09 OK 360--369 01-01-10 01-01-13 OK 1 Wu Ke 001--010 01-01-05 01-01-08 OK Good!! 210--219 01-01-09 01-01-12 OK Good! 2 differ 011--020 01-01-05 01-01-07 OK Good!!! 250--259 01-01-09 01-01-11 OK Thanks. 260--269 01-01-09 01-01-11 OK Thanks. 270--279 01-01-09 01-01-11 OK Thanks. 3 Li Yuan 021--030 01-01-05 01-01-10 OK Good! 4 蚊子 031--040 01-01-05 01-02-01 OK Good! 5 Jerry Xing 041--050 01-01-05 01-01-09 OK Good!! 400--409 01-01-10 01-01-14 OK Good! 6 stephen 051--060 01-01-06 01-02-26 OK Good! So late :) 7 Leeseon 061--070 01-01-06 01-01-08 OK Good! 8 王晋隆 071--080 01-01-06 01-01-15 OK Good! 9 meijg 081--089 01-01-06 01-01-08 OK Good!! 200--209 01-01-08 01-01-16 OK Good! 10 Jimi 090--099 01-01-07 01-01-21 OK Good! 11 Xuym 100--109 01-01-07 01-01-09 OK Good!! 300--309 01-01-10 01-01-22 OK Good!! 12 longman 110--119 01-01-07 01-01-09 OK Good! 13 mingnan 120--129 01-01-07 01-01-08 OK Good! 340--349 01-01-10 01-01-15 OK Good! 14 minqiangshang 130--134 01-01-07 01-01-12 OK Good! 15 深夜清风 140--149 01-01-08 01-01-08 OK Good!! 420--429 01-01-10 O1-01-11 OK Good! 16 雨轩 150--159 01-01-08 01-01-10 OK Good!! 520--525 01-01-11 01-01-12 OK Good! 17 eighth 160--169 01-01-08 01-01-10 OK Good! 18 风中之烛 170--179 01-01-08 01-01-10 OK Good!! 330--339 01-01-10 01-01-16 OK Good! 19 Zhangbin_$$$_ 180--189 01-01-08 01-02-03 OK Good! 致谢 2 20 benjamin 190--199 01-01-08 01-01-16 OK Good! 21 kimfeng 220--229 01-01-09 wangzhe new 22 大海 230--239 01-01-09 01-01-11 OK Good! 23 lij 240--249 01-01-09 01-01-12 OK Good! 24 xafgs 280--289 01-01-10 xinjian new 25 javylee 290--299 01-01-10 liangyx new 26 LECON 310--319 01-01-10 01-01-10 OK So quickly 27 喻强 320--329 01-01-10 无法下载 28 Mr Jiang 350--359 01-01-10 陈立峰 29 chencqs 370--379 01-01-10 01-01-10 OK So quickly 30 张岩 380--389 01-01-10 01-01-10 OK So quickly 31 萧萧 390--399 01-01-10 01-01-12 OK Good! 32 laojiu 410--419 01-01-10 01-01-21 OK Good! 33 freewei 430--439 01-01-10 01-01-11 OK Good!! 34 HugeAnt 440--449 01-01-11 Shen_Ray 35 liangyx 450--459 01-01-11 01-01-17 OK Good! 36 yunannan 460--469 01-01-11 01-01-11 OK So quickly 37 RichardYu 470--479 01-01-12 01-01-17 OK Good! 38 Cao 480--489 01-01-12 出差 zhangjinyu new 39 王晓初 490--499 01-01-12 01-01-15 OK Good! 40 冰狐 500--509 01-01-12 01-01-12 Good!! 41 tecman 510--519 01-01-12 01-01-13 OK Good! 42 杨立波 135--139 01-01-13 ... 已寄去 on 01-02-13 43 dxx 090--099 01-01-16 01-01-21 OK Good! 44 Brandon Wang 220--229 01-02-12 01-02-20 OK VeryGood! kimfeng old 45 xinjian 280--289 01-02-13 01-02-27 OK VeryGood! xafgs old 46 vdgame 320--329 01-02-14 01-02-16 OK VeryGood! 喻强 old 47 Shen_Ray 440--449 01-02-16 01-02-23 OK 很棒! HugeAnt old 48 liangyx 290--299 01-02-16 01-02-26 OK Good! javylee old 49 陈立峰 350--359 01-02-19 01-02-20 OK So quickly! 50 zhangjinyu 480--489 01-02-20 01-02-28 OK 很棒!Cao old 51 mayongzhen 135--139 01-03-20 ... 给一个非 263 邮箱给我! 52 dongfang7 135--139 01-04-04 01-04-05 OK Very Good! 致谢 3 格式化进程格式化进程格式化进程格式化进程 (2001 (2001 (2001 (2001----04040404----20 09:09:0020 09:09:0020 09:09:0020 09:09:00 100% 100% 100% 100%完成完成完成完成)))) 章 志愿者 送出日期 送回日期 状态 备注 1-6 Bear 01-01-04 01-01-09 OK 7 Meijq 01-02-14 01-02-24 OK 虽页多,却很棒! 8 Libinbin 01-02-14 01-02-18 OK Good! 9 barrycqj 01-02-09 barrycqj OK- 差 135-139 ! 10 JSL 01-02-07 01-02-11 OK Good! 11 Fadey 01-02-14 01-02-22 OK 很棒 12 杨立波 01-02-08 01-02-14 OK Good! 13 Gyb 01-02-07 01-02-10 OK Good! 14 getit911 01-02-09 01-03-19 OK Good! 15 Gyb 01-03-20 01-03-21 OK So Quickly! free51 has gone , wai_chow lodgue old ! 16 ctx 01-02-09 01-03-01 OK NoDoc 一个字一个字地敲上去的! 17 jiang chun yi 01-02-09 ... ! 17 huzhiyan 01-03-21 ... 联系不上,263! 17 Bear 01-03-30 01-03-31 OK 18 dongfang7 01-02-10 01-02-15 OK 缺 280-299;但自己 OCR 了。 页虽多,却很漂亮! 19 mingnan 01-02-19 01-02-28 OK Very Good! 20 SimonLee 01-03-05 01-03-20 OK Very Good!金添 old 21 彭晖 01-02-20 01-03-01 OK Very Good! 22 Brandon Wang 01-02-20 01-03-08 OK Very Good! 23 Benjamin 01-02-12 01-02-14 OK 非常棒 24 锡山市堰桥中 学 01-02-13 01-02-23 OK Very Good! Steelim old for 出差了 25 lij 01-03-02 01-03-12 OK Perfect ! 26 winsun 01-02-12 ... 01-03-04 重发 26 xieye 01-03-21 01-03-22 OK Perfect ! is shcoking 27 vdgame 01-02-20 01-03-04 OK Wonderful! 28 Russell Feng 01-02-20 ... ... 2001-04-08 之前 28 Dongfang7 01-04-09 01-04-19 OK Perfect! 29A DeepBlue Eye 01-02-20 . ... 459-469 29A Bear 01-04-09 01-04-09 OK 29B 杨涛 01-02-28 ... 470-486 过两天 29B abc 01-03-27 . ... Gone off on 01-04-09 29B 郭力 01-04-09 01-04-09 OK Perfect! 30 libinbin 01-02-19 01-02-23 OK Perfect! 31 JSL 01-02-20 01-02-25 OK Perfect! 致谢 4 32 darkstar13 01-02-13 01-03-07 OK Very Good! 33 vdgame 01-02-13 01-02-14 OK Very Good! 统校进程统校进程统校进程统校进程 (2001(2001(2001(2001----04040404----21 21:09:0021 21:09:0021 21:09:0021 21:09:00 100% 100% 100% 100%完成完成完成完成)))):::: 章 志愿者 送出日期 送回日期 状态 备注 01-05 Bear 01-03-05 01-03-31 OK 终于完成了! 06-10 dongfang7 01-03-06 01-03-20 OK Perfect! 完成 135-139 11-15 Yu Youling 01-03-06 ... 给一个非 263 邮箱给我! 11-15 kingofwang 01-03-29 01-04-10 OK Perfect! 16-20 zigzeg 01-03-06 01-04-19 OK Good! 21-25 wslee 01-03-06 01-03-16 OK Perfect!!! 26-30 hyj 01-03-08 01-04-10 OK Perfect! 31-33 bgfish 01-03-06 01-03-09 OK Perfect! 全书整合进程全书整合进程全书整合进程全书整合进程 ( ( ( (2001200120012001----04040404----29 0:15:00 29 0:15:00 29 0:15:00 29 0:15:00 100%100%100%100%完成完成完成完成)))) 章 志愿者 开始日期 结束日期 状态 备注 1-33 Bear 01-04-21 01-04-29 OK Perfect! One for all, all for one!One for all, all for one!One for all, all for one!One for all, all for one! www.delphidevelopers.com
还剩28页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 15 金币 [ 分享pdf获得金币 ] 1 人已下载

下载pdf

pdf贡献者

ecjtuxuan

贡献于2010-11-23

下载需要 15 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf