内容


Rational Edge

是什么让软件变得如此之难?

Comments

系列内容:

此内容是该系列 # 部分中的第 # 部分: Rational Edge

敬请期待该系列的后续内容。

此内容是该系列的一部分:Rational Edge

敬请期待该系列的后续内容。

illustration同传统工程项目相比,软件项目通常拥有一个乏善可陈的记录。1 有大量的报告证明许多软件项目严重超出预算、未能如期交付、甚至被取消。即使是那些最终走出大门成为产品的项目,在大多数情况下,也将不得不花费相当多的时间来进行后期的修补和更正。

本文考察了一些使软件开发变得困难和容易发生错误的关键特性。我将主要通过对比软件建设和那些传统的、有形的、物理的工程系统建设(例如建筑、桥梁、轮船和飞行器)来探讨这一主题。我想补充的一点是,我在这里所描述的困难是针对于使用 IBM® Rational® 方法进行迭代开发的。关于这一方法请参见本发行物的相关部分。但是,即使你已经通过应用迭代开发技术在软件项目中获得成功,我相信探求那些技术如此关键的原因也同样是很有用处的。

记录

随着项目规模的增长,软件项目越发变得容易失败了。项目规模越庞大,越是容易超期、超支、甚至是被取消。从根本上说,最初的对成本和工期的评估往往都会失效。这使得一些人相信导致软件工业失败的根本原因就是对大型软件开发工程不够充分和有效的管理。然而,即使今天的许多软件项目无论在预算、工期、参与人员等等方面都十分宏大,但是实际上,与传统的工程项目(如桥梁或者水坝)相比起来,它们仍然显得渺小。

鉴于传统工程项目(有些传统项目的规模比目前最大的软件项目的规模还要大上几个数量级)在计划和预算方面远远好于软件项目的记录,我们有理由推断,软件工业中所存在的问题可以通过应用那些传统工程中所使用的项目管理的技术和方法来减少。问题是,表面上看起来显而易见的相似点可能在本质上截然不同。有许多关键的不同点使得软件项目较之传统的工程项目更加难以制订计划、进行评估、依照计划顺利完成。

软件项目中的主要问题

商业软件项目2往往超出预算和工期(经常是极端地):预算和日程由于一两个未听说的因素而超出限度。许多陷入严重问题的项目在后期被取消,从而导致重大的经济损失,错失了商机。一旦软件系统基本上可以使用时,它们又经常在运行时出现故障。典型的缺陷包括功能缺失、差劲的运行效率、以及系统漏洞。对于大多数软件系统和应用程序来说,从最初的交付使用到最终的运行稳定并且基本达到设计要求,需要经历一段相当长的时间,并且需要克服许多挫折,付出相当大的努力。因此,软件项目在计划和实际之间存在很大的不一致性。

与之相比,传统的工程项目(即使是那些时间跨度达到许多年、预算达到数十亿美元、参与人员达到数千人的大型项目)通常在完成时同最初的设计方案非常近似,无论是在工期上还是在预算上都是如此。因此,这种不一致性在这些项目中被限定在一个相当小的范围内。

问题来了:为什么无法对软件工程进行精确的评估呢?

设计与生产

软件项目和传统工程项目的一个关键区别在于花费在“创造性”阶段(即规划及设计)和生产制造阶段的时间、经费的比例是不同的。在传统工程中,大部分时间和经费用于生产,而用于规划和设计阶段的仅占一小部分。例如,对于一个房屋建筑项目,或者一个汽车新模型的开发,“创造性”部分只涉及有限数量的规划师和设计师,仅耗费一两个月的时间,然而与之对应的是,实际的生产阶段要涉及数千人(甚至是机器人),而且要耗费数年的时间。

另一方面,对于软件项目,规划设计同生产之间的关系不仅是反转的,而且实际上是趋向无穷的:因为软件花费在生产制造上的成本几乎等于零(见下文),几乎所有开销都来自创造性部分的工作流程——即软件的发明和设计。

我们可以将传统工程项目定义为“生产型项目”,而将软件项目定义为“设计型项目”。

生产型项目的特性

