杀不死的人狼——我读《人月神话》(五)

本文探讨了工程的本质需求及其实现方式,分析了Brooks的银弹理论在实际工程项目中的适用性,并提出广义工程与狭义工程的区别。认为在具体项目中,完成目标才是关键,而非追求理想的解决方案。

 

 
 
=====
五、从广义工程到狭义工程
=====
现在我们回到一个实际的问题上:工程的本质需求是什么?如果我问一千个人工程的本质,可能会得到一千种答案。因为大家离本质的东西都很远,又从不同的角度去看这本质,故而得到的答案并不相同——而且每一种答案都貌似正确。
但是我问的是“本质需求”。对此,我的答案是:本质需求是“实现 ( 工程的目标 ) ”。
 
不管工程本质是怎样的,但这个需求如一。我们完不成它就等于失败,至于它是否是 Brooks 所说的“软件活动的根本任务”,与这个具体的工程无关;至于它是不是从人类发展的历史上来看,向着“软件活动的根本任务”的目标迈进了一步,也无与这个具体的工程无关。
简单地说,我们做具体工程的目标,并不等同于 Brooks 所说的“软件活动的根本任务”。
 
回到具体工程的视角,我们面临的可能是:
a1 :自研发产品
a2 :客户投资的项目
b1 :短期效益的市场探针
b2 :战略方向上的一项长远计划
c1 :一个小型而称手的工具
c2 :一个大型的可持续平台
……
……
这个对比中, a1 的需求基本可控, a2 就得面对客户或业务规则的变化; b1 不需要背上历史包袱,甚至不用考虑架构一致性,而 b2 就必须做好设计并面临长期用户需求的沉积; c1 可能一两个人就完成任务, c2 就必须组织大型团队……我们如果要找一个方案来适应这所有的“软件开发活动”,那么它只可能是弹性的。而弹性并自由伸缩的一个方案必然带来学习和运用上的困难,因此你又得投入人力来学习使用,并在实施中不时监控它。——于是,你的人力和时间成本又增加了。
不要去相信“它适合于所有的工程”这种商业推广的鬼话。那绝对是赤祼祼的欺骗。你要看住你的口袋,因为你可能在消耗你的资源(时间、人力与金钱)去适应一种方法。 你一方面要花销资源去组织、实践和推动这些工程方法,另一方面工程的规模可能根本没有资源去推动它们,你必然面临失败;如果你增加资源去推动,那么成本可能大于项目利润,你的老板会不乐意而直接中止这个项目,你还是失败。
所以问题出在你启动这个工程的最早阶段:你认清目标并决定用什么方法来驱动这个工程。你的选择涉及到项目的各方面因素,而不是昨天从某个培训中听到的什么奇怪方法。作为合格的项目经理(和工程决策者),你必须要洞悉各种工程方法的应用环境、代价,也必须清楚所在团队或公司的规模与实力,同时还要了解团队的优点与弱点。只有充分评估这些因素,你才可能决策在具体工程中应用的方法,或尝试之。
 
但是我们总是会遇到无比庞大的项目,这绝不是“只做做小项目”就可以解决得了的问题。然而我认为 Brooks 的假设过于学术,因为我们找不出一个理由来证明:需要一种纯粹的、独立的和并不那么复杂的方法来实施一个工程。对于一个具体的、哪怕是无比庞大的项目来说,这种学术的纯粹和完美也不是必须的。在这个具体工程来说,完成它是必要的,而寻找完美方法,只是在完成这个项目之后进行总结时的一种附带价值。
换而言之,即使我们承认 Brooks 所说的“软件活动的根本任务”需要一种完美的、类似于银弹的解决方案,我们也不得不承认对于具体工程来说,“表达抽象实体,在一定范围内映射成计算机的执行逻辑”才是根本任务。
 
我们看到了分歧。而我认为对这个分歧的合理的解释是:在广义工程与狭义工程 ( 或言之具体工程 ) 中,主要目标与次要目标正好是倒置的。对于后者来说,将需求表达为抽象实体,并在“一定范围”内映射成计算机的执行逻辑,正好是这个工程存在的根本价值。如果这项目标不能被达成,那么这个狭义的工程既不可能实施,也不可能为所谓广义工程产生任何价值。
既然对于狭义工程(哪怕它无比庞大)来说, Brooks 所设的银弹只是面向其次要目标的,那么它也不是必须的元素。因此,我们尽可以选择集束炸弹来解决问题。我们可以从建筑工程中学习监理,可以从制造工业中学习模件,也可以从哲学中学习概念抽象,我们还可以从社会学中去了解集体、组织、规模和控制……
一切一切,前提是我们要放开对那个“银质子弹”的追寻。这样,面对一个确定的工程对象,我们便可以找到很多问题的解法。但如果坚持存在一个“绝对正确的解法”,那么任何实际问题都会延伸出枝节,蔓布于这个“绝对正确的解法”的墙篱之外。
 
最后再来看一眼那头人狼,也许(对于实施狭义工程来说,)我们接下来便要阔别它了。要知道在所有“有银弹”的故事里,“人狼”都是杀得死的。而 Brooks 描述了一头杀不死的人狼。因而“没有银弹”也自然成立了。但是如同我们上一节讲述过的,这种结论并没有意义。对于“杀不死”这个前提,“有或者没有”这样的讨论本身就是多余的。
同样的方法,我们也证明过 Brooks 所述的银弹是理想化的。于学术而言,任何现象都应该有一个纯粹的解。但这种广义工程的论题,除了给商家制造更多的商机之外,并不会因为它的争争吵吵而给狭义工程带来什么价值。事实上,正是狭义工程给广义工程提供了谈资和论据,才让后者变得越来越丰富。
却也正是这些丰富的、源自那些狭义工程的实践所带来的知识,让更多人憧憬于那颗银弹的存在,而全然忘却,一颗子弹的威力,原本是出自一个并不成功的丹药实验。

