2、渐入佳境的软件工业化
上面我对全球汽车工业生产方式的变迁做了一个简要的回顾,下面重新回到全球软件产业上来。回望诞生至今半个多世纪全球软件产业的发展,在产业规模迅速扩张的背后,软件的生产方式也像全球汽车工业一样发生了不少重大变迁。如今的软件产业发展,已表现出越来越明显的工业化和全球化的特征。
(1)个人英雄主义的作坊式软件开发
类似于全球工业从第一辆汽车诞生到福特T型车问世前的作坊式单件手工生产的时代,刚刚走过半个世纪风风雨雨的全球软件产业,在诞生之初也是手工作坊式的开发模式。中国老一辈的软件开发人员,应该都很熟悉这种软件开发模式。
回顾全球计算机工业的发展历史,全球最早的电子计算机,主要用于第二次世界大战最后阶段的军事战争中,当时的计算机中并未装载今天我们所说的软件。这些电子计算机需要程序员通过设置代表机器语言(0或1)的开关来输入指令和数据。程序员设置0/1开关的过程,主要依赖于程序员个人的智慧,这开创了手工作坊式软件开发的先河。冯•诺伊曼(John Von Neumann)是全球软件发展史上值得铭记的伟大人物,这位天才数学家在20世纪40年代中期提出了一种新的设想:可以在计算机内存储程序指令和数据,这样用户想要计算机执行特定操作时无需每次手动输入或者重新输入指令,这是计算机“存储程序”思想的开端。1949年,英国剑桥大学的EDSAC(电子存储自动计算机)第一次实现了“存储程序”,从而催生了全球软件产业的问世。
在全球软件产业发展初期,计算机是作为某些特殊领域的特殊人员的专用工具而存在的。这些计算机最初的使用者,其实就是今天所说的领域专家。他们具有所从事领域的专业知识,但又需要进行复杂而庞大的数学计算。这些领域专家,就像汽车工业作坊式生产时代技术娴熟的工匠一样,往往具备极其出色的计算数学的知识和编程技巧,能根据自身或团队工作的需要,完成程序设计。在这样的背景下,所谓的软件,其实就等同于程序。这些计算程序的编写者和使用者,往往为同一个或同一组人。因此,这些程序基本上是专用软件,仅仅是使用者根据自身的需要编写的,不仅软件规模小,而且其地位也完全是辅助性的,他们只是帮助这些领域专家完成他们所从事的某项工程的辅助工具而已。这种特定的应用环境和背景,使当时的程序只要能帮助他们达到计算的目的即可。这些软件只属于个人或者仅仅在小团队中间交流即可,他们往往没有很好的结构和说明,别人看不懂,或者说也不需要别人看得懂。从软件早期发展过程不难看出,最初的软件应用具有高度专用性,使用者和软件开发者合二为一。这种特定的应用环境,促成了全球软件产业发展初期个体化软件开发的传统。这种传统对以后的软件产业发展产生了深远的影响。
随着信息技术的进一步发展,进入20世纪60年代,软件开发者和使用者开始逐步分离,以开发软件为职业的人和以软件为主营业务的公司开始大量出现。这些软件开发人员,多是训练有素的数学专家和电气工程师。同时,市场上对软件的商业化需求也越来越多,软件开始作为一种产品被越来越广泛的接受了。在市场需求的催生下,在美国诞生了全球第一批以软件生产为目的软件开发团队或独立软件公司。这些软件组织一般由少数几个或几十个人组成,专门根据客户定制要求来编写软件。这些软件组织继续沿袭开发者和使用者合二为一的时代所形成的个体化软件开发传统。这种作坊式生产模式下生产出来的软件,仍然是个人或少数几个人的头脑风暴的自由实现,其中充满了各种别人无法理解的编程技巧,软件项目的成败和进度往往系开发人员于一身。
显而易见,软件产业发展初期的作坊式软件开发模式,有着前面我们刚刚提到的汽车工业早期作坊式生产模式类似的弊端和问题。
首先,作坊式软件开发模式的效率非常低下。就像前面在汽车工业发展简史时我曾提到的,以单件手工制造汽车,由于每辆汽车都要从头开始进行设计和制造,这种“重新发明轮子”的过程,效率是非常低下的。同样,在这种作坊式软件生产模式下,每一个软件,几乎都要从头开始设计和开发,程序员所采用的开发工具也非常简单,开发过程中很少采用一些专业的工具,软件的复用性很差,生产效率也就非常低下。可以说,除了个人学习和组织学习所带来的经验曲线外,这种作坊式软件生产模式几乎不具备任何的规模经济效应。
其次,作坊式软件开发模式下,开发周期和预算很难控制,质量和性能也很难保证。由于在作坊式软件开发模式下,每一个软件几乎都要从头开始设计,并且一行一行从头编写代码,在软件项目启动初期,很难对软件项目的开发周期和预算做出准确估计,超过项目周期和项目预算是家常便饭。另外,在这些手工作坊式的软件开发模式下,几乎每一行代码都是从头开始编写的,每一个软件产品刚拿出来都是测试版本,必须由程序员反复进行各种复杂的测试和调试,逐步清除其中存在的各种错误(Debug),直到最后的功能设计达到用户的使用要求,并且能持续稳定地运行为止。这就类似于早期作坊式生产模式下生产出来的每一台汽车都是样车,质量和性能很不稳定,必须由专业机械师或专职司机亲自上路进行调试和修理,反反复复折腾几个回合才能让客户满意地开走一样。
最后,作坊式软件开发模式下开发出来的软件可读性和可维护性很差。类似于作坊式手工生产出来的各种汽车零件由于不采用相同的量具系统从而造成后续一系列的保养维修的问题一样,这些由不同程序员依靠个人技巧编写出来的计算机程序,并不具备相同的程序结构和规范。这时所谓的软件,往往只有源程序,而没有相关的使用说明和各种文档资料。这就造成软件的可读性和可维护性极差。程序员不仅难以读懂别人编写的软件,即使是同一个人编写的软件,在经过一段时间之后,自己也无法读懂。
简而言之,作坊式软件开发的弊端集中体现在极低下的效率、对项目进度和预算难以准确预估和控制、软件质量和性能不稳定、维护性差等几个方面。
到了20世纪60年代,随着软件数量的急剧膨胀和对软件的需求越来越复杂,作坊式模式下开发的软件维护的难度越来越大,导致越来越多的软件开发项目失败,这产生了众所周知的“软件危机”。“软件危机”的出现,促使学术界和产业界去深刻地反思当时的软件生产模式,寻找解决问题的出路。
(2)大规模软件开发的兴起和发展
作坊式软件生产模式的开发效率和质量,远远跟不上用户对软件的需求和软件规模的增长速度。软件业界开始寻求解决这一矛盾的出路。在此过程中,汽车工业从手工作坊式生产转向大规模流水线生产所带来的巨大效率提升,无疑让软件专家看到希望。不少软件专家也从建筑行业的发展中汲取了营养。软将工程的概念逐渐形成并普及。
汽车工业领域工业化所展示的巨大力量,为全球软件工业寻找出路提供了方向,将工程化原则引入软件开发项目,开始进入软件专家的视野。1967年,北大西洋组织(North Atlantic Treaty Organization,NATO)的一个研究小组创造了软件工程(software engineering)的概念,并于1968年在德国Garmisch召开的NATO软件工程会议上得以签署。软件工程概念的提出和确立,是全球软件发展史上一次重要的里程碑。正是从这次软件工程会议开始,越来越多的计算领域的研究者和实践者都相信,软件工程应当使用已建立的工程学科的基本原理和范式,用工程化的原则和方法来改变传统的作坊式软件开发,通过推进软件开发的工业化来解决“软件危机”。
随着软件工程概念和技术的发展,工程化原则、方法和工具开始广泛地应用于软件生产过程。回顾软件工程的发展历史,有几个重要的人物值得永远纪念,他们提出的很多颇有创见的想法,直至今天仍在卓有成效地指导着我们的软件开发实践。首先我要提起的是,荷兰学者E.W. Dijkstra,他在20世纪60年代末率先提出了结构化程序设计的概念,这就为现代程序设计方法学奠定了基础。结构化程序设计的出现和普及,让不同程序员在程序结构设计时遵循大致相同的原则。从更宽广的视角来看,结构化程序设计思想,类似于亨利•福特曾以宗教般的虔诚所追求的标准量具,它让不同的程序员有了大致可遵循的程序结构,这就极大地增强了程序的可读性和可维护性,为软件工业化生产奠定了基础。美国学者E.Youdon也是一个值得纪念的人物,他在20世纪70年代末提出了结构化分析方法,并有创见地指出分析和设计其实比编码更重要。这种强调需求分析、软件规约和设计的重要性的思想,在如今的大规模复杂程序设计中被证明是正确的,而且是极为重要的原则。此后,结构化方法学开始在软件业界备受关注并逐渐发展成为一种规范。早期程序设计中曾流行一时的Goto语句,开始被函数调用所代替,这些都有效地规范了程序结构,也为软件模块化复用打下了基础。
随后,软件瀑布模型的兴起为大规模软件开发提供了保障。软件生命周期(software life cycle)的经典瀑布模型,虽因过于死板和容易产生风险而受到学者和实践者的批评,但它首次明确区分了传统软件开发过程的几个主要阶段,即需求分析(requirement analysis)、设计(design)、编程(programming)、测试(testing)和维护(maintenace),这些阶段的划分为软件开发过程的标准化、劳动分工、软件项目管理和风险控制夯实了基础。
自20世纪70年代瀑布模型(waterfall model)诞生以后,软件开发过程(software process)开始受到普遍关注。为更好地实现对软件项目周期和项目预算的控制,在越来越多的大型软件企业中,软件开发过程开始基于软件工程模型和内部管理制度,并被逐渐细化和标准化。基于结构化、模块化的软件设计思想和细化、标准化的软件开发过程,大型软件的开发过程被划分成不同的阶段和不同的功能模块,由不同的软件团队负责。软件团队内部也进行了细致而明确的劳动分工,在软件开发领域出现了行业领域专家、软件架构师、程序员和测试工程师等不同的专业角色细分。这种日渐专业化的劳动分工,进一步提高了软件开发效率和质量。一个程序员全程做创意、设计、编程和测试的开发模式,在大型软件项目中逐渐成为历史。软件开发过程的阶段划分,与亨利•福特通过对生产过程和工人劳动精细化分工、进而实现汽车的流水线制造的大规模生产思想有异曲同工之妙。
为了提高软件生产率和软件质量,在企业内部推进软件模块的标准化,进而实现这些软件模块的复用,成为大型软件企业进行软件生产的潮流和大趋势。从编写标准函数数据库开始,软件开发人员意识到在软件开发过程中,能尽可能多地使用在其他项目中已经开发出来的模块,不仅提高了生产效率,而且因为这些复用的模块,曾在其他项目的使用中经过了更多的技术测试和用户检验,可以提高软件的质量。为了推进软件模块的复用,越来越多的大型软件企业,开始设立企业内部的软件开发标准,倡导鼓励软件复用的企业文化,强调在设计阶段就考虑程序模块等软件资产的复用,在企业内部建立软件资产管理系统,在新软件开发过程中尽可能优先选用已有的程序模块等软件资产,而不是“重新发明轮子”地全部从头编写代码。尽管直到20世纪80年代,在软件企业内部复用的还主要是子程序、程序包、类、模板等形态存在的程序代码片段,但这种基于企业内部标准的模块化和模块复用的软件开发思想,已经类似于现代汽车工业设计和制造过程中以现有部件和系统为基础,而不是以最基本螺钉、铆钉等零件为基础的设计和制造理念,初步展示了软件生产向工业化模式转型的端倪。
(3)大规模软件定制开发初露端倪
虽然软件工程的管理方法和开发技术在持续进步,但经济社会发展形成的软件不断增长的强劲需求与落后的软件生产力之间的矛盾,仍然一直在困扰着全球软件产业。软件复杂性的增长,导致了软件成本大幅增长。据Jones在1994年发布的统计结果显示,超过50%以上的大型软件项目最后都因各种原因被取消了,这里所说的“大型软件项目”是指规模超过10,000个功能点的项目;即使是在软件产业最发达的美国,工期超过一年的大型软件项目的成本,是计划成本的两倍,而性能则低于预期。这些数据时刻在提醒业界,距离发现解决“软件危机”的“银弹”,还有相当长的路要走;作为软件从业人员,我们必须继续寻找进一步提升软件生产率的道路。
最近10年来,随着软件工程方法逐渐取得成效,人们开始更加清晰地意识到,软件必须尽快从其他工业的发展经验中汲取精华,努力改进现有的生产方式,以更加工业化的方式来组织生产,这样才有可能能满足不同的企业和个人的个性化需求并降低软件维护成本。正如上文中我刚刚提到的汽车工业的基于共享平台和标准化零部件的定制生产模式,使得全球领先的汽车企业,已能够按照订单生产在满足用户的个性化需求的同时保持大规模生产的高效率和低成本;而当汽车需要维护修理时,维修人员所做的通常就是更换损坏的零部件或元件的电路板,这种模式下不仅耗时甚短,而且一般不会像软件维护那样容易引入新的错误。因此,这些基于模块化设计和标准化部件的工业产品的维护成本,较软件产品的维护成本要低得多。
从1968年Doug Mcllroy提出共享构件库以来,系统的软件复用和基于构件的开发便作为一种有吸引力的思想,受到学术界和产业界的普遍关注。多数软件企业在进行软件开发过程中,都在有意识地去积累和使用一些企业内的软件资产。从20世纪80年代中后期开始,基于构件的软件开发(Component Based Software Development,CBSD)和面向对象(Object Oriented)思想,被越来越多的业内人士认为是软件产业走出20世纪60年代以来由来已久的“软件危机”,走向高效率、高质量工业化生产的通路。从爱立信公司在业界取得巨大商业成功的AXE交换机的软件系统开始,面向对象和基于构件的软件开发,开始逐渐从实验室走向产业界,成为领先的大型软件企业普遍采用的软件开发实践。
基于构件的软件开发,有很多看得见的好处。首先,基于构件的开发,使软件企业能直接采用已存在的成熟构件搭建原型,依靠原型做需求分析和设计,而不需要重新编写全部的程序代码,能更快捷地根据用户需求进行定制化开发和实施。同时,这些相对成熟的软件构件,能分别用在不同的系统中,分别销售给众多的用户。这种软件构建的复用,更有效地分摊单个构件的研发成本,大大降低了软件生产过程中不必要的重复劳动。再者,由于在基于构件的软件开发模式下,大多数软件开发者的主要工作逐渐从传统的代码编写,过渡到构件装配,摆脱了编程的细节问题,将更多的精力投入到与用户的交流中,从而更好地把握用户需求,更注重软件产品能针对用户问题提供解决方案。而且,在需求分析阶段,那些已有的构件框架和构件,还可以帮助软件开发者和用户进一步细化需求,更好地做好软件设计和规划。最后,在基于构件的软件开发模式下,由于不同的功能应用分别采用了强内聚、弱耦合的构件来实现,因此软件系统的运行维护以及根据业务发展进行扩展二次开发变得更为容易。软件开发者只需要用修改好的模块来代替原来的模块或根据新业务的发展需要开发新的模块并插入到已有的系统中即可实现软件系统的升级。由于高度模块化,这种维护过程就像汽车的维护一样,不容易引入新的错误。例如,在SAP中国研究院,进行新产品创新时,我们经常用已有的软件构件先搭建起一个应用原型系统,让咨询顾问甚至是最终客户对这个应用环境提出他们的意见和建议,当我们对客户需求有了更充分的把握,产品创意基本确定下来后,我们再将一些必要的模块重新进行开发。这样就大大节约了新产品开发的周期,降低了新产品推向市场的风险。
在基于构件开发中,软件平台是非常重要的环节。20世纪90年代以来,软件平台概念在全球的兴起,可以看作是基于构件的软件开发方法在大型软件企业实践中的重要发展。软件平台类似于汽车工业中由底盘等核心部件构成的车型平台。在汽车工业中,基于同一车型平台,汽车企业可以以更短的周期开发出一系列面向不同客户群的汽车,基于同一车型平台的汽车,采用很多相同的标准化零部件,在个性化和规模经济之间实现了平衡。同样,在基于构件的软件开发中,也有望通过引入软件平台,来提高满足客户个性化软件需求的能力。 |