典型的生产型项目的特点是具备相当标准的任务、步骤和方法。此外,生产型项目以操作标准化的建筑部件(例如建筑物的预制建设元素)为特点。生产型项目非常适合于机械化和自动化,而且它们可以被预见管理,传统上采用科学管理的 Tayloristic 方法,利用这种方法,每一项工作、任务和步骤都可以被详细的描述和精确的测量,从而实现时间和经费的最优化。这些类型的项目很好的定义了机械化的步骤和任务,也很容易对成本进行优化——例如,搬迁或者外包给低成本的供应商。

设计型项目的特性

设计型项目则完全不同。设计项目所涉及的工作和任务远非机械的,而且不容易采用 Tayloristic 或者其他类型的预测方法。相反,设计型项目要求长时间的发现和发明,涉及一群非常熟练的、有能力合格完成任务的技术人员。开发者必须在问题和解决方案领域中具备深厚和广博的知识,他们必须有能力完成智力工作,并且必须有能力在团队沟通和协作中表现良好。设计型项目同样也需要不同的方法来进行设计和管理。

“工厂方法”对于软件开发来说注定要失败

许多大型的软件开发组织看不到或者不承认设计型项目和生产型项目之间的差异,他们试图采用那些适用于生产制造型项目的经营和管理方法,但是这些方法并不适用于软件项目。因为软件项目是非机械化的、不平凡的、完全依赖于参与人员的素质。

相比生产型项目而言,设计型项目要求一种根本上不同的方法。成本最终无法通过雇佣廉价的“人力自动化”来保持低位。不能通过向项目增加更多的“自动化”、或者要求他们更快的工作来缩短上市时间。所涉及的大多数任务对于将其机械化来说简直太复杂。设计型项目要想获得成功,所有参与人员必须具备丰富的知识、熟练的技巧、广泛的软件工程领域的工作经验(从理解问题领域到客户需求),执行平台的所有细节。此外,他们还需要被激发。

试图将传统的生产型项目中的经营和管理方法应用到软件项目中——重点放在成本降低和工作流程的标准业务最优化——并没有真正理解一个典型的设计型项目所涉及到的复杂性,从而导致许多软件开发组织对于他们的项目的关键分析和创造性工作流程投资的方式太过稀少。例如,很少系统的使用原型、建模、或者方针。这往往导致规划和设计变得不充分,执行变得麻烦和棘手,而且费用比计划的要多得多,这是因为在后期需要大量的“补丁”。“又快又差”的分析和设计、接着是“跳转到执行”、然后是“试验并且出错”,这一典型的模式在基于质量控制的传统工程项目中是完全不能想象的,而且这种没有首先确保规划和设计的正确性而导致的开销也是完全被禁制的。很少有传统工程领域的组织能够处理大量的由于发生故障而被召回的产品。不幸的是,这一模式在软件开发领域中非常普遍:“我们将在此后的版本中修补这一问题。”

很少有人将重点放在负责软件开发的真正的创新、创造和艰苦方面的工作人员的素质上面,而这些方面恰恰包含了一个典型的软件开发项目的大多数工作流程。即使一些软件项目(特别是那些处于维护阶段的项目)可以由一支水平一般的团队成功完成,但是任何新的开发努力若想获得成功,都将依靠一群技术非常熟练的工作人员。

设计型项目的计划需要不断的进行调整以便处理许多未知的变化。对于开发任何软件来说,精确估计开发过程所需要的努力是不可能的,特别是在初期阶段。

“支持”与“做”原则

下面的讨论,对于区别任何一个开发或者建设项目所涉及的两种类型的活动:“支持”和“做”,很有用处。前者处理传统项目管理类型,例如计划、日程安排、人员安排、评估、监控和报告;后者包括处理系统实际建设的所有活动,即设计和建造所涉及的各种不同的“工艺”,例如分析、设计、建设和执行。

支持型的学科

表面上,似乎软件项目拥有同传统工程项目一样的支持活动和工作流程。诸如需求搜集、项目组织和管理、人员安排、评估、监控和报告等等活动都出现在这两种类型的项目中。有无数的方法和工具可以用来支持这些活动,并且传统的工程项目拥有一个行之有效的、或多或少按计划完成的记录。

在很长一段时间里,软件行业同样也将重点放在了支持型学科上面。针对软件行业,有太多特定的步骤、方法和工具。并且大多数组织已经进行了相当大的投入用于建设他们自己的支持型学科。

