上个周末,我又把《人月神话》翻出来读了一遍。

这是我第三次读这本书了。第一次读是在大学,那时候觉得这就是一本讲软件工程的老书,很多内容过时了。第二次读是在工作三年后,那时候带了一个小项目,遇到了很多书里说的问题,才觉得这本书说得真对。

这是第三次读,我已经工作八年了,带过几个大项目,踩过不少坑。再读这本书,感受又不一样了。很多以前觉得抽象的道理,现在都有了切身体会。

这个周末,读完之后,我坐在阳台上,想了很多。这篇文章,就来记录一下这次重读的感受和思考。

关于这本书

先简单介绍一下《人月神话》。

这本书的作者是弗雷德里克·布鲁克斯(Frederick P. Brooks Jr.),他是IBM的资深计算机科学家,曾经主持了IBM System/360计算机和OS/360操作系统的开发。这本书出版于1975年,是他根据自己在IBM的项目管理经验写成的。

书的名字"人月神话"(The Mythical Man-Month),来自书中的一个核心观点:人月是一个危险的神话。所谓"人月",就是用人乘以月来衡量工作量,比如一个项目需要100人月,意思是10个人做10个月,或者5个人做20个月。

布鲁克斯说,这种算法是错误的。因为人和人之间的沟通成本、任务的可分性、新成员的学习曲线,都会让"加人"不一定能"加进度"。在一个已经延期的项目里加人,反而会让项目更延期。这就是著名的"布鲁克斯定律"。

这本书虽然出版于近50年前,但里面的很多道理,在今天依然适用。软件行业变了,编程语言变了,开发工具变了,但人的问题、管理的问题、项目的问题,几乎没有变。

这也是为什么,《人月神话》能成为软件工程领域的经典,被一代又一代的程序员和项目经理阅读。

焦油坑:每个项目都会陷入的困境

书的第一章,叫"焦油坑"。

布鲁克斯说,大型系统的开发,就像一个焦油坑。很多大型动物(猛犸象、剑齿虎)都试图穿越这个焦油坑,但最后都陷了进去,越挣扎陷得越深。

这个比喻太形象了。每个做过大型项目的人,应该都有过这种感受:项目一开始雄心勃勃,大家都觉得能按时交付。但做着做着,需求变了,技术遇到瓶颈了,人员变动了,进度延期了,预算超支了。你越想挣扎出来,陷得越深。

我自己就经历过好几个这样的项目。有一个项目,一开始计划三个月完成,结果做了八个月。中间加过人,加过班,改过需求,最后交付的产品和最初的设计已经完全不一样了。项目结束的时候,整个团队都精疲力尽。

布鲁克斯说,焦油坑是大型系统开发的固有属性,不是某个人的错,也不是某个公司的错。它是由大型系统的复杂性决定的。我们能做的,不是完全避免焦油坑,而是认识到它的存在,尽量不要陷得太深。

这个观点,让我对项目延期有了更平和的心态。以前遇到项目延期,我会很焦虑,觉得是自己的问题。现在我知道,延期是大型项目的常态,重要的是及时发现问题,调整预期,而不是硬撑着假装一切正常。

人月神话:为什么加人不能解决问题

"人月神话"是这本书最核心的观点,也是我每次读都有新体会的一章。

布鲁克斯说,很多项目经理在项目延期的时候,第一反应是加人。他们觉得,原来10个人做10个月,现在加5个人,就能在7个月完成。但实际上,加人往往会让项目更慢。

为什么?因为加人会带来几个问题:

第一,沟通成本增加。原来10个人,沟通渠道是45条(10*9/2)。加5个人变成15个人,沟通渠道变成105条,增加了一倍多。人越多,花在沟通上的时间就越多,真正干活的时间就越少。

第二,新成员需要学习。新来的人不熟悉项目,需要老成员花时间培训和答疑。这不仅不能立刻提升产能,还会降低老成员的效率。等新成员终于上手了,项目可能已经延期更久了。

第三,任务的可分性有限。有些任务是不可分的,比如系统架构设计、核心模块开发。这些任务,加再多的人也没用,因为一个人做和十个人做,花的时间差不多。

