2. 对所完成代码的调试和测试,投入近一半的时间,比平常的安排多很多。
3. 容易估计的部分,即编码,仅仅分配了六分之一的时间。
通过对传统项目进度安排的研究,我发现很少项目允许为测试分配一半的时间,但大多数项目的测试实际上是花费了进度中一半的时间。它们中的许多项目,在系统测试之前还能保持进度。或者说,除了系统测试,进度基本能保证2。
特别需要指出的是,不为系统测试安排足够的时间简直就是一场灾难。因为延迟发生在项目快完成的时候。直到项目的发布日期,才有人发现进度上的问题。因此,坏消息没有任何预兆,很晚才出现在客户和项目经理面前。
另外,此时此刻的延迟具有不寻常的、严重的财务和心理上的反应。在此之前,项目已经配置了充足的人员,每天的人力成本也已经达到了最大的限度。更重要的是,当软件用来支持其他的商业活动(计算机硬件到货,新设备、服务上线等等)时,这些活动延误出现即将发布前,那么将付出相当高的商业代价。
实际上,上述的二次成本远远高于其他开销。因此,在早期进度策划时,允许充分的系统测试时间是非常重要的。
空泛的估算
观察一下编程人员,你可能会发现,同厨师一样,某项任务的计划进度,可能受限于顾客要求的紧迫程度,但紧迫程度无法控制实际的完成情况。就像约好在两分钟内完成一个煎蛋,看上去可能进行得非常好。但当它无法在两分钟内完成时,顾客只能选择等待或者生吃煎蛋。软件顾客的情况类似。
厨师还有其他的选择:他可以把火开大,不过结果常常是无法“挽救”的煎蛋——一
面已经焦了,而另一面还是生的。
现在,我并不认为软件经理内在的勇气和坚持不如厨师,或者不如其他工程经理。但为了满足顾客期望的日期而造成的不合理进度安排,在软件领域中却比其他的任何工程领域要普遍得多。而且,非阶段化方法的采用,少得可怜的数据支持,加上完全借助软件经理的直觉,这样的方式很难生产出健壮可靠和规避风险的估计。
显然我们需要两种解决方案。开发并推行生产率图表、缺陷率、估算规则等等,而整个组织最终会从这些数据的共享上获益。
或者,在基于可靠基础的估算出现之前,项目经理需要挺直腰杆,坚持他们的估计,确信自己的经验和直觉总比从期望派生出的结果要强得多。
重复产生的进度灾难
当一个软件项目落后于进度时,通常的做法是什么呢?自然是加派人手。如图2.1至2.4所示,这可能有所帮助,也可能无法解决问题。
我们来考虑一个例子3。设想一个估计需要12个人月的任务,分派给3个成员4个月时间,在每个月的末尾安排了可测量的里程碑A、B、C、D(图2.5)。
现在假定两个月之后,第一个里程碑没有达到(图2.6)。项目经理面对的选择方案有哪些呢?
1. 假设任务必须按时完成。假设仅仅是任务的第一个部分估计不得当,即如图2.6所示,则剩余了9个人月的工作量,时间还有两个月,即需要4.5个开发人员,所以需要在原来3个人的基础上增加2个人。
2. 假设任务必须按时完成。假设整个任务的估计偏低,即如图2.7所示,那么还有18个人月的工作量以及2个月的时间,需要将原来的3个人增至9个人。
3. 重新安排进度。我喜欢P.Fagg,一个具有丰富经验的硬件工程师的忠告:“避免小的偏差(Take no small slips)”。也就是说,在新的进度安排中分配充分的时间,以确保工作能仔细、彻底地完成,从而无需重新确定时间进度表。
4. 削减任务。在现实情况中,一旦开发团队观察到进度的偏差,总是倾向于对任务进
行削减。当项目延期所导致的后续成本非常高时,这常常是唯一可行的方法。项目经理的相应措施是仔细、正式地调整项目,重新安排进度;或者是默默地注视着任务项由于轻率的设计和不完整的测试而被剪除。
月人124351234567 8
ABCD计划进度
图2.5
月人124351234567 8
ABCD落后1个月(剩余9人/月)
图2.6
月人124351234567 8
ABC(剩余18人/月)
D
图2.7
月人1243512345678ABCD5个编程人员7+人月培训结束
图2.8
前两种情况中,坚持把不经调整的任务在四个月内完成将是灾难性的。考虑到重复生成的工作量,以第一种为例(图2.8)——不论在多短的时间内,聘请到多么能干的两位新员工,他们都需要接受一位有经验的职员的培训。如果培训需要一个月的时间,那么三个人月将会投入到原有进度安排以外的工作中。另外,原先划分为三个部分的工作,会重新分解成五个部分;某些已经完成的工作必定会丢失,系统测试必须被延长。因此,在第三个月的月末,仍然残留着7个人月的工作,但此时只有5个有效的人月。如同图2.8所示,产品还是会延期,如同没有增加任何人手(图2.6)。
期望四个月内完成项目,仅仅考虑培训的时间,不考虑任务的重新划分和额外的系统测试,在第二个月末需要增添4个,而不是2个人员。如果考虑任务划分和系统测试的工作
量,则还需要继续增加人手。到那时所拥有的就不是3人的队伍,而是7人以上的团队;并且小组的组织和任务的划分在类型上都不尽相同,这已经不是程度上的差异问题。
注意在第三个月的结尾时,情况看上去还是很糟。除去管理的工作不谈,3月1日的里程碑仍未达到。此时,对项目经理而言,仍然存在着很强的诱惑——添加更多人力,结果往往会是上述循环的重复。这简直就是一种疯狂、愚蠢的做法。
前面的讨论仅仅是第一个里程碑估计不当的情况。如果在3月1日,项目经理做出了比较保守的假设,即整个估计过于乐观了,如图2.7所示。6个人手需要添加到原先的任务中。培训、任务的重新分配、系统测试工作量的计算作为练习留给读者。但是毫无疑问,重现“灾难”所开发出的产品,比没有增加人手,而是重新安排开发进度所产生的产品更差。
简单、武断地重复一下Brooks法则:
向进度落后的项目中增加人手,只会使进度更加落后。(Adding manpower to a late software project makes it later)
这就是除去了神话色彩的人月。项目的时间依赖于顺序上的限制,人员的数量依赖于单个子任务的数量。从这两个数值可以推算出进度时间表,该表安排的人员较少,花费的时间较长(唯一的风险是产品可能会过时)。相反,分派较多的人手,计划较短的时间,将无法得到可行的进度表。总之,在众多软件项目中,缺乏合理的时间进度是造成项目滞后的最主要原因,它比其他所有因素加起来的影响还要大。
外科手术队伍(The Surgical Team)
这些研究表明,效率高和效率低的实施者之间具体差别非常大,经常达到了数量级的水平。
- SACKMAN, ERIKSON和GRANT1
These studies revealed large individual differences between high and low performers, often by an order of magnitude.
- SACKMAN, ERIKSON, AND GRANT1
在计算机领域的会议中,常常听到年轻的软件经理声称他们喜欢由头等人才组成的小型、精干的队伍,而不是那些几百人的大型团队,这里的“人”当然暗指平庸的程序员。其实我们也经常有相同的看法。
但这种幼稚的观点回避了一个很困难的问题——如何在有意义的时间进度内创建大型的系统?那么就让我们现在来仔细讨论一下这个问题的每一个方面。
问题
软件经理很早就认识到优秀程序员和较差的程序员之间生产率的差异,但实际测量出的差异还是令我们所有的人吃惊。在他们的一个研究中,Sackman、Erikson和Grand曾对一组具有经验的程序人员进行测量。在该小组中,最好的和最差的表现在生产率上平均为10:1;在运行速度和空间上具有5:1的惊人差异!简言之,$20,000/年的程序员的生产率可能是$10,000/年程序员的10倍。数据显示经验和实际的表现没有相互联系(我怀疑这种现象是否普遍成立。)
我常常重复这样的一个观点,需要协作沟通的人员的数量影响着开发成本,因为成本的主要组成部分是相互的沟通和交流,以及更正沟通不当所引起的不良结果(系统调试)。这一点,也暗示系统应该由尽可能少的人员来开发。实际上,绝大多数大型编程系统的经验显示出,一拥而上的开发方法是高成本的、速度缓慢的、不充分的,开发出的是无法在概念
上进行集成的产品。OS/360、Exec 8、Scope 6600、Multics、TSS、SAFE等等——这个列表可以不断地继续下去。
得出的结论很简单:如果一个200人的项目中,有25个最能干和最有开发经验的项目经理,那么开除剩下的175名程序员,让项目经理来编程开发。
现在我们来验证一下这个解决方案。一方面,原有的开发队伍不是理想的小型强有力的团队,因为通常的共识是不超过10个人,而该团队规模如此之大,以至于至少需要两层的管理,或者说大约5名管理人员。另外,它需要额外的财务、人员、空间、文秘和机器操作方面的支持。
另一方面,如果采用一拥而上的开发方法,那么原有200人的队伍仍然不足以开发真正的大型系统。例如,考虑OS/360项目。在顶峰时,有超过1000人在为它工作——程序员、文档编制人员、操作人员、职员、秘书、管理人员、支持小组等等。从1963年到1966年,设计、编码和文档工作花费了大约5000人年。如果人月可以等量置换的话,我们所假设的200人队伍需要25年的时间,才能使产品达到现有的水平。
这就是小型、精干队伍概念上的问题:对于真正意义上的大型系统,它太慢了。设想OS/360的工作由一个小型、精干的团队来解决。譬如10人队伍。作为一个尺度,假设他们都非常厉害,比一般的编程人员在编程和文档方面的生产率高7倍。假定OS/360原有开发人员是一些平庸的编程人员(这与实际的情况相差很远)。同样,假设另一个生产率的改进因子提高了7倍,因为较小的队伍所需较少的沟通和交流。那么,5000/(10×7×7)= 10,他们需要10年来完成5000人年的工作。一个产品在最初设计的10年后才出现,还有人会对它感兴趣吗?或者它是否会随着软件开发技术的快速进步,而显得过时呢?
这种进退两难的境地是非常残酷的。对于效率和概念的完整性来说,最好由少数干练的人员来设计和开发,而对于大型系统,则需要大量的人手,以使产品能在时间上满足要求。如何调和这两方面的矛盾呢?
Mills的建议
Harlan Mills的提议提供了一个崭新的、创造性的解决方案2,3。Mills建议大型项目的每一个部分由一个团队解决,但是该队伍以类似外科手术的方式组建,而并非一拥而上。
也就是说,同每个成员截取问题某个部分的做法相反,由一个人来进行问题的分解,其他人给予他所需要的支持,以提高效率和生产力。
简单考虑一下,如果上述概念能够实施,似乎它可以满足迫切性的需要。很少的人员被包含在设计和开发中,其他许多人来进行工作的支持。它是否可行呢?谁是编程队伍中的麻醉医生和护士,工作如何划分?让我们继续使用医生的比喻:如果考虑所有可能想到的工作,这样的队伍应该如何运作。
外科医生。Mills称之为首席程序员。他亲自定义功能和性能技术说明书,设计程序,编制源代码,测试以及书写技术文档。他使用例如PL/I的结构化编程语言,拥有对计算机系统的访问能力;该计算机系统不仅仅能进行测试,还存储程序的各种版本,以允许简单的文件更新,并对他的文档提供文本编辑能力。首席程序员需要极高的天分、十年的经验和应用数学、业务数据处理或其他方面的大量系统和应用知识。
副手。他是外科医生的后备,能完成任何一部分工作,但是相对具有较少的经验。他的主要作用是作为设计的思考者、讨论者和评估人员。外科医生试图和他沟通设计,但不受到他建议的限制。副手经常在与其他团队的功能和接口讨论中代表自己的小组。他需要详细了解所有的代码,研究设计策略的备选方案。显然,他充当外科医生的保险机制。他甚至可能编制代码,但针对代码的任何部分,不承担具体的开发职责。
管理员。外科医生是老板,他必须在人员、加薪等方面具有决定权,但他决不能在这些事务上浪费任何时间。因而,他需要一个控制财务、人员、工作地点安排和机器的专业管理人员,该管理员充当与组织中其他管理机构的接口。Baker建议仅在项目具有法律、合同、报表和财务方面的需求时,管理员才具有全职责任。否则,一个管理员可以为两个团队服务。
编辑。外科医生负责产生文档——出于最大清晰度的考虑,他必须书写文档。对内部描述和外部描述都是如此。而编辑根据外科医生的草稿或者口述的手稿,进行分析和重新组织,提供各种参考信息和书目,对多个版本进行维护以及监督文档生成的机制。
两个秘书。管理员和编辑每个人需要一个秘书。管理员的秘书负责项目的协作一致和非产品文件。
程序职员。他负责维护编程产品库中所有团队的技术记录。该职员接受秘书性质的培训,承担机器码文件和可读文件的相关管理责任。
所有的计算机输入汇集到这个职员处。如果需要,他会对它们进行记录或者标识。输出列表会提交给程序职员,由他进行归档和编制索引。另外,他负责将任何模型的最新运行情况记录在状态日志中,而所有以前的结果则按时间顺序进行归档保存。
Mills概念的真正关键是“从个人艺术到公共实践”的编程观念转换。它向所有的团队成员展现了所有计算机的运作和产物,并将所有的程序和数据看作是团队的所有物,而非私人财产。
程序职员的专业化分工,使程序员从书记的杂事中解放出来,同时还可以对那些杂事进行系统整理,确保了它们的质量,并强化了团队最有价值的财富——工作产品。上述概念显然考虑的是批处理程序。当使用交互式终端,特别是在没有纸张输出的情况下,程序职员的职责并未消失,只是有所更改。他会记录小组程序和私有工作拷贝之间的更新,依然控制所有程序的运行,并使用自己的交互式工具来控制产品逐步增长的完整性和有效性。
工具维护人员。现在已经有很多文件编辑、文本编辑和交互式调试等工具,因此团队很少再需要自己的机器和机器操作人员。但是这些工具使用起来必须毫无疑问地令人满意,而且需要具备较高的可靠性。外科医生则是这些工具、服务可用性的唯一评判人员。他需要一个工具维护人员,保证所有基本服务的可靠性,以及承担团队成员所需要的特殊工具(特别是交互式计算机服务)的构建、维护和升级责任。即使已经拥有非常卓越的、可靠的集中式服务,每个团队仍然要有自己的工具人员。因为他的工作是检查他的外科医生所需要的工具。工具维护人员常常要开发一些实用程序、编制具有目录的过程库以及宏库。
测试人员。外科医生需要大量合适的测试用例,用来对他所编写的工作片段,以及对整个工作进行测试。因此,测试人员既是为他的各个功能设计系统测试用例的对头,同时也是为他的日常调试设计测试数据的助手。他还负责计划测试的步骤和为测试搭建测试平台。
语言专家。随着Algol语言的出现,人们开始认识到大多数计算机项目中,总有一两个乐于掌握复杂编程语言的人。这些专家非常有帮助,很快大家会向他咨询。这些天才不同于外科医生,外科医生主要是系统设计者以及考虑系统的整体表现。而语言专家则寻找一种简洁、有效的使用语言的方法来解决复杂、晦涩或者棘手的问题。他通常需要对技术进行一些研究(两到三天)。通常一个语言专家可以为两个到三个外科医生服务。
以上就是如何参照外科手术队伍,以及如何对10人的编程队伍进行专业化的角色分工。
如何运作
文中定义的开发团队在很多方面满足了迫切性的需要。十个人,其中七个专业人士在解决问题,而系统是一个人或者最多两个人思考的产物,因此客观上达到了概念的一致性。
要特别注意传统的两人队伍与外科医生——副手队伍架构之间的区别。首先,传统的团队将工作进行划分,每人负责一部分工作的设计和实现。在外科手术团队中,外科医生和副手都了解所有的设计和全部的代码。这节省了空间分配、磁盘访问等的劳动量,同时也确保了工作概念上的完整性。
第二,在传统的队伍中大家是平等的,出现观点的差异时,不可避免地需要讨论和进行相互的妥协和让步。由于工作和资源的分解,不同的意见会造成策略和接口上的不一致,例如谁的空间会被用作缓冲区,然而最终它们必须整合在一起。而在外科手术团队中,不存在利益的差别,观点的不一致由外科医生单方面来统一。这两种团队组建上的差异——对问题不进行分解和上下级的关系——使外科手术队伍可以达到客观的一致性。
另外,团队中剩余人员职能的专业化分工是高效的关键,它使成员之间采用非常简单的交流模式成为可能。 外科医生管理员秘书编辑秘书副手程序职员工具维护人员测试人员语言专家
图3.1:10人程序开发队伍的沟通模式
Baker的文章3提出了专一的、小规模的测试队伍。在那种情况下,它能按照所预期的进行运作,并具有良好的效果。
团队的扩建
就目前情况而言,还不错。然而,现在所面临的问题是如何完成5000人年的项目,而不是20或30人年规模的系统。如果整个工作能控制在范围之内,10人的团队无论如何组织,总是比较高效的。但是,当我们需要面对几百人参与的大型任务时,如何应用外科手术团队的概念呢?
扩建过程的成功依赖于这样一个事实,即每个部分的概念完整性得到了彻底的提高——决定设计的人员是原来的七分之一或更少。所以,可以让200人去解决问题,而仅仅需要协调20个人,即那些“外科医生”的思路。
对于协调的问题,还是需要使用分解的技术,这在后续的章节中会继续进行讨论。在这里,可以认为整个系统必须具备概念上的完整性,要有一个系统结构师从上至下地进行所有的设计。要使工作易于管理,必须清晰地划分体系结构设计和实现之间的界线,系统结构师必须一丝不苟地专注于体系结构。总的说来,上述的角色分工和技术是可行的,在实际工作中,具有非常高的效率。
贵族专制、民主政治和系统设计(Aristocracy, Democracy, and System Design)
大教堂是艺术史上无与伦比的成就。它的原则既不乏味也不混乱 真正达到了风格上的极致,完成这件作品的艺术家们,完全领会和吸收了以往的成功经验,也完全掌握了他们那个时代的技术,而且在应用的时候做到了恰如其分,绝不轻率,也绝不花哨。
正是Jean d ‘Orbais构思了建筑的整体设计,这个设计得到了后继者的认同,至少在本质上如此。这也是这个建筑如此和谐统一的原因之一。
- 兰斯大教堂指南1
This great church is an incomparable work of art. There is neither aridity nor confusion in the tenets it sets forth. . . . It is the zenith of a style, the work of artists who had understood and assimilated all their predecessors ’ successes, in complete possession of the techniques of their times, but using them without indiscreet display nor gratuitous feats of skill.
It was Jean d ‘Orbais who undoubtedly conceived the general plan of the building, a plan which was respected, at least in its essential elements, by his successors. This is one of the reasons for the extreme coherence and unity of the edifice.
- REIMS CATHEDRAL GUIDEBOOK1
概念一致性
绝大多数欧洲的大教堂中,由不同时代、不同建筑师所建造的各个部分之间,在设计或结构风格上都存在着许多差异。后来的建筑师总是试图在原有建筑师的基础上有所“提高”,以反映他们在设计风格和个人品味上的改变。所以,在雄伟的哥特式的教堂上,依附着祥和的诺曼第风格十字架,它在显示上帝荣耀的同时,展示了同样属于建筑师的骄傲。
与之对应的是,法国城市兰斯(Reims)在建筑风格上的一致性和上面所说的大教堂形
成了鲜明的对比。设计的一致性和那些独到之处一样,同样让人们赞叹和喜悦。如同旅游指南所述,风格的一致和完整性来自8代拥有自我约束和牺牲精神的建筑师们,他们每一个人牺牲了自己的一些创意,以获得纯粹的设计。同样,这不仅显示了上帝的荣耀,同时也体现了他拯救那些沉醉在自我骄傲中的人们的力量。
对于计算机系统而言,尽管它们通常没有花费几个世纪的时间来构建,但绝大多数系统体现出的概念差异和不一致性远远超过欧洲的大教堂。这通常并不是因为它由不同的设计师们开发,而是由于设计被分成了由若干人完成的若干任务。
我主张在系统设计中,概念完整性应该是最重要的考虑因素。也就是说为了反映一系列连贯的设计思路,宁可省略一些不规则的特性和改进,也不提倡独立和无法整合的系统,哪怕它们其实包含着许多很好的设计。在本章和以下的两章里,我们将解释在编程系统设计中,这个主题的重要性。
如何得到概念的完整性?
这样的观点是否要有一位杰出的精英,或者说是结构设计师的贵族专制,和一群创造性天分和构思被压制的平民编程实现人员?
如何避免结构设计师产出无法实现、或者是代价高昂的技术规格说明,使大家陷入困境?
如何才能与实现人员就技术说明的琐碎细节充分沟通,以确保设计被正确地理解,并精确地整合到产品中?
获得概念的完整性
编程系统(软件)的目的是使计算机更加容易使用。为了做到这一点,计算机装备了语言和各种工具,这些工具实际上也是被调用的程序,受到编程语言的控制。使用这些工具是有代价的:软件外部描述的规模大小是计算机系统本身说明的十倍。用户会发现寻找一个特定功能是很容易的,但相应却有太多的选择,要记住太多的选项和格式。
只有当这些功能说明节约下来的时间,比用在学习、记忆和搜索手册上的时间要少时,易用性才会得到提高。现代编程系统节省的时间的确超过了花费的时间,但是近年来,随着越来越多的功能添加,收益和成本的比率正逐渐地减少。而IBM 650使用的容易程度总萦绕
在我的脑际,即使该系统没有使用汇编和任何其他的软件。
由于目标是易用性,功能与理解上复杂程度的比值才是系统设计的最终测试标准。单是功能本身或者易于使用都无法成为一个好的设计评判标准。
然而这一点被广泛地误解了。操作系统OS/360由于其复杂强大的功能被它的开发者广为推崇。功能,而非简洁,总是被用来衡量设计人员工作的出色程度。而另一方面,PDP-10的时分系统由于它的简洁和概念的精干被建造它的人员所称道。当然,无论使用任何测量标准,后者的功能与OS/360都不在一个数量级。但是,一旦以易用性作为衡量标准,单独的功能和易于使用都是不均衡的,都只达到了真正目标的一半。
对于给定级别的功能,能用最简洁和直接的方式来指明事情的系统是最好的。只有简洁(simplicity)是不够的,Mooers的TRAC语言和Algol 68用很多独特的基本概念达到了所需的简洁特性,但它们并不直白(straightforward)。要表达一件待完成的事情,常常需要对基本元素进行意料不到的复杂组合。而且,仅仅了解基本要素和组合规则还不够,还需要学习晦涩的用法,以及在实际工作中如何进行组合。简洁和直白来自概念的完整性。每个部分必须反映相同的原理、原则和一致的折衷机制。在语法上,每个部分应使用相同的技巧;在语义上,应具有同样的相似性。因此,易用性实际上需要设计的一致性和概念上的完整性。
贵族专制统治和民主政治
概念的完整性要求设计必须由一个人,或者非常少数互有默契的人员来实现。
而进度压力却要求很多人员来开发系统。有两种方法可以解决这种矛盾。第一种是仔细地区分设计方法和具体实现。第二种是前一章节中所讨论的、一种崭新的组建编程开发团队的方法。
对于非常大型的项目,将设计方法、体系结构方面的工作与具体实现相分离是获得概念完整性的强有力方法。我亲眼目睹了它在IBM的Stretch计算机和360计算机产品线上的巨大成功。但同时我也看到了这种方法在360操作系统的开发中,由于缺乏广泛应用所遭受的失败。
系统的体系结构(architecture)指的是完整和详细的用户接口说明。对于计算机,
它是编程手册;对于编译器,它是语言手册;对于控制程序,它是语言和函数调用手册;对于整个系统,它是用户要完成自己全部工作所需参考的手册的集合2。
因此,系统的结构师,如同建筑的结构师一样,是用户的代理人。结构师的工作,是运用专业技术知识来支持用户的真正利益,而不是维护销售人员所鼓吹的利益。
体系结构同实现必须仔细地区分开来。如同Blaauw所说的,“体系结构陈述的是发生了什么,而实现描述的是如何实现3。”他举了一个简单的例子——时钟。它的结构包括表面、指针和上发条的旋钮。当一个小孩知道了时钟的外表结构,他很容易从手表或者教堂上的时钟辨认时间。而时钟的实现,描述了表壳中的事物——很多种动力提供装置中的一种,以及众多控制精度方案的一种。
例如,在System/360中,一个计算机的结构可以用9种不同的模型来实现;而单个实现——Model 30的数据流、内存和微代码实现——可以用于4种不同的体系结构:System/360计算机、拥有224个独立逻辑子通道的复杂通道、选择通道以及1401计算机4。
同样的划分方法也适用于编程系统。例如,美国的Fortran IV标准,是多种编译器所遵循的体系结构标准。该体系结构下有多种可能的实现:以文本为核心、以编译器为核心、快速编译和优化以及侧重语法的实现。相类似的,任何汇编语言和任务控制语言都允许有多种编译器或调度程序的实现。
现在让我们来处理具有浓厚感情色彩的问题——贵族统治和民主政治。结构师难道不是新贵?他们一些智力精英,专门来告诉可怜的实现人员如何工作?是否所有的创造性活动被那些精英单独占有,实现人员仅仅是机器中的齿轮?难道不能遵循民主的理论,从所有的员工中搜集好的创意,以得到更好的产品,而不是将技术说明工作仅限定于少数人?
最后一个问题是最简单的。我当然不认为只有结构师才有好的创意。新的概念经常来自实现者或者用户。然而,我一直试图表达,并且我所有的经验使我确信,系统的概念完整性决定了使用的容易程度。不能与系统基本概念进行整合的良好想法和特色,最好放到一边,不予考虑。如果出现了很多非常重要但不兼容的构想,就应该抛弃原来的设计,对不同基本概念进行合并,在合并后的系统上重新开始。
至于贵族专制统治的问题,必须回答 “是”或者“否”。就必须只能存在少数的结构师而言,答案是肯定的,他们的工作产物的生命周期比那些实现人员的产物要长,并且结构
师一直处在解决用户问题,实现用户利益的核心地位。如果要得到系统概念上的完整性,那么必须控制这些概念。这实际上是一种无需任何歉意的贵族专制统治。
第二个问题的答案是否定的,因为外部技术说明的编制工作并是比具体设计实现更富有创造性,它只是一项性质不同的创造工作而已。在给定体系结构下的设计实现,同样需要同编制技术说明一样的创造性、同样新的思路和卓越的才华。实际上,产品的成本性能比很大程度上依靠实现人员,就如同易用性很大程度上依赖结构师一样。
有很多行业和领域中的案例让人相信纪律和规则对行业是有益的。实际上,如同某艺术家的格言所述,“没有规矩,不成方圆。”最差的建筑往往是那些预算远远超过起始目标的项目。巴赫曾被要求每周创作一篇形式严格的歌剧,但这似乎并没有被压制他的创造性。并且,我确信如果Stretch计算机有更严格的限制,那么该计算机会拥有更好的体系结构。就我个人意见而言,System/360 Model 30预算上的限制,完全获益于Model 75的体系结构。
类似的,我观察到外部的体系结构规定实际上是增强,而不是限制实现小组的创造性。一旦他们将注意力集中在没有人解决过的问题上,创意就开始奔涌而出。在毫无限制的实现小组中,在进行结构上的决策时,会出现大量的想法和争议,对具体实现的关注反而会比较少5。
我曾见过很多次这样的结果,R.W.Conway也证实了这一点。他在Cornell的小组曾编制PL/I语言的编译器。他说:“最后我们的编译器决定支持不经过改进和增强的语言,因为关于语言的争议已经耗费了我们所有的时间和精力。6”
在等待时,实现人员应该做什么?
几百万元的失误是非常令人惭愧的经验,但同时也是让人记忆深刻的教训。当年我们计划和组织编写OS/360外部技术说明的那个夜晚,常常重现在我的脑海。我和体系结构经理、程序实现经理一起制订计划进度,并确认责任分工。
体系结构经理拥有10个很好的员工,他声称他们可以书写规格说明,并出色地完成任务。该任务需要10个月,比所允许的进度多了3个月。
程序实现经理有150人。他认为在体系结构队伍的协助下,他们可以准备技术说明,并且能按照时间进度,完成高质量的、切合实际的说明。此外,如果光是由体系结构的团队
承担该工作,他的150人只能坐在那儿干等10个月,无所事事。
对此,体系结构的经理的反应是,如果让程序实现队伍来负责该工作,结果不会按时完成,仍将推迟3个月,而且质量更加低劣。我将工作分派给了程序实现队伍,其结果也确实如此。体系结构经理的两个结论都得到了证实。另外,概念完整性的缺乏导致系统开发和修改上要付出更昂贵的代价,我估计至少增加了一年的调试时间。
当然,很多因素造成了那个错误的决策,但决定性因素是时间进度和让150名编程人员进行工作的愿望。而它也正是我想强调的致命危险。
当建议由体系结构的团队来编写计算机和编程系统的所有外部技术说明时,编程人员提出了三个反对意见:
该说明中的功能过于繁多,而对实际情况中的成本考虑比较少
结构师获得了所有创造发明的快乐,剥夺了实现人员的创造力
当体系结构的队伍缓慢工作时,很多实现人员只能空闲地坐着等待
这些问题中的第一个确实是一项危险,在下一章中我们将讨论这个问题,但其他的两个问题都是一些简单而纯粹的误解。正如我们前面所看到的,实现同样是一项高级别的创造性活动。具体实现中创造和发明的机会,并不会因为指定了外部技术说明而大为减少,相反创造性活动会因为规范化而得到增强,整个产品也一样。
最后一个反对意见是时间顺序和阶段性上的问题。问题的简要回答是,在说明完成的时候,才雇用编程实现人员。这也正是在搭建一座建筑时所采用的方法。
在计算机这个行业中,节奏非常快,而且常常想尽可能地压缩时间进度,那么技术说明和开发实现能有多少重叠呢?
如同Blaauw所指出的,整个创造性活动包括了三个独立的阶段:体系结构(architecture)、设计实现(implementation)、物理实现(realization)。在实际情况中,它们往往可以同时开始和并发地进行。
例如,在计算机的设计中,一旦设计实现人员有了对手册的模糊设想,对技术有了相对清晰的构思以及拥有了定义良好的成本和目标时,工作就可以开始了。他可以开始设计数据流、控制序列、大体的系统划分等等。同时,还需要选用工具以及进行相应的调整,特别
是记录存档系统和设计自动化系统。
同时,在物理实现的级别,电路、板卡、线缆、机箱、电源和内存必须分别设计、细化和编制文档。这项工作与体系结构及设计实现并行进行。。
在编程系统的开发中,这个原理同样适用。在外部说明完成之前,设计实现人员有很多的事情可以做。只要有一些最终将并入外部说明的系统功能雏形,他就可以开始了。首先,必须设定良好定义的时间和空间目标,了解产品运行的平台配置。接着,他可以开始设计模块的边界、表结构、算法以及所有的工具。另外,还需要花费一些时间和体系结构师沟通。
同时,在物理实现的级别,也有很多可以着手的工作。编程也是一项技术,如果是新型的机器,则在库的调整、系统管理以及搜索和排序算法上,有许多事情需要处理7。
概念的完整性的确要求系统只反映唯一的设计理念,用户所见的技术说明来自少数人的思想。实际工作被划分成体系结构、设计实现和物理实现,但这并不意味着该开发模式下的系统需要更长的时间来创建。经验显示恰恰相反,整个系统将会开发得更快,所需要的测试时间将更少。同工作的水平分割相比,垂直划分从根本上大大减少了劳动量,结果是使交流彻底地简化,概念完整性得到大幅提高。
画蛇添足(The Second-System Effect)
聚沙成塔,集腋成裘。
- 奥维德
Adde parvum parvo magnus acervus erit.
[Add little to little and there will be a big pile.]
- OVID
如果将制订功能规格说明的责任从开发快速、成本低廉的产品的责任中分离出来,那么有什么样的准则和机制来约束结构师的创造性热情呢?
基本回答是结构师和建筑人员之间彻底、仔细和谐的交流。另外,还有很多值得关注的、更细致的答案。
结构师的交互准则和机制
建筑行业的结构设计师使用估算技术来编制预算,该估算技术会由后续的承包商报价来验证和修正。承包商的报价总会超过预算。接下来,设计师会重新改进他的预算或修订设计,调整到下一期工程。他也可能会向承包商建议,使用更加便宜的方法来实现设计。
类似的过程也支配着计算机系统和计算机编程系统的结构师。相比之下,他有能在设计早期从承包商处得到报价的优势,几乎是只要他询问,就能得到答案。他的不利之处常常是只有一个承包商,后者可以增高或降低前者的估计,来反映对设计的好恶。实际情况中,尽早交流和持续沟通能使结构师有较好的成本意识,以及使开发人员获得对设计的信心,并且不会混淆各自的责任分工。
面对估算过高的难题,结构师有两个选择:削减设计或者建议成本更低的实现方法——挑战估算的结果。后者是固有的主观感性反应。此时,结构师是在向开发人员的做事方式
提出挑战。想要成功,结构师必须
牢记是开发人员承担创造性和发明性的实现责任,所以结构师只能建议,而不能支配;
时刻准备着为所指定的说明建议一种实现的方法,同样准备接受其他任何能达到目标的方法;
对上述的建议保持低调和平静;
准备放弃坚持所作的改进建议;
一般开发人员会反对体系结构上的修改建议。通常他是对的——当正在实现产品时,某些特性的修改会造成意料不到的成本开销。
自律——开发第二个系统所带来的后果
在开发第一个系统时,结构师倾向于精炼和简洁。他知道自己对正在进行的任务不够了解,所以他会谨慎仔细地工作。
在设计第一个项目时,他会面对不断产生的装饰和润色功能。这些功能都被搁置在一边,作为“下一个”项目的内容。第一个项目迟早会结束,而此时的结构师,对这类系统充满了十足的信心,熟练掌握了相应的知识,并且时刻准备开发第二个系统。