尽管如此,很少有软件项目按照计划执行;最初的和后来的评估都会走样,我们需要频繁的中心制定计划,不幸的是这些计划往往也都过于乐观。

那么到底是什么使得软件项目的计划如此之难呢?

做事情的学科

抽象与具体

显然,我们可以在做事情学科中发现软件工程和传统工程之间最明显的区别。即使它们之间有一些相似之处——特别是在规划这一工作流程中,软件工程和典型的传统工程一样,都使用模型——然而,除此之外的其他活动非常的不同:传统学科的工程师往往从事于标准化的物理实体,而软件工程师则专注于无形的、抽象的事物。与焊接金属片不同的是,软件工程师靠编写代码将原料有机的结合在一起。与建造物理模型或者使用数学模型不同的是,软件设计者靠编写高层的代码来建立“模型”。与通过施加压力来测试建筑砖块的结构完整性不同的是,软件设计者靠编写代码来测试他们的程序。不管工作流程如何,软件设计者终日从事于无形的、抽象的和灵活的事物——纯智力劳动。

建设的方法

软件系统与传统系统的不同之处之一就在于建设或者执行的方法。物理系统在相当大的程度上是通过组装标准化部件而建成的。而软件系统则不同,它根本上说是通过发现、发明和创造新的组件而得到的。即使软件行业一直以来都追求可重用性、接口标准化和组件化,但是收效甚微。

物理系统

物理系统——一座建筑、一座桥梁、一辆汽车、一架飞行器、一艘轮船、或者一台计算机——存在于物理世界。除了占据三维空间,它们的“原子结构”(即组成这些系统的单个成分或部分)都来源于其他的物理实体。如果不考虑它们究竟是作为物理系统还是作为某一个组成部分的话,它们共有着一些通用的物理属性,比如重量、长度、宽度、高度等等。它们同样还拥有确切性:我们能够看、触碰、感觉和移动它们,我们还可以通过物理世界提供给我们的法则轻易的使用和试验它们。

我们还可以为这些物理系统创造比例模型,并且采用那些真实系统所遵守的物理法则来对这些模型进行试验和测试,从而获得有价值的数据以便帮助我们建造真实的事物。部分原因在于,掌管物理系统的法则以及物理系统本身都从根本上遵循着连续性特性。这使得这些系统的行为可以被适度的预测、计量和测算,而软件系统而不然,它们本质上是不连续的(离散的),输入时的一个微小的改变就将导致输出时巨大的不同。

人们非常熟悉物理系统,无需成为一名工程师就可以懂得物理系统和法则的实用性。从我们降生的那一天起,我们就在感受和处理着物理世界。我们在第一次摔倒的时候就学会了重力原则,我们在小的时候就感受到了许多其他的物理法则。

软件系统

而软件则不然,它不同于物理的、有形的事物。相反,软件是一个纯粹抽象的、概念化的事物,它仅仅存在于人们的脑海里。诚然,我们可以将软件的原子结构(即单个的位)放置在媒体(比如磁盘驱动器或者光盘)上,从而创造出它的物理表现,但是,软件系统本身是纯粹概念画的和无形的东西。因此,它不受制于任何一条掌管物理系统的法则。这种缺少法则或者第一原则的事实使得软件系统更像是一门艺术而非科学。对于软件开发来说,任何有用的分析方法都是没有什么用处的。相反,大多数软件开发在根本上都是基于综合的方法的。经验、技巧和“最佳实践”的应用成为决定成败的唯一要素。

此外,无形性大大限制了我们“试验”软件系统的可能性——我们不能触碰它、感觉它、移动它——我们能做的只有思考它。

缺少第一定律(规律)

对于软件来说,没有能够掌控创造和组装的第一定律或者规律。相反,传统工程(比如建筑)则是被良好定义的和广为人知的物理法则约束着。这种缺失使得软件具有很强的灵活性,也就是说,对于你能够用软件做什么并没有多少约束,这是一件好事。不幸的是,缺少法导致了几乎接近于无限程度的自由,而且软件固有的灵活性也意味着软件专业人员在预先约束如何开展工作方面几乎不能得到任何帮助。一位建筑工程师在他的设计里会非常关注物理世界的法则,但是对于软件工程师来说,情况大不相同:他们所从事的工作本质上是不受任何预先约束的,唯一能够约束设计的只有那些我们自己施加的影响,以及我们所使用的方法、步骤和工具。