=====
结语
=====
总的来说,我事实上并不反对某种具体的方法,而是在努力学习种种方法。但我并不认为有什么单一的方法能解决所有问题。每一种解决方案都有其前提和背景,精通一种或全部工程工具、方法和过程,都无助于掌握这些前提、背景以及潜在的关系。 理解工程的适用性,涉及工程专家的整体素养和实践经验,也涉及具体的工程环境、目标和实施者(团队)。而这些课题,正好是目前的软件工程甚少谈论的。
在银弹的话题上,答案不外是:有、没有和将来一定会有。我的答案与这些都不一样。我认为“有没有”的话题没有意义,不值得讨论。因为Brooks 在人狼的设定上是一个伪命题,而在银弹的假设上则是学术的。我进一步的观点是,广义工程对首要任务(人狼)和完美方案(银弹)的假设,不应该成为狭义工程所追求的终极与利器。
我们要分清狭义工程与广义工程。正是由于他们对本质需求的设定完全不同,因而也有各自不同的主要与次要任务。一切工程活动的历史告诉我们,曾经的经验、失败和成功,以及据此在广义工程中归纳推演的理论,都只是我们在具体的、狭义的工程中的参考,而非无往不利的银弹。
曾经,我们如同走在一片沙漠,看不到沙漠的边缘,也不知道如何行走。Brooks的伟大贡献,在于他用《人月神话》指出了一条道路并教给我们基本的行走方法,让我们从中学会了辨识流沙,懂得了沙暴的征兆;同时“没有银弹”的假设激发了我们的斗志,如同有人在说“你要证明沙漠有边界,你就拿出一束青草来看看”。
于是有了几种喋喋不休于“有没有青草”的人。一种是已经在灵魂上上升到另一个层次,故而无需行走于沙漠。另一种则只是站在沙盘边上,用长杆推动卒子,而鞋子上根本不会沾上一点点沙土。
还有一种人则不时地宣称他们已经找到了青草。他们总能确保你在付费的时候看得到青草,而你转身时才会发现那里并不是沙漠的边缘。
剩下的人一边喃喃着“沙漠边缘的青草”,一边在焦燥的沙海里缓步前行。不同的是喃喃而不自觉者掉进了沙坑,心怀憧憬而盯紧脚步的人则走出了沙漠。
走出来,你才会觉得:原来有没有青草,并不是那么重要。



### Brooks在《人月神话》中关于软件工程没有银弹的观点的合理性分析 Fred Brooks在其经典著作《人月神话》中提出,软件工程领域存在所谓的“银弹”(There is no silver bullet),即没有任何单一的方法或技术能够解决所有软件开发中的问题[^1]。这一观点具有深远的影响,并在软件工程的发展历程中得到了广泛的认可和验证。 #### 观点的合理性 1. **本质复杂性** 软件开发的核心挑战在于其本质复杂性。这种复杂性来源于多个方面,包括需求的确定性、系统的规模以及技术的快速变化。即使引入了新的工具和技术,如敏捷开发方法、微服务架构等,这些方法只能缓解某些特定的问题,而无法从根本上消除软件开发中的复杂性[^4]。 2. **管理复杂性与沟通成本** 在大型软件项目中,团队成员之间的沟通和协调成为主要瓶颈。随着团队规模的扩大,沟通成本呈指数级增长,这使得增加力并一定能加快项目的进度。Brooks指出,月并非衡量生产力的有效单位,因为添加更多的手可能会导致更多的混乱和延迟[^1]。 3. **技术局限性** 尽管新技术断涌现,但它们往往只适用于特定场景。例如,面向对象编程(OOP)虽然提高了代码的可重用性和可维护性,但在处理大规模分布式系统时仍面临诸多挑战。同样,微服务架构虽然增强了系统的灵活性和扩展性,但也引入了额外的复杂性,如服务间的通信和一致性问题[^4]。 #### 结合软件工程发展历程的讨论 - **从瀑布模型到敏捷开发** 瀑布模型曾是软件开发的主要方法,但它对需求变更的适应能力较差,容易导致项目失败。敏捷开发通过迭代和增量的方式,允许需求在开发过程中逐步明确,从而降低了风险。然而,敏捷开发本身并能完全避免软件危机,尤其是在面对复杂的业务逻辑或明确的需求时[^2]。 - **前后端分离与分布式架构** 前后端分离模式和分布式架构的兴起,标志着软件开发向模块化和解耦方向迈进。现代前端框架(如React、Vue)和后端微服务架构共同构成了当前主流的系统设计方法。然而,这种架构也带来了新的挑战,如跨服务依赖管理和数据一致性问题[^3]。 - **自动化工具的作用** 自动化测试、持续集成/持续部署(CI/CD)等工具的引入,显著提高了开发效率和产品质量。然而,这些工具能解决所有问题,特别是在需求分析和设计阶段,仍然需要依赖开发员的经验和判断。 ### 示例代码:微服务架构中的服务间通信 以下是一个简单的示例,展示如何在微服务架构中实现服务间通信。使用RESTful API进行调用,尽管这种方法简单易用,但在高并发场景下可能面临性能瓶颈。 ```python import requests def call_user_service(user_id): url = f"http://userservice/api/v1/users/{user_id}" response = requests.get(url) if response.status_code == 200: return response.json() else: return None ```
评论 13
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值