四、没有银弹,或人狼杀不死
人狼这个动物很奇怪,皮肉坚实还是自疗系的,所以要么砍它不动,要么杀它不死。这种动物如同习得(传说中的)金钟罩功夫,刀枪不入,水火不怕。也如同金钟 罩有罩门一样,人狼对银没有免疫,因此如果做一颗银弹就能穿透它,进而杀了它。
所以人们总是说一物克一物,大象怕老鼠,总有对付它的法子。但如果你设定了一个自圆已说的悖论,那除了否定悖论本身没有意义,也就没有解它的法子了。同样 的道理用在“没有银弹”这个观点上,也是成立的。
也就是说,如果我们讨论“有或者没有银弹”,那么应该先反过来看看“人狼”的本质。因为本质是人狼对银不免疫,所以我们才能找到银弹并杀了它。如果人狼根 本就杀不死,那么不要说金弹银弹,就是核弹也没用——因为它杀不死。
我们来看看Brooks所谓的人狼,也就是“软件活动的根本任务”。首先,Brooks认为我们并没有足够的精力来放到“软件活动的根本任务”这一目标之 上。他的论证过程是:
根本任务的目标:抽象软件构成的复杂概念结构;
次要任务的目标:表达抽象实体,在一定范围内映射成计算机的执行逻辑;
我们大多时候在关注次要目标,例如写程序和开发“写程序用的”程序;
我们写再多的程序与再强的“写程序用的”程序都不会触及到根本任务。
进一步的分析来说,是我们探索目标的方法,分散了达到目标的力量。我们在通向目标的路线上越是努力,那么我们的力量就被分解得越快。次要目标是达到主要目 标所必须的,但次要目标上花费越多的精力,就越无法接近主要目标。既然要经过A才能达到B,而经过了A也就没有力量达到B。那么结论自然是:达不到B(主 要目标)。
这个悖论说的是手法问题。你当然可以超越某种手段,可以从纯理论上来推论出:没有了A就成了,我们可以由C达到B。由于永远存在C至*(任意)的途径,那 么当然存在C~B的途径。由于手段无以穷尽,所以Brooks当然不能从这上面说服大众。于是,Brooks立即又论述了这个人狼的四个具体特性:复杂 度、一致性、可变性和不可见性。
一是要面对极端的复杂性。尽管我们可以用模件复用来缓解复杂性,但是软件实体的扩展必须是不同元素实体的添加,这些元素“以非线性递增的方式交互,因此整 个软件的复杂度以更大的非线性级数增长”。所以你创建一个新软件就必然面临更多的(非线性级数增长的)旧软件中不能被复用的元素。所以在复杂性方面,人狼 是自疗系的:越做越复杂,不可能变简单。
二是要背上不可丢弃的历史包袱。由于Brooks强调新的软件需要保证跟旧的软件兼容(有点象MS Vista兼容MS DOS),你创生了一个软件也就创生了下一个软件的需求,所有的创生活动产生了需求的自增集合,尽管这种“变体不是必需的”,但它一个不可丢弃的历史包 袱。所以在保证一致性这一方面,人狼是自增长的。
三是要接受需求的持续变更。软件要保证设计一致性才能成功,但从这个软件被设计的那一刻开始,你就必须接受来自它人的、自身的、市场的、自然及社会规律 的,以及不同的文化和思想习惯的差异的需求(这意味着每个人的想法都可能被作用在一个软件实体上)。需求是无度和不可控的,所以人狼本身又是变形系的。
四是不可见。你找不到足够的抽象方法描述软件的不同侧面,也就不能将它们表达为抽象概念上的图形。如果你找到了这样的方法,那么这个“软件”本身就不足够 复杂,因此也就不是原本含义上的“根本任务”。所以,它是隐形的——你如果看见了它,要么是看见了诸多复杂的方面中的一面,要么根本就是看错了。
从游戏术语来说,我们要面对的是“自增+自疗+变形+隐身”的终极大BOSS,而Brooks还要求:HI,小子,你得拿个足够简洁(例如小刀?)的武器 去单挑(独立的解决方案?)。
如果有游戏策划写出这样的脚本,那么他得被玩家活活骂死。但Brooks描绘了这样一只“杀不死的人狼”,并开心的说“你们没有银弹”。然而,他不但没有 被骂死,还得到了一致的认可,并且整个工程界欢欣雀跃,一致以找出那枚银弹为已任。
这样来戏谑大师的预言实在是有些不敬。那么大师是否就是在那么严谨地对待自己的观点呢?他说:必须声明的是,构建独立小型程序的数据不适用于编程系 统产品。
大师的意思是:因为不能通过“做更多的小型程序”来得到做大型系统的经验/数据,所以无论何时,只要面对大型工程,你的经验值就立即归零(或者极低)。显 然,(连白痴都知道)毫无经验值地直接面对终极大BOSS,结果一定是失败。又由于所有面对这些大BOSS的都(无可置疑地)失败,因此我们也就不可能有 成功。
显然这是一个法宝:如果你违背这个逻辑而又获得了成功,那么这种成功可以立即被归结于:你在做一个小型程序。
放心吧,没有人能杀得死Brooks的人狼的,也不可能找得到这样的银弹。因为Brooks的人狼原本就是杀不死的,他甚至连“给睡熟的人狼胸口一刀”这 样偶然性的机会也没给你留下。任何时候,你杀死了一头看起来有点象是人狼的怪物,Brooks都可以轻描淡写的说:OH,小子,你看错了,那并不是人狼。
五、从广义工程到狭义工程
现在我们回到一个实际的问题上:工程的本质需求是什么?如果我问一千个人工程的本质,可能会得到一千种答案。因为大家离本质的东西都很远,又从不同的角度 去看这本质,故而得到的答案并不相同——而且每一种答案都貌似正确。
但是我问的是“本质需求”。对此,我的答案是:本质需求是“实现(工程的目标)”。
不管工程本质是怎样的,但这个需求如一。我们完不成它就等于失败,至于它是否是Brooks所说的“软件活动的根本任务”,与这个具体的工程无关;至于它 是不是从人类发展的历史上来看,向着“软件活动的根本任务”的目标迈进了一步,也无与这个具体的工程无关。
简单地说,我们做具体工程的目标,并不等同于Brooks所说的“软件活动的根本任务”。
回到具体工程的视角,我们面临的可能是:
这个对比中,a1的需求基本可控,a2就得面对客户或业务规则的变化;b1不需要背上历史包袱,甚至不用考虑架构一致性,而b2就必须做好设计并面临长期 用户需求的沉积;c1可能一两个人就完成任务,c2就必须组织大型团队 ……我们如果要找一个方案来适应这所有的“软件开发活动”,那么它只可能是弹性的。而弹性并自由伸缩的一个 方案必然带来学习和运用上的困难,因此你又得投入人力来学习使用,并在实施中不时监控它。——于是,你的人力和时间成本又增加了。
不要去相信“它适合于所有的工程”这种商业推广的鬼话。那绝对是赤祼祼的欺骗。你要看住你的口袋,因为你可能在消耗你的资源 (时间、人力与金钱)去适应一种方法。你一方面要花销资源去组织、实践和推动这些工程方法,另一方面工程的 规模可能根本没有资源去推动它们,你必然面临失败;如果你增加资源去推动,那么成本可能大于项目利润,你的老板会不乐意而直接中止这个项目,你还是失败。
所以问题出在你启动这个工程的最早阶段:你认清目标并决定用什么方法来驱动这个工程。你的选择涉及到项目的各方面因素,而不是昨天从某个培训 中听到的什么奇怪方法。作为合格的项目经理 (和工程决策者),你必须要洞悉各种工程方法的应用环境、代价,也必须清楚所在团队 或公司的规模与实力,同时还要了解团队的优点与弱点。只有充分评估这些因素,你才可能决策在具体工程中应用 的方法,或尝试之。
但是我们总是会遇到无比庞大的项目,这绝不是“只做做小项目”就可以解决得了的问题。然而我认为Brooks的假设过于学术,因为我们找不出一个理由来证 明:需要一种纯粹的、独立的和并不那么复杂的方法来实施一个工程。对于一个具体的、哪怕是无比庞大的项目来说,这种学术的纯粹和完美也不是必须的。在这个 具体工程来说,完成它是必要的,而寻找完美方法,只是在完成这个项目之后进行总结时的一种附带价值。
换而言之,即使我们承认Brooks所说的“ 软 件 活动的根本任务”需要一种完美的、类似于银弹的解决方案,我们也不得不承认对于具体工程来说,“表达抽象实体,在一定范围内映射成计算机 的执行逻辑”才是根本任务。
我们看到了分歧。而我认为对这个分歧的合理的解释是:在广义工程与狭义工程(或言之具体工程)中,主要目标与次要目标正好是倒置的。对于后者来说,将需求 表达为抽象实体,并在“一定范围”内映射成计算机的执行逻辑,正好是这个工程存在的根本价值。如果这项目标不能被达成,那么这个狭义的工程既不可能实施, 也不可能为所谓广义工程产生任何价值。
既然对于狭义工程(哪怕它无比庞大)来说,Brooks所设的银弹只是面向其次要目标的,那么它也不是必须的元素。因此,我们尽可以选择集束炸弹来解决问 题。我们可以从建筑工程中学习监理,可以从制造工业中学习模件,也可以从哲学中学习概念抽象,我们还可以从社会学中去了解集体、组织、规模和控制……
一切一切,前提是我们要放开对那个“银质子弹”的追寻。这样,面对一个确定的工程对象,我们便可以找到很多问题的解法。但如果坚持存在一个“绝对正确的解 法”,那么任何实际问题都会延伸出枝节,蔓布于这个“绝对正确的解法”的墙篱之外。
最后再来看一眼那头人狼,也许(对于我们实施狭义工程的人们来说,)我们接下来便要阔别它了。要知道在所有“有银弹”的故事里,“人狼”都是杀得死的。而 Brooks描述了一头杀不死的人狼。因而“没有银弹”也自然成立了。但是如同我们上一节讲述过的,这种结论并没有意义。对于“杀不死”这个前提,“有或 者没有”这样的讨论本身就是多余的。
同样的方法,我们也证明过Brooks所述的银弹是理想化的。于学术而言,任何现象都应该有一个纯粹的解。但这种广义工程的论题,除了给商家制造更多的商 机之外,并不会因为它的争争吵吵而给狭义工程带来什么价值。事实上,正是狭义工程给广义工程提供了谈资和论据,才让后者变得越来越丰富。
却也正是这些丰富的、源自那些狭义工程的实践所带来的知识,让更多人憧憬于那颗银弹的存在,而全然忘却,一颗子弹的威力,原本是出自一个并不成功的丹药实 验。
结束语
总的来说,我事实上并不反对某种具体的方法,而是在努力的学习种种方法。但是我并不认为有什么单一的方法能解决所有问题,每一种解决方案都是有其前提和背 景的。精通一种或全部工程工具、方法和过程,都无助于掌握这些前提、背景以及潜在的关系。理解工程的适用性,涉及到工程专家的整体素养和实践经验,也涉及 到具体的工程环境、目标和实施者(团队 )。而这些课题,却正好是目前的软件工程 甚少谈论的。
在银弹的话题上,答案不外是:有、没有和将来一定会有。我的答案与这些都不一样。我认为“有没有”的话题没有意义,不值得讨论。因为Brooks在人狼的 设定上是一个伪命题,而银弹的假设上则是学术的。我进一步的观点是,广义工程对首要任务(人狼)和完美方案(银弹)的假设,不应该成为狭义工程所逐求的终 极与利器。
我们要分清狭义工程与广义工程。正是由于他们对本质需求的设定完全不同,因而也有各自不同的主要与次要任务。一切工程活动的历史告诉我们,曾经的经验、失 败和成功,以及据此在广义工程中归纳推演的理论,都只是我们在具体的、狭义的工程中的参考,而非无往不利的银弹。