在某种意义上,创造软件与撰写小说非常近似。作者可以自由的撰写任何类型的故事,他受到的约束仅仅是作者的想象以及叙述时所必须交代的事实。此外,作者必须在他的头脑中建造故事的框架结构,并且确保故事的设计和执行同整个框架结构相一致。作品的质量在很大程度上取决于作者是否成功的将故事的细节统一在总体的框架结构之下。

作者建造的抽象系统仅仅存在于他的脑海里,它的物理表现(书)仅仅是为了方便的保存和发行的一种手段。这一点同软件的情形非常相似。

系统的边际成本

传统工程系统有着显著的边界成本。举例来说,即便已经成功建造了一座桥梁,若要在建造一座同样的桥梁还是要花费同第一座桥梁一样的费用。这一点与软件有着很大的不同。对于软件来说,创造一个已经存在的系统的副本,边界成本几乎为零。事实上,软件的边界成本的不存在性产生了传统工程与软件工程之间另外两个关键的区别:

  • 许多软件系统解决那些以前从来没有遇到的独特问题。
  • 有这样一种强烈的倾向:试图对现有的软件系统进行超出其能力的扩充。

实际上,上述两点其实是同一个问题的两个方面:由于软件的边界成本为零,所以相关组织非常倾向于使用先前的系统作为基础来解决新问题,也就是说,扩展并且修正老的系统来处理新的问题。在一定程度内,这是一种很好很有效的方法,但是如果超出一定的范围的话,就将最终导致问题频出、框架结构的迅速崩溃,并且使得后期的扩展和维护变得不可能。

其次,由于利用现有的代码来处理相似的但却是扩展的系统这一做法非常具有诱惑性,但其余的软件系统实际上需要从零开始去创造,并且需要处理先前系统的问题死角,这就要求该组织将其现有的技术、方法和工具拉伸到极限。那些第一次的项目同纯粹的研究项目之间具有很多相似之处,它们非常难以评估和预测结果。对于软件项目来说,这种对边界技术不断工作的趋势,是源于现代数字技术看似永不停止的稳定增强的能力,就像将各个组织将要试图利用软件要做的事放进信封里一样。此外,摩尔定律导致的另一个结果就是我们的基础(所使用的平台)永远是不稳定的,它们在持续的变化,这就要求我们的软件开发项目以同样的速率跟着改变。因此,软件开发团队必须学会如何生存,并且处理好这个任何事情都在不断变化的动态的世界。5.

灵活性——是福还是祸?

软件固有的灵活性,结合数字技术持续发展的动力,使得我们可以应用软件不断的解决那些从来没有遇到过的问题。由于灵活性,我们可以将软件塑造成任何形式从而处理几乎所有的问题。灵活性将我们使用软件所能完成的工作扩展为接近无穷。不幸的是,灵活性同样也是软件项目出现问题的罪魁祸首之一,这是因为它同样适用于“如何”进行软件工程这一问题。也就是说,软件不仅可以被塑造为不同的形式,而且能够以任意方式执行这一塑造工作。由于软件几乎不受任何约束的限制,所以所能采取的方式在数量上几乎是无穷的。因此,软件开发组织几乎可以无限可能的选择方法、工具和步骤,而且往往在同一个组织内部存在着许多种不同的工作方式。

以此类推,对比一下有些建筑使用 Lego,而有些建筑则使用 Play-Doh。即使我们能够将单个的 Lego 砖块用几乎无数种方式结合起来构成无限种“系统”,我们也仍然受到 Lego 框架结构及其固有原则所提供的严格法则的约束,约束我们如何将 Lego 砖块放在一起。同样的情形也存在于物理系统之中。另一方面,Play-Doh 同软件非常近似,它们不仅可以被建造成任何一种结构,而且允许建造者以任意方式对其进行操作,几乎不对“如何”操作 Play-Doh 进行限制。

需求预测和评估

为了精确预测和评估项目的工期、耗力等指标,所有涉及到的任务和步骤必须不仅是确定和安排好的,而且需要在若干个方面(例如工期、困难度、资源消耗、和依赖程度)可以被精确的计量。基本上,精确的预测和评估要求一套现有的算法,或者一个拥有有限数目的明确步骤的分步解决问题的程序。对于传统工程来说,它们具有大量典型的建筑或者类似系统的经验,在人们熟知的物理法则下,典型的人物和步骤是人所共知的,并且可以相对精确的完成评估工作。然而,对于软件项目(尤其是第一次性的项目)而言,这些参考数据是不存在的。大量的可应用的分析或者定量的方法也是不存在的。

