人月神话 —— 1999 年图灵奖获得者 Fred Brooks 作于 1975 年,到现在已经快半个世纪。
计算机行业的发展速度不必赘言,
这本上个世纪的书还有用吗?
有用。
第一次见到 人月神话,是在 2007 年,大连奥林匹克电子广场地下二层鹿鸣书店。
鹿鸣书店专门卖计算机/电子科技书籍,所以我当时一度以为 人月神话 摆错了地方,因为它的书名非常像武侠言情小说,比如古龙的新月传奇,或是张国荣的星月童话。
第二次见到 人月神话,是在 2010 年,当时刚刚考完研,打算把计算机经典书籍过一遍,在所有的推荐书单我都发现了这本书。
看来这本书不是武侠言情小说。
第一次阅读,过程十分痛苦:一部分,源自于这本书故作聪明但并不达意的翻译(比如把 Second System Effect 翻译成 画蛇添足 ),另一部分,源自于这本书面向项目经理和有经验的工程师,我一个在校学生,能读出个屁来。
第一遍读完我只记住了书中那句略显逗逼的话:
无论多少个母亲,孕育一个生命都需要十个月。
之后每次别人催我做什么,我都会用这句话顶回去。
所以这本书并不是给在校学生看的,甚至不是给刚入行的看的,要读懂它没个几年经验是不行的。
要是你还在读大学,有人推荐你看人月神话,那个人一定是个大忽悠,或是知乎买书刷返利。
第二次阅读,是在 2012 年,当时已经实习了一年多,写了一些小项目,也有了一点与人协作的经验,加上阅读的是英文版,阅读体验好了很多。
工作之后又读了两三次,每次都有新的体会。下面我摘录一些让我共鸣的段落:
史前史中,没有别的场景比巨兽在焦油坑中垂死挣扎的场面更令人震撼。上帝见证着恐龙、猛犸象、剑齿虎在焦油中挣扎。它们挣扎得越是猛烈,焦油纠缠得越紧,没有任何猛兽足够强壮或具有足够的技巧,能够挣脱束缚,它们最后都沉到了坑底。 过去几十年的大型系统开发就犹如这样一个焦油坑,很多大型和强壮的动物在其中剧烈地挣扎。他们中大多数开发出了可运行的系统–不过,其中只有非常少数的项目满足了目标、时间进度和预算的要求。
焦油坑(国内又称 屎山),程序员无法绕开的梦靥。即便在 Google 和 Facebook,焦油坑也到处都是,由于自动化测试/持续集成/代码评审/源代码控制等现代软件工程理念的加成,这些项目不会像人月神话的焦油坑一样沉的那么快,此外,这些公司会定期(每年一次或两次)进行代码大扫除,清理尽可能多的焦油。
当任务由于次序上的限制不能分解时,人手的添加对进度没有帮助。无论多少个母亲,孕育一个生命都需要十个月。由于调试、测试的次序特性,许多软件都具有这种特征。
不完全正确。对一些特定任务,添加有领域经验的资深程序员会有奇效,从业近十年,我见过不少案例:几个菜鸡搞了几个月没弄出来,找个大神几天搞定——因为菜鸡见识少,给他们多长时间都搞不出来。添加新人就是在瞎几把搞。
对于软件任务的进度安排,以下是我使用了很多年的经验法则:
1/3计划 1/6编码 1/4构件测试和早期系统测试1/4系统测试
依然适用(不过我不太信国内的公司会花大把时间测试)
在大公司,对大多数项目而言,编码可能是最简单的一环,大部分时间都花在说服领导为啥要做这个项目,以及和同事撕逼抢项目占山头。
向进度落后的项目中增加人手,只会使进度更加落后。
这段话阐述了人月神话(Mythical Man Month)的含义——不能简单的用人月估算项目,人力和时间不能等价替换。
然而在实际中大家还是在往进度落后的项目中增加人手,在我看来,这并不是管理者蠢——甩锅手段而已。而且人越多话语权越大。
软件经理很早就认识到优秀程序员和较差的程序员之间生产率的差异,但实际测量出的差异还是令我们所有的人吃惊。在他们的一个研究中,Sackman、Erikson和Grand曾对一组具有经验的程序人员进行测量。在该小组中,最好的和最差的表现在生产率上平均为10:1;在运行速度和空间上具有5:1的惊人差异!简言之,$20,000/年的程序员的生产率可能是$10,000/年程序员的10倍。
严重低估,最好的程序员和最差的程序员之间能差出天际。
而且差的程序员经常会起到负作用,不少优秀的程序员,都把大把的时间花在排差的程序员的雷上。
我主张在系统设计中,概念完整性应该是最重要的考虑因素。也就是说为了反映一系列连贯的设计思路,宁可省略一些不规则的特性和改进,也不提倡独立和无法整合的系统,哪怕它们其实包含着许多很好的设计。
严重同意。系统设计绝对要找做过类似系统的顶尖资深工程师,不然后果不堪设想。
在开发第一个系统时,结构师倾向于精炼和简洁。他知道自己对正在进行的任务不够了解,所以他会谨慎仔细地工作。
在设计第一个项目时,他会面对不断产生的装饰和润色功能。这些功能都被搁置在一边,作为”下一个”项目的内容。第一个项目迟早会结束,而此时的结构师,对这类系统充满了十足的信心,熟练掌握了相应的知识,并且时刻准备开发第二个系统。
第二个系统是设计师们所设计的最危险的系统。而当他着手第三个或第四个系统时,先前的经验会相互验证,得到此类系统通用特性的判断,而且系统之间的差异会帮助他识别出经验中不够通用的部分
严重同意。我在 Facebook 经手的几个项目基本符合这个规律:开局一盘好棋,中间项目经理各种瞎几把加功能,工程师无脑点头,最后搞出一个四不像。
这种机制在我们项目中碰到别的问题之前,稳定运行了六个月。工作手册大约厚达1.5米!如果将我们在曼哈顿Time-Life大厦办公室里所使用的100份手册叠在一起,它们比这座大厦还要高。另外,每天分发的变更页大约5厘米,归入档案的页数大概有150页。日常工作手册的维护工作占据了每个工作日的大量时间。
这个时候,我们换用了微缩胶片,在为每个办公室配备了微缩胶片阅读机之后,节约了大量金钱,工作手册的体积减少了18倍。更重要的是,对数百页更新工作的帮助–微 缩胶片大量地减轻了归档问题。
难以想象过去的项目文档为了减少体积,需要打印在胶片上。
战略上突破常来自数据或表的重新表达–这是程序的核心所在。如果提供了程序流程图,而没有表数据,我仍然会很迷惑。而给我看表数据,往往就不再需要流程图,程序结构是非常清晰的。
谜之翻译。原文是:Show me your flowcharts and conceal your tables, and I shall continue to be mystified. Show me your tables, and I won’t usually need your flowcharts; they’ll be obvious.大致意思是,好的数据结构要比精妙的算法流程更重要。严重同意。
构建独立小型程序的数据不适用于编程系统产品。对规模平均为3200指令的程序,如Sackman、Erikson和Grant的报告中所述,大约单个的程序员所需要的编码和调试时间为178个小时,由此可以外推得到每年35,800语句的生产率。而规模只有一半的程序花费时间大约仅为前者的四分之一,相应推断出的生产率几乎是每年80,000代码行。计划、编制文档、测试、系统集成和培训的时间必须被考虑在内。因此,上述小型项目数据的外推是没有意义的。就好像把100码短跑记录外推,得出人类可以在3分钟之内跑完1英里的结论一样。
严重同意。
小程序和大规模程序的复杂度根本没法比。
一些领导会把构建原型的时间当成软件开发的实际时间,碰上这种人,要么一起欺上瞒下瞎几把搞,要么赶紧跑。
里程碑有明显边界和没有歧义,比它容易被老板核实更为重要。如果里程碑定义得非常明确,以致于无法自欺欺人时,很少有人会就里程碑的进展弄虚作假。但是如果里程碑很模糊,老板就常常会得到一份与实际情况不符的报告。毕竟,没有人愿意承受坏消息。这种做法只是为了起到缓和的作用,并没有任何蓄意的欺骗。
严重同意。
明确的里程碑对于按时交付极其重要。一个功能,要么完成,要么未完成。90% 完成是扯淡的说法。(我见过无数次,估计 90% 完成,然后花了两倍时间完成剩下的 10%)
Thomas J. Watson讲述了他年轻时在纽约北部,刚开始做收银机推销员的经历。他带着一马车的收银机,满怀热情地动身了。他工作得非常勤奋,但是连一台收银机也没有卖出去。他很沮丧地向经理汇报了情况,销售经理听了一会儿,说道:”帮我抬一些机器到马车上,收紧缰绳,出发!”他们成功了。在接下来的客户拜访过程中,经理身体力行地演示了如何出售收银机。事实证明,这个方法是可行的。
严重同意。
我自己大量的经验和技能源自于观察和模仿身边的高级/资深工程师,很多东西书里面是学不来的,更不要提什么网课(刷粉卖课的请自动对号入座)。
这也是疫情之后的一大问题,新人入职后很难融入项目,老人也不会主动传授新人技能。
现实中,流程图被鼓吹的程度远大于它们的实际作用。我从来没有看到过一个有经验的编程人员,在开始编写程序之前,会例行公事地绘制详尽的流程图。在一些要求流程图的组织中,流程图总是事后才补上。一些公司则很自豪地使用工具软件,从代码中生成这个”不可缺少的设计工具”。
45 年后依然如此。没人去画流程图,UML 更多是给不懂技术的人展现工作量复杂度而已。
最后,回到一开始的问题:一本上个世纪,近 50 年前的计算机书,还有用吗?
有用。因为 45 年前程序员踩的坑,我们现在还在继续踩。
在我看来,新手程序员和资深程序员的最大区别,在于绕坑技巧。
这本书讲的就是软件开发里的坑。
少写点坑,既为自己,也为他人。