我们如何定义软件开发过程?这看上去似乎是一个愚蠢的问题。为什么不直接说“软件开发就是软件开发”,然后置之不理呢?其实,如果将软件开发的工作与其他专业性质的工作进行对比,就可以深入了解软件开发的过程。然后通过研究相关领域的过程改进,来优化软件开发的过程。为此,本章将会探讨理解软件开发的一些常见方式。
为了更好地理解程序员是如何开发软件的,我们可以将软件比喻为人们创造的其他东西。这样做,是为了让我们更好地理解软件开发是什么,以及不是什么。
Robert Pressman在他的 Software Engineering:A Beginner's Approach 一书中指出了软件的几个特征。本节会通过探讨这些特征来阐明软件的本质,以及如何定义一个计算机程序员的工作。
软件是被开发或者设计出来的,它不是传统意义上被制造出来的。
——Robert Pressman
与硬件产品相比,软件产品的生产制造成本非常低,例如,刻录一张CD或者DVD只需几元钱,再加上少量的运输和人工费用(如果是电子分销,则会更便宜)。此外,软件设计对生产出来的CD/DVD的质量或者最终成本影响很小。假设生产工厂有合理的质量控制,那么程序员在设计软件应用程序时,很少需要考虑生产制造的问题 。相比之下,在其他工程行业中,工程师必须根据产品的可制造性来进行设计。
无论是软件还是硬件,在产品的早期都会因为糟糕的设计而面临失败。然而,如果我们能够解决产品中的设计缺陷(也就是说,交付一个没有缺陷的软件或者硬件),那么两者之间的差异就会变得非常明显。一旦某个软件是可以正确运行的,它就永远不会失败或者“耗尽”。只要底层的操作系统运作正常,软件就会一直工作 。与硬件工程师不同的是,软件工程师在设计时,不必考虑应该如何轻松地替换那些随着时间推移而失效的组件。
大多数软件都是定制化的,而不是由已有的(标准)组件组装而成的。
——Robert Pressman
尽管人们已经做了很多尝试,希望能够创建类似于标准化的软件组件,再由软件工程师将其组装成一个大型的应用程序,但是软件IC(相当于电子集成电路)的概念从未被实现过。软件库和面向对象的编程技术鼓励重用已经编写好的代码,但是通过组装较小的预定义组件来构建大型软件系统的想法,始终未能像硬件设计一样产生出类似的东西。
在许多情况下,我们无须投入很大的成本,就可以将一个已有的软件应用程序用一个新的版本(甚至是一个完全不相关的应用程序)替换掉 。应用程序的最终用户可以轻易地将旧的软件替换为新的软件,并且享受新版本所带来的各种好处。事实上,大多数现代的软件系统和应用程序都会通过互联网进行自动升级,而不需要一般的人工操作。
软件不是一个独立的产品。电气工程师可以设计一个硬件设备,它可以完全独立地运行。然而,软件的正常运行依赖其他许多东西(通常是某个计算机系统)。因此,在设计和实现软件应用程序时,软件开发人员必须接受其他外部系统(例如,计算机系统、操作系统、编程语言等)所带来的约束。
计算机程序员经常被比作艺术家、工匠、工程师、建筑师或者技术员。虽然计算机编程与这些职业中的任何一个都不完全一样,但是可以通过与这些行业进行对比,从它们所使用的技术中获得经验,来帮助我们更好地理解程序员这个职业。
在计算机编程的早期,软件开发被认为是一门艺术。编写软件的能力——将如此多的废话弄明白,然后创建一个可以工作的程序——这似乎是上帝赐予的天赋,只有经过挑选的少数人才能具有这种能力,类似于绘画大师或者音乐大师。(事实上,相当多的证据表明,音乐家和计算机程序员使用相同的大脑区域来进行创造性活动,而且有相当比例的程序员曾经或者现在是音乐家 。)
但是软件开发真的是一种艺术形式吗?艺术家通常被定义为拥有某些天赋和以创造性的方式使用这些天赋的人。这里的关键词是天赋,这是一种与生俱来的能力。因为不是每个人天生都有同样的天赋,所以不是每个人都能成为艺术家。与此类比,如果你想成为一个程序员,那么你应该天生就是程序员,的确,有些人似乎天生就有编程的天赋。
“程序员像艺术家一样”的比喻似乎更适用于评价那些最好的程序员。尽管艺术家们遵循他们自己的一套规则创作出高质量的艺术作品,但是当他们打破规则并探索新的创作领域时,往往能创作出最杰出的艺术作品。同样,最优秀的程序员虽然熟悉好的软件开发规则,但是也愿意尝试用新的技术来改进软件开发过程。正如真正的艺术家不满足于重复现有的工作或者风格一样,“程序员像艺术家一样”指的是程序员更喜欢创建新的应用程序,而不是在一个旧的版本上一直打磨。
注意 :最受尊敬的计算机科学系列教材之一是Donald Knuth编写的 The Art of Computer Programming (《计算机程序设计艺术》)。显然,编程作为一种艺术形式的观念在计算机科学领域已经根深蒂固。
对于很多小项目来说,艺术家的比喻很形象,因为艺术家可以创造想法并且实现艺术创作,就像程序员设计并实现一个小型软件系统一样。然而,对于较大型的软件系统,“程序员像建筑师一样”的类比可能更加合适。虽然建筑师设计建筑结构,但是将实现留给其他人(因为从逻辑上讲,通常一个人不可能建造一座建筑物)。在计算机学科中,那些设计系统而由他人来实现的人,通常被称为分析师。
建筑师会对一个项目进行大规模的创造性控制。例如,建筑师在设计一座漂亮的建筑物时,会定义它的外观、使用什么材料,以及建筑工人要遵循什么样的指导原则,但是不负责建造建筑物本身。建筑师可能会监督建筑物的建造过程(很像分析师会审查其他人添加到软件系统中的模块),但是不会自己使用锤子或者操作起重机。
这种比喻似乎并不适用于小型项目,但是如果允许个人“更换帽子(更换角色)”,那么就说得通了。也就是说,在项目的第一阶段,程序员可以戴上建筑师或者分析师的帽子来设计系统,然后他们会换掉帽子,戴上编码人员的帽子来实现系统。
“程序员像建筑师一样”相比于“程序员像艺术家一样”,增加了验证和安全措施的特点。当艺术家画一幅画、谱写一段音乐,或者雕刻一个物体时,通常不会担心这个作品是否符合除他们自己之外的任何要求。而且,他们不必担心这些艺术作品会对生命或者财产造成任何伤害 。但是,建筑师必须考虑物理现实和一个糟糕的设计可能会导致伤害的事实。“程序员像建筑师一样”的说法,为程序员这个身份增加了个人责任、审查(测试)和安全性等要求。
1968年举行的一次北约会议,挑战了优秀程序员是天生的,而不是后天培养的观念。正如在本书的前言中所提到的,世界正面临着一场软件危机——人们对新的软件应用程序的需求,比培训程序员开发软件的速度还要快。因此,北约主办了1968年的会议,创造了软件工程这个术语,来描述如何通过将工程理论应用到计算机编程的蛮荒世界中,以求解决问题。
工程师们感兴趣的是如何用低成本、高收益的方法来解决实际问题,其中包括设计成本和生产成本。由于这个原因,再加上工程专业已经存在很长一段时间(特别是机械工程和化学工程),因此积累了许多可以将工程师工作流水线化的流程和制度。
在当今的许多工程领域,工程师的任务都是从一些较小的、预先设计好的构件模块开始的,逐渐构建出一个大型系统。想要设计一个计算机系统的电子工程师,不会从设计一些特定的晶体管或者其他小部件开始;相反,他们会优先使用已经设计好的CPU、内存单元和I/O设备,然后将它们组合成一个完整的系统。同样,机械工程师可以使用预先设计好的桁架和基座来设计一座新的桥梁。设计的重用性是工程专业的一个重要标志。这是一个能够尽快产出生产上安全、可靠、具有功能性,以及低成本、高收益的设计的关键因素。
软件工程师还会遵循一套定义良好的流程和策略,通过组合许多较小的、预定义的系统来构建一个大型系统。事实上,电气和电子工程师学会(IEEE)对软件工程的定义如下:
使用一种系统化的、有理可寻的、可量化的方法来开发、运行和维护软件,即工程化在软件方面的应用。
工匠的比喻方式介于艺术家和工程师之间。这里强调的是程序员作为个体的想法,即软件工匠的比喻认为人很重要。在一个问题上投入更多的人员和增加限制性约束不会产生更高质量的软件,但是更好地培训个人,并让他们运用自己的天赋和技能,反而可能做到这一点。
传统工匠的开发过程与软件工匠的开发过程有相似之处。和所有的工匠一样,软件工匠也是从学徒或者实习生做起的。程序员学徒在另一位工匠的密切指导下进行工作。在掌握了相关技术之后,程序员学徒就变成了一个熟练工,通常在软件工匠的监督下与其他程序员团队一起工作。最终,随着程序员个人编程技能的提升,他也有机会成为一个大师级工匠。
工匠是对于那些希望成为卓越程序员的最好比喻。我将在后面的“软件匠艺”一节中来讨论这个比喻。
为了写出卓越的代码,你必须首先理解是什么让代码变得卓越的。在写代码时,你需要使用最好的工具、编码技术、开发流程和策略。此外,你必须不断学习新的知识,并且通过改进开发流程来提高软件质量。这就是我们需要了解不同的软件开发方法、理解软件产品并选择最佳方法的重要原因。
你需要努力学习如何写出卓越的代码,然后再努力去做到这一点。一个优秀的软件开发人员会从刚才讨论的各种特性中取其精华,去其糟粕。我们将上面的各类比喻总结如下:
● 卓越的艺术家会通过不断实践技能来发展自己的才华。他们会通过发散思维来探索新的表达信息的方式。
● 卓越的建筑师知道如何通过标准化组件,基于现有的设计来创建自定义的对象。他们了解成本上的限制、安全问题、各种需求,以及为了确保产品可靠运行而进行过度设计的必要性。卓越的建筑师能够理解形式和功能之间的关系,以及如何满足客户的需求。
● 卓越的工程师能够认识到一致性的好处。他们会编写文档,将所有开发步骤自动化,从而避免在流程中遗漏某些步骤。与建筑师一样,工程师会鼓励重用现有的设计,来提供更健壮、更经济的解决方案。软件工程学可以提供有效的过程和策略,来帮助克服项目中的个人局限性。
● 卓越的工匠需要在大师的指导下训练和实践技能,最终的目标是成为大师级工匠。这个比喻强调了个体的重要性,比如他们解决问题和组织的能力。
软件工程自20世纪60年代末出现以来,已经取得了绝对性的成功。今天,很少有专业的程序员还认为编码是一件很难的事情,但是在编码刚刚出现时,对每个人都是一个很大的挑战。现代的程序员认为理所当然的一些概念——例如结构化编程、适当的程序布局(如缩进)、注释和良好的命名方式,这些都来自对软件工程的不断研究。事实上,对软件工程几十年来的研究已经极大地影响了现代的编程语言和其他编程工具。
软件工程已经存在很长时间,并且对计算机编程的各个方面都产生了巨大的影响,以至于许多人认为软件工程师就是指计算机程序员。当然,任何专业的软件工程师也应该是一个有编程能力的计算机程序员,但是编程仅仅是软件工程的一小部分。软件工程主要会涉及经济和项目管理方面。有趣的是,那些真正负责管理项目、维护时间进度表、选择软件方法论等的人,往往并不是软件工程师,他们被称为项目经理、项目负责人,以及其他暗示权威地位的头衔。同样,我们称为软件工程师的人实际上并不是做软件工程的——他们只是编写由那些真的软件工程师(项目经理和项目负责人)所规定的代码。也许,这就是大家对“软件工程”这个词理解如此混淆的原因。
似乎没有一个对软件工程的定义能够满足所有人的要求。不同的人会对这个词添加自己的“理解”,使得他们的定义与其他的定义略有(或者有很大的)不同。之所以将这本书命名为《软件工程化》,是因为我想避免在软件工程这个词上添加另一个定义,让大家更加困惑。顺便提醒一下,IEEE组织对软件工程这个词的定义如下:
使用一种系统化的、有理可寻的、可量化的方法来开发、运行和维护软件,即工程化在软件方面的应用。
而最初的软件工程定义,也是我经常使用的定义如下:
软件工程是一门研究如何开发和管理大型软件系统的学问。
这里的关键词是大型。在软件工程的发展过程中,以前大部分系统都是国防系统或者类似的项目,所以软件工程被等同于大型系统也就不足为奇了。虽然IEEE的定义可以适用于几乎任何规模的系统,但是因为软件工程的大部分研究都是关于如何开发非常大型的系统的,所以我更喜欢第二个定义。
注意 :为了避免与软件工程的“通用定义”相混淆,我使用了一个更专业的术语——个人软件工程,来描述那些个体程序员在小型项目或者大型项目的其中一小部分工作中使用的流程和方法。我的目的是希望告诉计算机程序员,他们应该相信的是软件工程的本质,而不是任何与编写出卓越的代码无关的细节。
当我们谈到软件开发时,每个人对“大型”的定义其实都完全不同。计算机科学专业的本科生可能会认为,一个包含了几千行源代码的程序就是一个大型系统。而对于波音公司(或者其他大型公司)的项目经理来说,一个大型系统应该包含超过一百万行代码。根据我最近一次的统计(虽然那也是很久以前了),微软Windows操作系统(OS)的源代码已经超过5000万行,没有人会怀疑Windows是一个大型系统!
因为传统的软件工程定义通常只适用于大型软件系统,所以我们需要对大型(和小型)的软件系统给出一个合理的定义。尽管代码行数(Lines of Code,LOC)是软件工程师经常用来描述软件系统大小的一个度量指标,但是它其实非常不准确,方差几乎在两个数量级 。本书会经常使用LOC或者千行代码(KLOC)这两个度量指标。但是,将一个正式的定义建立在这样一个糟糕的度量指标上,并不是一个好主意,这样会降低定义的准确性。
一个小型项目指的是一个普通程序员能够在合理的时间内(一般不超过两年)完成的项目。一个中型项目指的是一个人无法在合理的时间内完成,但是一个由2~5个程序员组成的小团队可以完成的项目。一个大型项目则需要一个较大的程序员团队(超过5个成员)来完成。
就LOC而言,一个小型项目会包含50~100 KLOC,一个中型项目会在50~1000 KLOC(约100万行代码)范围内,而一个大型项目少则包含500~1000 KLOC。
小型项目管理起来很简单。因为小型项目不需要程序员之间的交流,也不需要程序员与外部环境之间的交互,所以生产力几乎完全取决于程序员个人的能力。
中型项目会带来新的挑战。由于多个程序员在项目中一起工作,沟通可能会成为一个问题,但是又因为团队足够小,所以这种开销还是可管理的。不过,因为团队之间的互动需要额外的资源支持,所以会增加编写每一行代码的成本。
大型项目需要一个大型的程序员团队。团队成员之间的沟通和其他开销经常会消耗掉每个工程师50%的生产力。因此,对于大型项目而言,有效的项目管理至关重要。
软件工程涉及成功管理需要大型程序员团队完成的项目的各种方法、实践和策略。遗憾的是,个人或者小型团队的良好实践经验无法被扩展到大型团队中,而大型项目的方法、实践和策略也无法被应用到中小型项目中。在大型项目中应用良好的实践经验,通常会给中小型项目带来不合理的开销,从而降低那些小团队的生产力。
让我们来仔细看看不同规模项目的一些优点和缺点。
在小型项目中,一个软件工程师会全面负责系统设计、实现、测试、调试、部署和文档编写。在这样的项目中,单独的工程师要比中型项目或者大型项目中的一个工程师负责更多的任务。但是这些任务都很小,因此是可管理的。因为小型项目只有一个人来执行各种任务,所以这个程序员必须拥有各种技能。个人软件工程涵盖了一个开发人员在小型项目中所有的行为活动。
小型项目可以最有效地利用工程资源。工程师可以使用最有效的方法来解决问题,因为他们不必与其他工程师就项目达成一致意见。工程师还可以优化他们花在每个开发阶段的时间。在一个结构化的软件设计过程中,需要花费相当多的时间来记录开发过程,但是当项目中只有一个程序员时,这样做就没有意义了(尽管在产品的生命周期后期,可能需要另一个程序员来编写代码)。
小型项目存在的缺点和陷阱在于,工程师必须能够处理所有不同的任务。许多小型项目失败(或者开发成本太高)的原因,就是工程师没有接受过完成整个项目的适当培训。与其他的目标相比,《编程卓越之道》系列图书的主要目标就是教会程序员如何正确地完成一个小型项目。
在中型项目中,个人软件工程会涉及一个工程师要负责的各个方面,通常包括系统组件的设计、实现(编码)和编写该模块的文档。通常,他们还负责测试各个组件(单元测试),然后整个团队来测试整个系统(集成测试)。通常,有一个工程师(项目负责人或者主程序员)会负责整个系统设计,以及项目部署。根据项目的不同,可能会需要一个技术作者来编写系统文档。因为在一个中型项目中,工程师之间是共享任务的,所以可以形成专业分工,而且项目不要求每个工程师都有能力执行所有任务。主程序员可以指导那些缺乏经验的人,从而保证整个项目的质量。
在一个小型项目中,工程师可以看到项目的整体情况,并且可以根据其对项目的理解来优化某些行为活动。但是在一个大型项目中,工程师无法了解其所负责的任务以外的情况。中型项目则结合了这两种极端情况:个人既可以了解整个项目的大部分内容,并以此来调整其实现方式,也可以专门研究系统的某些方面,而不会被其他细节牵扯大量的精力。
在大型项目中,不同的团队成员都有其专门的角色,从系统设计到实现、测试、文档编写、系统部署,以及系统优化和维护。与中型项目一样,在大型项目中,个人软件工程只涉及单个程序员所负责的行为活动。大型项目中的软件工程师通常只做很少的工作(例如,编码和单元测试),因此他们不需要具备小型项目中程序员所具备的广泛技能。
除了行为活动,项目的规模大小还会影响到工程师的生产力。在一个大型项目中,工程师会变得非常专业,并且专注于自己的专业领域,这使得他们能够比使用普通技术更有效地完成工作。但是,为了达到这种效果,在大型项目中必须使用一种通用的软件开发方法,如果其中一些工程师不喜欢这种方法,那么他们可能就没有那么高效了。
将工程领域的技术经验应用到软件开发中,然后以一种更加经济有效的方式来开发应用程序是可能的。但是,正如Pete McBreen在 Software Craftsmanship:The New Imperative 一书中所说的,软件工程最大的问题是假设“系统化的、有理可寻的、可量化的方法”是唯一合理的方法。事实上,他提出了一个非常好的问题,即是否有可能让软件开发变得系统化和可量化?在controlchaos网站上,McBreen这样写道:
如果一个流程可以被完全定义,你对它的所有事情都很清楚,这个流程就是可被设计的,重复运行该流程可以产生可预测的结果,那么这样的流程就被称为已定义流程,并且可以被自动化。如果你对一个流程中的所有事情都不完全清楚,即当你输入一堆东西时只知道大概会发生什么,并且不确定如何测量和控制结果,那么这样的流程就被称为经验性流程。
软件开发不是一个已定义流程,而是一个经验性流程。因此,软件开发不能被完全自动化,并且通常将工程领域的经验应用到软件开发中是很困难的。部分问题在于,实际的工程实现在很大程度上依赖于对现有设计的重用。尽管在计算机编程中也存在大量的重用,但是它比其他工程领域需要更多的定制化。
我们在本书的前言中介绍过软件工程的另一个重要问题,就是软件工程把软件工程师当作一种商品资源,项目经理可以随意地在项目中更换软件工程师,从而忽略了个人才能的重要性。这个问题并不是说工程技术没有价值,而是说管理层试图将它们统一应用到每个人身上,并且鼓励在软件开发中使用一些所谓的“最佳实践”。虽然这种方法可以产生高质量的软件,但是它限制了我们跳出思维定式,以及创造更好的实现方式的可能。
软件匠艺,是指一个程序员在编程大师的指导下训练和实践各种技能,立志于终身学习并成为最优秀的软件开发人员。按照软件匠艺的定义,一个程序员先要接受良好的教育,完成学徒阶段,再逐渐成为一个熟练的程序员,并努力开发出一款杰出的软件。
学院和大学为编程实习生提供了成为软件工匠的先决条件。如果实习过程能够让一个刚开始接触编程的人(实习生或者学徒),接触到和正规教育一样的信息和体验,那么这个实习过程也可以相当于一个正规教育。遗憾的是,很少有软件工匠有时间或者能力,从头开始培训一个学徒。他们忙于现实世界的项目开发,无暇顾及教给实习生他们所需知道的一切。因此,教育是通向软件匠艺之路的第一步。
此外,在学院或者大学接受正规教育有两个主要目的:首先,你必须学习那些自学时可能会跳过的计算机科学知识;其次,你要向世界证明你有能力完成一个重要的承诺。尤其是当你完成一个正式的计算机程序之后,就可以真正地开始学习软件开发了。
然而,无论是多么高级的大学学位,都不能自动让你成为一个软件工匠。一个拥有研究生学位的人,一开始也只能像本科生一样,作为一个实习生开始学习编程,但是他需要对计算机科学进行更深入、更专业的学习。拥有研究生学位的实习生,虽然其实习时间会短一些,但是他仍然需要经过大量的培训。
在学徒阶段,完成一个正式的计算机程序,是你开始学习如何成为一个软件工匠的第一步。一个典型的计算机程序会让你学会如何使用编程语言(语法和语义)、数据结构、编译器理论、操作系统等,但是它不会教你如何编写出超出第一学期或者第二学期《编程入门》课程范围的程序。学徒阶段会让你知道现实世界中的编程是什么。学徒阶段的目的是让你用所学的知识,通过各种不同的方式来解决问题,并且尽可能获得各种不同的经验。
学徒会向一个掌握了更高级编程技术的人学习。这个人可能是软件熟练工(见下一节内容),也可能是一个软件工匠。这个“师父”会给学徒分配任务,演示如何完成任务,并检查学徒的工作,在中途进行适当的纠正以完成难度更高的工作。最重要的是,学徒还要经常学习师父的程序——可以采用多种形式,包括测试、结构化浏览代码和调试。重要的一点是,学徒要学会如何维护师父编写的代码 。通过这样做,学徒们会一点点学会自学时永远无法掌握的编程技术。
如果一个学徒足够幸运,那么他将有机会跟随几个大师学习,并从他们那里学习到扎实的技术。在高级程序员的指导下,随着每个项目的完成,学徒期也接近尾声,并进入软件工匠路线的下一个阶段:软件熟练工。
从某种意义上说,学徒生涯永远不会结束。你应该经常留意新技术和新技巧。例如,所有在结构化编程中成长起来的软件工程师,都不得不学习面向对象编程。但是,在某种程度上,你会更频繁地使用已经掌握的技能,而不是不断开发新技能。这时,你就开始把自己的智慧传授给别人,而不是再向别人学习。之后,如果与你一起工作的“大师们”觉得你已经准备好,可以在没有帮助或者监督的情况下独自开发项目了,那么就是你成为软件熟练工的时候了。
软件熟练工会负责软件开发的大部分工作。顾名思义,他们通常会从一个项目转移到另一个项目,运用他们的技能来解决应用程序的各种问题。尽管软件开发人员的教育从未结束,但是软件熟练工更加关注应用程序开发,而不是学习如何开发应用程序。
软件熟练工要承担的另一项重要任务是培训新的软件学徒。他们会经常检查学徒们在项目中的工作,并与他们分享与编程有关的技术和知识。
软件熟练工会不断寻找可以改进软件开发过程的新工具和新技术。通过尽早采用新的(但是经过验证的)技术,他们始终会保持快速学习,并不断跟上当前的技术发展趋势,以免落后。他们会利用行业最佳实践为客户创造高效、经济的解决方案,这正是这一匠艺阶段的标志。软件熟练工的工作效率高、经验丰富,这正是大多数项目经理在组建团队时希望找到的软件开发人员类型。
成为大师级工匠的一种传统方法,就是创造一个杰作,一个足以让你在同行中脱颖而出的作品。一些(高端)软件杰作的例子包括VisiCalc 、Linux操作系统、vi和emacs文本编辑器。这些产品最初都是某一个人的创意,尽管后来有数十个或者数百个不同的程序员参与其中。杰作不一定要出名,例如Linux或者某些GNU工具。但是,你的同行必须认识到这个杰作是有用的并且创造性地解决了某个问题。杰作也不必是一段独立的原始代码。为某个操作系统编写一个复杂的设备驱动程序,或者用一些有效的方法扩展其他程序,这些都可能被称为杰作。杰作的目的是,让你有一个拿得出手的项目来告诉全世界:“我有能力开发真正的软件,所以请认真对待我!”。杰作让别人知道他们应该认真考虑你的观点,相信你所说的话。
一般来说,大师级工匠的责任是确定当前的最佳实践方式是什么,以及发明新的方式。最佳实践指的是完成某项任务最广为人知的方式,但是不一定是最好的方式。大师级工匠需要研究是否有更好的方式来设计应用程序,当某种新的技术或者方法论普及时,他们要了解其作用和效果,以及验证某种实践方式是否是最好的,并将该信息告诉其他人。
Steve McConnell在他的经典软件工程著作 Code Complete (《代码大全》)中声称,经验并不会像人们想象的那样重要:“如果一个程序员在一两年后还没有学会C语言,那么接下来的三年也不会有太大的区别。”接着他问道,“如果你已经工作了10年,那么你是有10年的工作经验,还是把1年的经验重复了10次?”McConnell甚至认为从书本中学习可能比积累编程经验更加重要。他认为,计算机科学领域变化如此之快,以至于一个有10年编程经验的人可能会错过这10年中所有伟大的研究成果,而这些成果正是新的程序员会接触到的。
你能编写出卓越的代码,并不是因为遵循了一系列规则。你必须自己下定决心,努力保证写出的代码真的很棒。如果你违反了一些众所周知的软件工程原则,那么肯定无法编写出卓越的代码,但是严格遵循这些规则也会带来同样的效果。一个经验丰富、细致入微的开发人员,或者说一个软件工匠,可以同时驾驭这两种方法,既会在需要时遵守既有的实践规范,也会在需要时勇于尝试不同的技术或策略。
遗憾的是,书本只能教给你这些规则和方法,但是创造力和智慧需要你自己去培养。这本书会教给你这些规则,并且向你建议何时可以考虑打破它们。但是,是否选择这样做,仍然要取决于你自己。
Andrew Hunt和David Thomas编写的 The Pragmatic Programmer ,Addison-Wesley Professional,1999年。
Brian W.Kernighan和Rob Pike编写的 The Practice of Programming ,Addison-Wesley Professional,1999年。
Pete McBreen编写的 Software Craftsmanship:The New Imperative ,Addison-Wesley Professional,2001年。
Steve McConnell编写的C ode Complete . 2nd ed ,Microsoft Press,2004年。
Rapid Development:Taming Wild Software Schedules ,Microsoft Press,1996年。
Robert S.Pressman编写的 Software Engineering,A Practitioner's Approach ,McGraw-Hill,2010年。