软件工程是近些年来在计算机领域中非常活跃的一个学科。对从事软件开发的人员来说,“软件工程”毫无疑问是一个时下出现频率非常高的字眼,对于我们许多IT人而言,如企业领导者、项目管理负责人,或是其它各种不同职位的软件技术人员,我们经常都会有意识或无意识地提到与软件工程相关的许多字眼,诸如RUP、敏捷软件开发方法、UML,或是CMM等。是啊!由此可见,在我们的潜意识里,软件工程不仅很重要,它也的确很Fashion!
当然,时髦归时髦,时髦大多时候也许是感性的,它不一定会很科学和合理。因此,我们不禁要大声地反问自己:软件工程究竟给我们的项目(尤其是那种大型的软件项目)开发和实施,带来了多大的变化呢?例如,它能够给我们的项目节约了多少成本?对我们软件产品质量的提高起到了多大的作用?还有就是,它又能够规避了多少项目的风险等?
在实践中,也许我们的许多项目对上述问题的回答并不值得乐观;甚至很多时候,软件工程对我们项目的影响还会是负面的。那么,这里又不禁要问:为什么在软件开发领域中应用工程化管理方法后,就不能够像许多其它工业领域中那样应用工程化管理方法之后,能够发挥出更大更积极的作用呢?
对于上述问题,也许我们每一个人都可以轻松得出一个大概一致性的结论:这是由于软件开发是属于高技术含量的产品研发过程,它不同于其它一些比较普通的工业产品在开发过程那样容易进行控制和管理;而且同一种类型的产品生产流程也很容易被有效地复制使用。而软件产品的开发,有许多其自身的一些特殊性,如很多环节都是创造性的智力劳动,有其唯一性,需求不容易确定,或需求经常更换太快等特点。
客观的说,上述的结论基本上阐述出了问题的实质。但是本人认为这样的结论太过于笼统,或者说,它没有阐述到问题的具体关键点上。因此在本文接下来的内容中,我试图,也可以说是胆大妄为地,来阐述出自己对此的一些独到理解和观点。也许这其中的诸多观点可能会有些偏颇,值得大家来进一步商榷。这是因为我本人既没有对软件工程进行过系统的研究,不是自称为是这方面的专家,也没有一箩筐又一箩筐对软件工程的实践,更不是具备那种与生俱来杰出天赋之人。但是,我相信我会有属于自己的一份的自信,再外加上一份自己特有的成长、教育、学习和工作经历 —— 在农村长大,后进入城市学习和工作,在属于事业单位性质的医院实习过一年,后又在处于改革风口浪尖的国企工作过6年,近5年又漂泊在异乡为处于市场机制下运行的私企和外企给辛苦地打工;做过推销药品的业务员,也曾在办公室里安安静静地工作过,还从事过会计;虽在校所学是药学专业,后决定毅然转行,系统地自考过经济学专业课程,最后居然完全靠自学,而进入了计算机软件开发行业内工作,并保持到至今;喜欢哲学,勤于思考,酷爱动手,常常莫名地拥有“打破沙锅问到底”的那一股韧劲。所以,凭着这独特的一份人生阅历作为背景,我在这里主要从经济学和软件技术的视角,来对当前软件工程应用不甚理想的状况展开了几点深入的思考,真诚地希望能对我们以后的软件业发展有点参考价值,或能给大家一些有用的启发。当然,如下文中的某些观点能获得更多的有识之士认同,或能够产生一些共鸣,那将是本人的最大荣幸。
毫无疑问!“工程化”不是软件开发行业所独有的,它是工业革命(或者说产业革命)的产物。软件开发行业引进工程化的管理方法,也即软件工程,它当初的目的是为了解决软件危机。而造成软件危机的主要原因是由于软件项目的规模日益快速扩大,而规模宏大的软件项目必定会需要更多、更多的人来齐心协力的共同参与。因此从本质上说,软件工程研究的内容其实很简单 —— 那就是,软件开发人员如何更好地在一起协同工作,以便能够共同完成某一项规模宏大的软件产品的开发任务。就好像蜜蜂协同建蜂巢那样,这当中需要科学的方法和科学的管理,以及很好的协同和分工。因此软件工程实际上必然会包括很多很具体的一些东西,如任务的分工和协作、开发过程方法、计划与进度控制、质量保证、成本控制与资源分配等等。在这里,我本人不太感兴趣对这些具体的东西展开过多讨论,而是重点围绕在工业化革命中,对工程化管理思想带来革命性进步的一项技术方法 —— 产品的流水线作业展开分析讨论。
我个人执著的认为:“如果没有流水线作业技术,根本就没有后来的如此发达的工业社会文明”。这样说其实一点也为不过分。我们也许不敢说流水线作业技术是最好的分工和协作方式,但是毫无疑问,它却是至今为止最为行之有效的一种分工和协作方式。它把无论多么复杂的制作过程进行拆分,一步一步的,直至它很简单为止。这样,流水线作业技术就使人类自身获得了较彻底的解放,一个人再也不用去掌握那么多的技能。这不仅是提高了效率,也更提高了产品的质量。而且这样被拆分后的每一个简单工作任务,可以很容易地让机器去代替完成,从而大幅提高生产效率并降低生产成本。同时,对复杂过程进行最大程度上的细分后,能有效的实施无关联步骤的并行开发活动,从而大幅缩短每件产品开发所需的时间。
如果我们从一个更广义的视角来审视软件工程;那么软件工程其实可以被理解为,是对软件的开发活动,如何来实施流水线作业化的拆分过程。这个流水线作业化如果实施得好,那么可以说对这个软件项目的工程化,肯定也是实施得很成功的。80年代盛行的结构化分析和设计方法中的瀑布模型,它基本是遵循完全线性化的工作拆分流程,和其它的工业产品的生产流程类似,前一个“工序”没有被完成并审核通过,后一个任务流程是不会启动的。当然,后来发现,这样僵硬死板的软件工程化开发流程,其实对许多项目并不适合,尤其是那些需求从一开始很难确定的项目,或是需求变化太快的一些项目。因此,后来在软件工程领域中,出现了许多其它的一些软件开发方法,诸如原型法、迭代法、螺旋法、演进法等等。
上面的这些不同的软件工程化开发方法,这些都是由于软件开发这一领域的本身独特性所致,前面也阐述过这一点。但是真正导致当前软件工程应用不甚理想的原因,就仅仅是因为如此吗?就完全是因为软件开发其自身根本不适合采用工程化的思想来管理吗?不!本人决不赞成这种观点,虽然我也认为,由于软件开发领域中每一个工作任务都需要很大的创新性等诸多特点,它会很大程度上影响软件工程化的实施难度;但是,这一点我们通过不断的实践,不断的改进,以及软件技术本身的发展,其实我们是可以有效地克服这些困难的,后面会进一步阐述与此相关的一些技术的演进过程。而我认为,更为关键的原因是我们社会,或者说是我们人类自己的一些缺点所导致的,是我们的思想文化上的狭隘和片面追求利益之上的情结所造成软件工程很难突飞猛进。为何这么说呢?
试问!其它的工业产品在其完整生产周期过程中,会只有一个厂家参与某个产品生产的全过程吗?很明显,绝对不是这个样子的。我们知道除了原材料之外,中间还有许许多多的中间产品(半成品)环节。试想!如果一个房产建筑商在承建某一栋大楼时,所有的东西,所有的任务都由它一家公司来做,这可能吗?它又要去生产钢筋,又要去生产水泥,它还有能力去造楼吗?所以这就需要社会分工。而“流水线作业”,也绝对不是狭隘仅指,你某个公司内部有很好的流水线作业管理就能够行得通!而是一个某行业的、甚至是全社会的合理分工和协作。
但目前的软件行业却并非如此,看看那些个软件巨头们!它们几乎都是独成一个体系,什么软件包都是自己做,很少去依赖于别人。当然,在此也许大家会觉得不以为然,实际不是这个样子呀!软件开发厂商之间也有很多的合作呀!而且对于应用软件系统的开发商或集成商,它们会觉得有许多开发平台,以及很多很多的可复用的开发库可以利用。这些“开发库”不就是相当于其它工业产品中的半成品吗?
本人不敢苟同上述的这种意见!因为这些所谓的“开发库”是完全封闭的、并受某个厂商单向控制并垄断的。所以它有很大的不确定性,例如,对这些库的整体结构设计,或者某个接口的设计,作为使用者你,你有权去修改它吗?可能连建议权也没有吧!另外还有就是,当开发库在升级时,你的应用程序很可能存在由于接口不一致性所带来的巨大风险!也许又有朋友认为,你可以使用那些开源项目的开发库呀!那么我又请问?此时你的软件产品质量由谁来保证,如果某个库中的某个bug导致了你系统的崩溃,你能及时找得到谁是真凶吗?即使你找到了真凶,你还能找得到某人或某软件开发商来为此来负责吗?
所以说,现在的软件开发领域,它这里缺乏一个很好的产业链环境。缺乏像其它工业产品中的“半成品”式的复用,虽然我们曾经对组件的搭积木开发方式寄予过很美好的希望,还有ActiveX控件等。究其原因,就是由于各个软件公司为追求利益最大化,梦想自己垄断并主宰整个(或某类)软件产品的全部规范及开发过程;其结果导致软件工程的思想很难全面实施,最终也必将影响各个软件企业间的合作,并影响软件产品的开发效率。这里我们再举一个例子。两个企业厂商,一个从事PC的组装生产,而另一个从事企业应用软件的集成(EAI),您认为,这两个企业所从事的工作,那一个更容易、更简单呢?我们不能说PC机的里面的构造会很简单吧!它里面那么多电路板和那么多精密元件,但是由于它的任务分工很好,模块化程度很高!所以最后做组装和集成的时候,就很容易进行。而从事EAI的工作任务时,本来这毫无疑问是很简单的一件事,但是由于各个应用之间缺乏规范和合作,使得本来很轻而易举的一件事,未必就会那么被轻易地搞定。
在文章最后的一段内容中,我不想在这里再过多评论现在的软件工程技术的一些是是非非,而是给出一个俺本人认为较为理想的软件工程实施模型,也许这个模型过于理想化,甚至是很不成熟。但是我会执著地认为,我们的软件工程应该朝这个方向去努力。
要想软件工程真正能够像其它产业中的工程化应用那样发挥出更多更好的作用。那么,首先就一定要注意培育出一个好的、健康的软件开发的产业链环境。只有这个产业链环境健康了,成熟了,各个软件企业才会有更多的资源去关注属于自己擅长的那一块工作任务,也才可能把属于自己的工作任务真正地去完成好。当然,这样各自的软件企业在这个大的软件产业链环境中,必定会找到并实现自己的最大利益。
那么,这个理想的软件工程实施模型究竟是个什么样子呢?具备哪些特点呢?下面从几个方面概括一下。
首先,软件工程的首要任务是对工作任务的细分,也即把工作拆分,实现流水线式的作业化,而且这还不仅是企业内部自己的工作任务流水线化,而且还应该涵盖在整个软件产业链中工作任务的流水线化,也即能够实现软件企业间的“半成品”性质的大颗粒度软件复用。
我觉得从技术上来说,这绝对已不成问题,因为软件的模块化实现技术现已非常成熟,那就是我们可以采用基于组件的开发技术,因为它能够实现非常优良的软件的模块化细分。当然我们也都知道,组件开发技术不是什么新鲜玩艺,通常我们总把它与面向对象开发技术放在一起来理解,并做出一些比较,认为组件开发技术是比面向对象开发技术更好的一种软件开发的技术方法。诚然,这种观点也没什么太大的不妥;但是我认为,这种对组件技术的理解可能不是很准确,如果究其本质,面向对象开发技术与面向组件开发技术,这两者之间也许并无太多的关联,或者说它们根本不是一回事。我们可以这样认为:面向对象开发是一种编程思想;而组件则仅仅是一项技术,是一项接口的技术。组件技术能够实现二进制意义上的软件模块复用,它能够使得模块间的耦合性更小,从而提供软件模块的可复用性,及软件模块的可扩展性,同时还为能够轻松实现软件模块的动态装载与更新。
组件技术虽然能够实现很好的软件模块化,但是我想仅凭这点是远远不够的。而更重要的是,我们模块化之间的沟通接口必须是规范的、统一标准的,并公开的。因为只有这样统一了接口的模块化软件,它才能真正让这个软件产品,能够实现跨多个厂家的流水线式的生产作业过程。而且,只有实现了接口的统一标准化,才能有效去判断某个模块组件的好坏优劣,才能够实现组件间的优胜劣汰。而现在的实际情况是,我们的接口设计太随意,太多样化了。
我想微软的COM/COM+当初设计时所预期的目标,肯定也会是建立起能够以这样一种松散合作方式,来构建软件产品的生产开发平台(本文,我们把这种方式称为“流水线式的产品作业链”)。在这个平台环境下,每个公司专注于自己擅长的那一块工作任务,并最终以组件的方式把这个功能模块发布出去;而这些可以被形象地称为半成品,它可以被其它公司进一步加工和封装为颗粒度更大一些的组件;最后软件产品的集成商,可以将这多个大颗粒度的组件,通过连接器来把它们集成为一个最终的软件产品。但是从现在实际情况来看,当初这种美好的设想在今天并没有完全成为现实。究其原因,我认为最为关键的因素,就是因为它们对接口设计没有统一的规范所导致。或者说,COM/COM+对接口的规范化设计没有构成很好的约束力,这就导致对实现同一类功能的某些组件,可能它们会是完全是由不同人来所设计并实现的,所以其接口也可能会截然不同。例如,一个mp3播放的组件模块,有的人可以只实现了对某一种格式(如16bit量化标准)的mp3文件实现播放;而另外一个类似功能的mp3播放组件有可能它是封装为Activx形式而进行发布的;而还有的mp3播放组件可能只对输入mp3文件路径时能够予以正确播放,但是它却不能直接播放音频流等。
总之,这些没有统一规范接口的组件,对于使用它们的软件集成商来说,便会觉得无所适从,因此对于我们大多数软件公司来说,对于我们大多数软件开发者这来说,我们经常更愿意是自己来实现软件产品的每一部分的主要功能,而总觉得现在已有的那些个组件,虽然它们似乎已经实现了我想要的那部分功能,但还总是觉得它们不太好用,或不太适合自己,或不能很好的满足自己。
所以说,微软的COM/COM+并没有能够真正地成为流水线式的产品作业链平台,它不能像其它工业产品的生产过程中的那样,其各个零件之间的接口设计都很规范,因此最终的产品也很容易被组装和拆卸,而且半成品的厂家来源也都是很丰富的,大家有优胜劣汰的选择标准和机会。而现在的仅有的一些可复用的组件几乎都是随微软的开发平台一块发布出来的,而更多的软件开发公司很难真正参与到这个平台中来。因此我们不妨直接了断地说,现在所谓的许多软件平台,其实它们都不是真正意义上的开发平台,因为它们没有发挥出一个真正平台所应该有的那些功能,它没有扮演“有效而公平地分工”的这种角色,当然最终也就难形成为高效的流水线式的产品作业链环境。
所以说,对于理想的软件工程应用模型中,最为适合的一种开发方式是“基于接口的编程”。当然,基于接口的编程,这也绝不属于什么创新思想!俺个人在这里也无意炒作概念。而只是觉得“基于接口的开发方式”比“基于组件的开发方式”,它的这种提法更为合理和科学一些,因为它更重点强调接口设计的规范性和公开化,它这不应该属于某个公司的私人财产,而应该是为大家所共有的共享资源财富。其实我觉得可以通过一个协会性质的团体来促进接口设计的统一规范化,类似于RFC标准制定的那种流程方式。另外,如果模块之间的接口规范化了,合理化了,那么这毫无疑问将对软件的测试和软件质量的度量提供了方便,而且也会因此给软件质量的提高有了更多的保障。
刚才上面的讨论,我们的重点是从技术角度上进行了较全面的阐述,也即通过接口的规范化设计,来保证“流水线式的产品作业链平台”顺利实施。但是仅从技术上能够实现就已经万事大吉了吗!不是,当然不是!因此接下来的内容中,我们来探讨另一个至关重要的因素,那就是“利益的合理分配机制”问题。
有合作就会有收获,有收获就会有如何分配!如何使经济利益的分配更为合理?这绝对是一个人类所面临的自古至今都存在的难题?当然,它同时也是一个非常关键、也非常敏感的问题。分配机制是否合理?这毫无疑问会直接影响事情的成败!而事实上,现在出现的很多问题,其最终的根源都是由于我们的狭隘利益观所导致。因此,为了使得“流水线式的产品作业链平台”不是我们想象中的空中楼阁,那么就必须要为它建立起一个合理而公平的利益分配机制。而这一点,恰恰是我们目前基于组件(或基于服务)方式下进行软件产品开发过程中,解决得最不理想的一个关键环节。
想一想,其它工业产品的生产过程中,各方对利益的分配那是有相当的默契。各种环节的半成品都可以明码标价、公平竞争、自由而畅通的销售。但是现在软件产品的中间环节中的半成品,却很难有这样良好的市场环境。当然,这其中的一方面可能是由于软件产品本身的一些特点所导致的,但我想更根本的原因,是因为我们狭隘的自私主义所导致。如其它工业产品的半成品可以一个卖多少钱,而且一个萝卜一个坑,一个半成品只能被消费一次。但软件产品中的半成品却不是这样,它可以被充分的复用,按说这应该是软件产品生成过程中的优势,但是如果生产组件的提供商,自己辛辛苦苦开发出来的半成品只能被卖一次,收一次钱,但却可以被无限次复制使用,那么它这家公司当然干不下去这个行当。
因此我们必须要很好的解决掉这个问题后,才能最终实现“流水线式的产品作业链平台”。虽然本人现在对此还没有想出更好的具体的解决方案,但是我坚信这是一定可以做到的。因为,如果我们不能够实现对软件产品中的半成品(组件模块)实现公平交易,那么我们的软件工程技术就一定难以取得实质性的突破,也难以真正地去消除软件危机。
当然我还乐观地认为,其实这个问题也许没有我们想象中的那么难以解决!因为首先从技术上,由于我们前面所说的采用了面向接口的开发方式,使得组件模块之间的接口规范化了,这样就为软件半成品提供了很好的可度量手段,而且由于有了统一的接口标准,有了公平的市场竞争平台,于是同一功能的组件也必然会有多的提供商,这样组件间就有了良性竞争的环境,我们可以很好地实现组件的优胜劣汰。而且也为组件模块的定价提供了市场机制。其次,就是应该提高我们自身的素质,坚决打击盗版。因为一个良好的秩序,对整个软件产业链环境中的良性运转是至关重要的。虽然对组件的复制重用很容易被实现,但是从良心上来说,你使用了人家辛辛苦苦开发出来的产品,也应该给人家付费呀,这是最现代社会最基本的经济规律,按劳分配吗!当然,我们也许可以设计一些方法来让组件的盗版更难进行,或者我们可以设想,找到一种方法,去统计应用程序对组件使用情况,如计算调用次数,或CPU运行时间等,总之,我们可以按任务的实际工作量来进行利益的合理分配。
综上所述,我们是要形成这种一种局面:那就是按组件模块的方式来发布和销售软件产品(或半成品),并以此来获得自己该得的那份利润;来代替现在仅按最终软件产品(或软件服务)才能销售获利的方式。其实,如果我们的软件产品按照这种方式生产出来的话,那么对提高它的最终的软件产品质量将是大有帮助的,因为我们可以建立起一个责权利相一致的质量保证体系。就好像我们现在的其它工业产品那样,每个厂家必须保证自己的产品或半成品的质量,而集成商则更专注于产品的统一协调上。如果某个零件出现质量问题,那么生产这个零件的厂家将应该承担主要责任。这套规则我觉得同样它也适用于对软件产品的质量保证上,首先是全行业(或某一个产业的应用系统)形成一个统一的接口规范;然后大家按此规范,各尽所能,根据自己的资源情况,做自己适合的那一个组件模块,在保证接口规范统一的基础上,组件模块的提供商将要主要测试组件内部的运行情况;之后大家各自发布自己的组件模块,并因此获利,同时也将承担起维护和升级这个组件的任务;最后,软件产品的集成商可以根据自己的需要,从众多组件模块中优胜劣汰,挑选出自己认为性价比最为合适的半成品组件模块,来组合出最终的软件产品,当然软件集成商重点要测试各个组件的接口是否遵循规范,以及组件间的协同工作情况。如果最终用户遇到某个意外崩溃,那么可以从例如一个特殊的故障纪录子系统中,来认定这个事件该由谁来承担相应的责任。
最后,我把这几关键的几点总结一下,如下:
1、采用面向接口的编程方式,对接口设计进行统一的规范化,并且通过组件技术,使得软件产品有更好的模块化特性。
2、建立一个合理的利益分配机制,按组件模块的方式来发布和销售软件产品(或半成品),并以此来获得自己该得的那份利润。加强专利保护,坚决杜绝盗版;
3、研究出一个对组件模块的质量进行规范化度量的统一方法。
4、建立起一个责权利相协调一致的质量保证体系