布鲁克斯有一个很经典的比喻:"不管多少个女人,生孩子都需要九个月。"有些事情,就是需要时间,加人没用。

这个道理,说起来简单,但做起来很难。我自己就犯过这样的错误。有一次项目延期了,我向领导申请加了两个人。结果,那两个人花了一个月才熟悉项目,期间还不断问我问题,打断我的工作。一个月后,他们终于能上手了,但项目已经延期了两个月。最后算下来,加人不仅没有加快进度,反而拖慢了。

从那以后,我在项目管理中就特别注意:不到万不得已,不加人。如果真的要加人,也要在项目早期加,而不是在项目后期加。而且,加人的时候要做好培训计划,不能让新人自己摸索。

没有银弹:软件工程的永恒困境

书里有一篇很著名的文章,叫《没有银弹》。这篇文章最初是布鲁克斯在1986年发表的一篇论文,后来收录到了《人月神话》的再版中。

"银弹"这个词,来自西方传说,指能杀死狼人的银色子弹。布鲁克斯用它来比喻能一次性解决软件工程所有问题的万能方法。

布鲁克斯说,软件工程里没有银弹。没有任何一种技术或管理方法,能让软件开发的生产率在十年内提高十倍。因为软件开发的困难,分为"本质困难"和"偶然困难"。

本质困难,是软件本身的复杂性带来的,比如需求的模糊性、设计的复杂性、一致性的要求、可变性的需求。这些困难是软件固有的,不管用什么技术和方法,都无法完全消除。

偶然困难,是由工具和方法的不完善带来的,比如编程语言的低级、编译速度慢、调试工具差。这些困难是可以通过技术进步来解决的。

布鲁克斯说,过去几十年,我们在解决偶然困难方面取得了很大进步,比如高级语言、面向对象编程、IDE、版本控制等等。但在解决本质困难方面,进展很小。而且,本质困难才是软件开发中最大的挑战。

所以,布鲁克斯预言,在未来十年内,不会有银弹。软件开发的生产率,不会有数量级的提升。

这篇文章发表于1986年,快40年过去了。回头看,布鲁克斯的预言是对的。虽然我们有了很多新的技术和工具,比如云计算、微服务、AI辅助编程,但软件开发的本质困难依然存在。项目依然会延期,bug依然会有,需求依然会变。

现在AI编程工具很火,很多人说AI会是银弹,会彻底改变软件开发。但我觉得,AI能解决的,更多是偶然困难,比如写样板代码、查文档、做代码补全。对于本质困难,比如理解用户的真实需求、设计复杂的系统架构、保证系统的一致性,AI能帮的忙还很有限。

当然,我不是说AI没用。AI确实能提升开发效率,能让程序员从重复劳动中解放出来。但指望AI彻底解决软件开发的所有问题,是不现实的。至少在可预见的未来,软件工程依然没有银弹。

第二系统效应:为什么第二个系统往往会过度设计

书里还有一个概念,叫"第二系统效应"(Second-System Effect)。

布鲁克斯说,一个工程师在做第一个系统的时候,往往会比较克制,因为经验不足,不敢做太多花哨的功能。但在做第二个系统的时候,他会把第一个系统里没来得及做的功能、想法,全部加到第二个系统里,导致第二个系统过度设计、过度复杂,最后失败。

这个效应,我在工作中见过很多次。

有一个团队,做第一个产品的时候,很克制,只做核心功能,产品很简洁,用户反馈很好。然后他们做第二个产品,觉得自己有经验了,加了很多"高级功能":插件系统、主题定制、多语言支持、自动化工作流……结果产品变得非常复杂,用户用不明白,性能也很差,最后失败了。

我自己也犯过这个错误。我做的第一个项目,功能很简单,但很稳定。做第二个项目的时候,我觉得自己懂了,设计了一个"完美"的架构,支持各种扩展和配置。结果开发周期翻了一倍,代码复杂度高得离谱,后期维护非常痛苦。

布鲁克斯说,要避免第二系统效应,最好的方法是:在做第二个系统的时候,找一个做过第一个系统的资深架构师来把关,让他对新功能说"不"。或者,有意识地提醒自己,不要把所有想法都加到一个产品里,要做减法。