,即便我们可以采用不同的测量方式,例如代码行数、类的数量、函数指针的数量、系统漏洞的数量,等等,软件还是缺乏一种定义良好的原子结构。问题是,这些测量方式在衡量努力程度方面既不是原子的,也不是可比较的。也就是说,用同一种语言编写的序列 A 和 B 都有10行代码,但是它们的复杂程度和困难程度可能根本无法相提并论。系统漏洞也是如此,一些狡猾的漏洞的发现和更正比起另外一些漏洞来说所付出的努力简直不在一个数量级上。但是,我们确实无法实现识别那些漏洞是最狡猾的。

评估和预测对于软件项目来说变成了猜想,只有保守的估价和先前的经验能够在实践中减少变数。这同纯粹的研究项目非常相似,在获得成功之前,许多种不同的方法被尝试并且被抛弃。

已经被证明的是,单一个体的软件开发者的生产力之间的差异非常巨大。同一个开发团队中不同个体之间的生产力可以相差许多个数量级。

此外,由于软件自身固有的灵活性,我们能够随心所欲的建造系统,这就进一步增加了精确评估问题的困难程度。

所有这些因素综合在一起,使得估计和预测不够准确。本质上,全面准确地对项目或任务进行预测和评估,要求采用科学管理中的 Tayloristic 方法,而这一方法仅适用于琐碎的,机械的任务。基于以上讨论的原因,典型的软件项目远未琐碎的或机械的。

总结和结论

软件很难,这是因为:

  • 软件项目是设计型项目,而不是生产型项目。
  • 由于软件是纯粹的中间件,软件开发更多的是一门艺术或者工艺,而不是一门科学或者工程学科,所以软件开发中的“做”的原则难以运行、管理和衡量。不同个体间生产力的不同非常巨大。
  • 软件缺乏法则和第一性原则。
  • 软件缺乏一个可度量的标准单位。
  • 鉴于软件的灵活性,软件项目中“支持”的原则(计划、评估、预测和观察)非常困难。
  • 摩尔定律使得软件的基础日新月异——软件没有一个“永久”的运行平台。

即使我们将软件工程看作“仅仅是另外一种工程学科”,然后据此推断软件可以使用和传统工程一样的经营、管理和工程原则来对软件进行开发,但还是有许多独特的特性使得软件和软件开发不仅特殊,而且较之传统的工程项目更加难以评估和监控。

软件开发有其固有的特性,它存在于一个仅仅由摩尔定律所掌控的动态的世界里。在相当长的一段时间里,它始终会更像是一门艺术而非科学。我们只有承认软件是不同的,并且理解由此而产生的各种差异,才有希望处理好软件开发中的各种问题。

任何把软件开发当作是另一种形式的传统工程的企图通常都不会带来预期的结果。我们只有很好地理解了是什么使软件变得不同,才可以着手解决软件开发中的特定问题。迭代开发、建模、需求管理,以及利益攸关方“尽早-经常”的参与其中等等,都是提供给软件团队的技术。开发者将认识到这种关键的差异,并且寻找一条新的前进道路。

注释

1 至少考虑到日程的话,所有为奥运会而建设的项目都可以称之为成功工程项目的范例——据我所知,所有的奥运会都是如期开幕的。另一个成功的范例是 Sears Tower,它花费1.6亿美元,60个转包商参与其中,最高峰时工人数量达到2400人。更多的信息请参见 http://skyscraperpage.com/cities/?buildingID=5

2 有趣的是,有证据显示,非商业的软件项目(即使是那些非常大型的项目,如 Eclipse 开源项目或者 GNU/Linux 项目) 比起完全商业化的软件项目来,拥有更好的记录。

3 汽车工厂装配生产线是一个很好的例子。现在大多数任务是由机器人而不是人来完成的。

4http://en.wikipedia.org/wiki/Scientific_management

5 Panta Rei


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Rational
ArticleID=261742
ArticleTitle=Rational Edge: 是什么让软件变得如此之难?
publish-date=10152007