作者:Winston W. Royce 博士
译者:Seaborn Lee 李小波
审校:Lance Zhang 张宁宁
简介
我将要描述我个人的视⻆,关于管理大型软件开发。我在过去 9 年中有过不同的任务,大部分涉及软件包开发,为航天飞机制定任务计划,命令和升空后分析。在这些任务中,我经历了不同程度的成功,包括在时间和成本范围内达到可运行的状态。通过我的经历,我得出了一些「偏⻅」,我将在这次演示中分享其中的一部分。
计算机程序开发职能对于任何计算机程序的开发,与规模和复杂度无关,都有两个基本的步骤。第一步是分析,第二步是编码。如 图一所示。
对于那些开发成本足够小,且最终产品的使用者与开发者是同一群人时(即那些仅供内部使用的计算机程序),这类特别简单的实现概念是所需要的全部步骤。这也是大多数 客户乐意支付的开发成本,因为两个步骤都涉及真正的创造性工作,直接为最终产品的可用性做贡献。一个制造大型软件系统的实现计划,如果也仅仅包含这两步的话,那么将注定要失败。还有很多其他的开发步骤是必须的, 它们不像分析和编码一样直接贡献到最终产品上,并且还抬升了开发成本。客户工作人员常常不愿意为它们买 单,开发人员也不愿落实它们。管理的主要功能是让两边都接受这些概念,并且在开发人员这方贯彻执行。
一个更加宏伟的软件开发方法如图二所示。
分析和编码依然在图中,但是在那之前要经过两个层次的需求分析,并在中间插入了程序设计环节,后面紧跟着测试环节。这些环节从分析和编码中分离出来作为单独的环节,是因为它们执行的方式明显不同。为了最好地利用开发资源,必须单独地计划和分配资源。
图三描述了这种模式下的连续开发阶段之间的迭代关系。
步骤之间的顺序是基于如下概念:随着每一步的发展和设计的细化,前一个步骤和后一个步骤之间存着一个迭代关系,但是序列中较远的步骤间几乎不存在。这样的优势在于,随着设计继续进行,变更流程被缩小在可管理的范围内。在需求分析完成后的设计过程中的任何一点,都存在一个稳定的,清晰的,活动的基线,以便于在遇到不可预⻅的设计困难时可以返回。我们有一条有效的退路,以便最大程度上拯救并保存之前的工作成果。
我相信这个概念,但上面描述的这种实现方式有很大的风险并可能导致失败。图 4 呈现了这个问题。
与分析不同的是,测试是第一次可以体验到程序的时效性、存储、输入输出转换,等等。这些方面无法进行精确分析,举个例子,它们不像解数学物理中标准偏微方方程。但是,如果这些方面不能满足外部约束,总是需要进行大规模的重新设计。简单的八进制补丁或重写某部分独立的代码,并不能修正这一类难题。这些必须的设计变更,可能是如此颠覆性的,基于软件需求作出的设计所提供的各种原理都被推翻了,要么必须修改需求,要么必须对设计做大量的变更。实际上,开发过程回到了起点,因此成本和时间的超支是毋庸置疑的,甚至可能达到100%的超支。
必须注意的是,前面的讨论跳过了分析和编码阶段。当然,跳过这两个阶段而生产软件是不可能的,但通常这两步相对容易管理,而且对需求,设计和测试的影响也更小。在我的经验中,有完整的部⻔分析轨道力学,航天飞机姿态测量,有效载荷的活动的数学优化等等,但是当这些部⻔完成了他们困难复杂的工作后,后续的编码环节只涉及数行串行算法代码。如果在他们执行困难复杂的分析工作中犯了一些错误,也只需要对代码做一些微小的改动就能修复,不需要颠覆其他的开发基础。
不管怎样,我相信前面陈述的过程大体上是好的。后续的讨论,呈现五个附加的特性,必须添加到这个基本过程以消除大部分的开发⻛险。
第一步:先做程序设计图五展示了修正的第一步。
在软件需求生成阶段和分析阶段之间,插入了一个程序预设计阶段。这个过程会被批评,因为程序设计师被强制在初始软件需求没有经过任何分析的相对真空中设计程序。结果就是,相对于等到需求分析完成后再做设计,他的预先设计可能会错得离谱。这个批评有道理,但不在点子上。通过这种方法,程序设计师确保了软件不会因为存储,时效性,数据流量等原因失败。当在后续的阶段进行分析时,程序设计师必须对存储、时效性、运行等方面的约束进行分析,以这样一种方式,他可以感知所带来的后果。当他无可非议地要求更多的这类资源,为了实现他的方程,它必须被同时从他的分析师同胞那里一把抓起。在这种方式下,所有的分析师和程序设计师能贡献于有意义的设计流程,将找到最佳的执行时间和存储资源分配。如果可用的资源不足,或者初期运行设计是错的,在这个早期阶段就能识别到,并且需求和预设计可以在设计定稿、编码和测试开始之前重做。
这个过程是如何实现的呢?下面的步骤是必须的。1)由程序设计师开始设计过程,而不是分析师或程序员。
2)冒着犯错的⻛险也要进行设计,定义和分配数据处理模式。分配过程,功能,设计数据库,定义数据库过程, 分配执行时间,基于操作系统设计界面和处理模式,描述输入和输出过程,定义预操作程序。
3)编写系统概览文件,要可理解,信息丰富的并且是实时的。每一个工作人员都必须对系统有基本的理解。至少 一个人深入理解系统,部分来自于不得不编写系统概览。
第二步:把设计文档化在这个点上,很适合提出这个问题:“我们需要多少文档?”我个人的观点是“很多”。肯定比大多数程序员,分析师或者程序设计师们自己乐意写的要多。管理软件开发的第一条规则是,无情地强调对文档的需求。
偶尔,我也被叫去评审其他软件设计的进度。我的第一步是调查文档的状态。如果文档是严重缺失的,那么我 的第一个建议很简单。替换项目管理。停止一切与文档无关的活动。把文档完善到可接受的标准。没有非常高度的文档,管理软件开发是基本不可能的。举个例子,让我提供以下估算作为对比。要采购 500 万美元的硬件设备,我会期待一个 30 ⻚的规格说明,以提供足够的细节来控制采购。要采购 500 万美元的软件,我会期待差不多1500 ⻚的规格说明来达到相同的控制度。
为什么需要这么多文档?
1)每一个设计师,必须和接口设计师沟通,和他的经理沟通,也可能和客户沟通。口头的记录不够实在,不足以提供足够的基础来为接口或管理决策提供依据。可接受的文字描述强制设计师提供明确的位置和提供实在的完成的证据。它防止设计师隐藏在一月接一月的“已完成 90%”的现象。
2)在软件开发的早期阶段,文档是规格说明和设计。直到开始编码,这三个名词(文档,规格说明和设计) 指向同一个东⻄。如果文档不好,那么设计也不好。如果文档不存在,那设计也不存在,人们只思考和谈论设 计,有一些价值,但不多。
3)好文档真正的金钱价值,从开发流程中的测试阶段开始,并且持续为运行和重新设计提供价值。文档的价值可以被描述为三个每位项目管理者都要面对的具体场景,
a)在测试阶段中,有好的文档,管理者能够把工作人员的注意力集中在程序错误上。没有好的文档,每一个错误,无论大小,都会被一个人分析过,而这个人很可能就是一开始犯了这个错误的人,因为他是唯一理解编程领域的人。
b)在运行阶段中,有了好的文档,经理可以让专业的运行人员来运行程序,不仅更好地完成工作,还更便宜。没有好的文档,就只有构建这个软件的人才能运行它。相对而言,这帮人对运行的兴趣不大,也没有专⻔做运行的人做得好。必须指出,在运行场景下,如果出现挂起,首先挨骂的就是软件。不管是为了赦免软件, 还是平复指责,软件文档都必须清晰明了。
c) 在运行初期,当系统改进井然有序,好的文档让我们可以有效地重新设计,更新和改造某些领域。如果文档不存在,那么在重新设计时,通常整个已有的运行软件框架都得报废,哪怕是相对适度的改动。
图六展示了前文所述的各步骤对应的文档计划。
注意,这六个文档是在交付最终产品的过程中同步产生的,文档 1,3,4,5,6 是已更新和实时的。
第三步:做两遍
关于成功的第二条重要准则是围绕该产品是否完全原创的。如果正在谈论的是首次开发的计算机程序,那么对关键设计和运行领域范围内的关注就尤为重要,以至于最终交付给客户部署运行的版本,实际上是第二版。图七通过模拟来展示了该如何执行。
注意,它们是整个流程的缩影,占据整体成本中相对较小的时间周期。这项工作的性质可能会有巨大的不同, 主要取决于整体时间规模和要建模的关键问题领域的性质。如果整体工作是 30 个月,那么这个早期的试验模型应大约计划 10 个月。这个计划也可以利用相当正式的控制,文档过程等等。然而,如果整体工作量缩减到 12 个月,为了能够充分利用好主线开发,试验模型的周期也许也可以压缩到 3 个月。在这种情况下,工作人员必须具备一种广泛的能力。他们必须对分析,编码和程序设计有直觉。他们必须快速感知到设计的问题点,对此进行建模,找到可选方案,忽略不值得在这个时间点研究的设计的简单方面,最终得到一个无错误的程序。在任何一 个案例中,所有的点在于,拥有一个模拟的好处在于,那些只能靠主观判断的时效性,存储之类的问题,都可以得到精确的研究。如果没有模拟,项目经理只能被人为判断左右。有了模拟,他至少可以对关键假设进行试验,减少主观判断的范围。而相对估算毛重,完成成本和双赌赛马而言,在计算机编程这个领域,这种主观判断总是严重乐观的。
第四步:计划,控制和监控测试
毋庸置疑,项目资源的最大消耗是在测试阶段,无论是人力还是计算机计算时间,或者管理的判断。它也是金钱和进度⻛险最大的阶段。它出现在时间计划表的最后,如果⻛险真的发生的话,也没有什么退路了。
前面的三个建议,在分析和编码之前设计程序,完整地用文档记录,构建一个试验模型,都是旨在在进入测试阶段前发现和解决问题。然而,尽管做了前面那些,还是有一个测试阶段,还是有重要的工作要做。
图八列出一些测试的其它方面。在做测试计划时,我建议考虑如下几点:
1)测试过程的很多部分都得到了测试专家最好的处理,测试专家不需要贡献到原始设计中。如果有人争论说 只有设计师才能执行彻底的测试,因为只有他们才理解他们构建的东⻄,这肯定是一个文档没有做好的信号。依我看来,如果有好的文档,产品保证专家会把测试工作做得比设计师更好。
2)大部分明显的错误,可以很容易地通过肉眼检查来发现。任何一点分析和代码都应该指定一名没有参与之前分析和编码的人来肉眼检查一遍。他们应该能发现诸如缺少负号,丢了两个元素,跳转到了错误的地址等等可通过校对来发现的分析和编码错误。别用计算机来干这类工作,因为太贵了。
3)用某种数值检查来测试程序中的每一条逻辑路径,至少一遍。如果我是客户,我不会接受交付,直到这个过程被完成和认证。这个步骤能发现主要的编码错误。
这个测试过程听起来很简单,对于大型复杂计算机程序,要下决心用可控的输入值测试每一个逻辑路径相对困 难。实际上,还有人可能会说那是几乎不可能的。尽管如此,我还是坚持建议要对每一个逻辑路径做一次真实的检查。
4)消除了简单的错误后(它们总是占大多数,并且它们掩盖了大的错误),就该把软件移交到测试区域,以达到检验的目的。在合适的时机,合适的人手里,电脑本身就是最佳的检验设备。关键的管理决策是:什么时候是最佳时机?谁是合适的人?来做最终的检验。
第五步:客户参与
由于一些原因,软件设计要做的是,广泛的解释,尽管在前面已经达成了共识。用正式的方式让客户参与进来 是很重要的,这样就能让客户在最终交付前更早的时间点上投身进来。在需求定义和运行之间,给承包商完全的自由,就是在自找麻烦。图九表明需求定义之后的三个点,客户可以提供洞⻅,判断和承诺来支持开发工作。
总结图十总结了我认为要将一个充满⻛险的开发过程转型到可以提供预期产品的过程的五步。
我要强调的是,每一步都有成本。如果一个相对简单的流程,没有上面描述的复杂的五步,也能顺利交付,那显然这钱就花的冤枉了。然而,我的经验是,简单的方法从来没有在大型软件开发上成功过,填坑所耗费的努力和成本,如果用来资助上面描述的五步的话,将会绰绰有余。