这个道理,不仅适用于软件设计,也适用于很多其他领域。做产品、做创业、做人生规划,都要警惕"第二系统效应",不要因为有了一点经验,就想做一个"大而全"的东西。

外科手术团队:小而精的团队更高效

布鲁克斯在书里提出了一个很有意思的团队组织方式,叫"外科手术团队"。

他说,传统的软件开发团队,是大家一起写代码,每个人写一部分。但更好的方式,是像外科手术团队一样:有一个主刀医生(首席程序员),负责核心的设计和编码;有几个助手,负责辅助工作,比如测试、文档、工具开发;还有护士、麻醉师等支持人员。

在这种团队里,核心的设计和编码由一个人(或者极少数人)完成,保证了设计的一致性和代码的质量。其他人负责辅助工作,让主刀医生能专注于最重要的部分。

布鲁克斯说,这种团队组织方式,比传统的"大家一起写代码"效率高很多。因为软件设计的一致性非常重要,如果十个人各写各的,最后拼在一起,接口不兼容,风格不统一,bug满天飞。而由一个人主导设计,能保证系统的整体性。

这个观点,在今天依然有现实意义。现在很多团队推崇"全栈工程师""小团队作战",其实和外科手术团队的理念是一致的:小而精的团队,比大而全的团队效率更高。

我带团队的时候,也尽量采用这种方式。核心模块由一两个资深工程师主导设计和编码,其他工程师负责周边模块和测试。这样做出来的系统,架构更清晰,代码质量更高,后期维护也更容易。

当然,外科手术团队也有缺点,比如对主刀医生的依赖太大,如果主刀医生离职了,项目就会受很大影响。所以,要做好知识沉淀和文档,避免单点依赖。

为什么要反复读经典

读完这本书,我在想一个问题:为什么一本出版了近50年的书,今天读起来依然觉得很有道理?

我觉得,原因是这样的:技术会变,但人性不会变。

编程语言从汇编到C,到Java,到Python,到现在的AI辅助编程,变了很多。开发工具从打孔卡到编辑器,到IDE,到云原生,变了很多。项目管理方法从瀑布到敏捷,到DevOps,变了很多。

但人的问题,没有变。人还是会高估自己的能力,低估项目的复杂度;还是会在项目延期的时候想加人;还是会在做第二个系统的时候过度设计;还是会追求不存在的银弹。

《人月神话》讲的,不是某个具体的技术或方法,而是软件工程中那些不变的、本质的问题。这些问题,只要还有人在做软件,就会一直存在。

这就是经典的价值。经典不会告诉你具体怎么做,因为具体的方法会过时。但经典会告诉你,哪些问题是本质的,哪些陷阱是常见的,哪些道理是永恒的。

所以,我建议每个程序员,尤其是做了三五年以上、开始带项目的程序员,都读一读《人月神话》。而且,最好每隔几年重读一次。因为在不同的阶段,你对这本书的理解会不一样。

第一次读,你可能觉得它在讲项目管理;第二次读,你可能觉得它在讲人的问题;第三次读,你可能觉得它在讲如何面对复杂性和不确定性。

每一次读,都会有新的收获。

写在最后

那个周末,读完《人月神话》,我坐在阳台上,看着楼下的车水马龙,想了很多。

我想到自己做过的那些项目,哪些成功了,哪些失败了,成功和失败的原因是什么。我想到自己带过的团队,哪些地方做得好,哪些地方还有改进的空间。我想到软件行业的未来,AI会带来什么,哪些东西会变,哪些东西不会变。

最后,我得出一个结论:做软件,说到底是做人的工作。技术是工具,方法是手段,最终决定项目成败的,还是人——人的判断、人的沟通、人的协作、人的反思。

《人月神话》之所以是经典,就是因为它看透了这一点。它讲的不是软件,而是人。

愿每个程序员,都能在焦油坑里保持清醒,在人月神话面前保持理性,在没有银弹的世界里,脚踏实地地做好每一个项目。

最后,用布鲁克斯的一句话结尾:"时间会流逝,但问题永存。"

与大家共勉。