引用中的内容是我自己的理解/想法。

全书看下来,虽然里边的某些细节过时了,但整体思想非常先进,作者说的是项目管理和软件工程的本质。这本书确实值得每年读一遍。

人月神话

人员增加会增加沟通成本:培训及交流。其中培训无法分解,其工作量与人员数量为线性关系;而交流的工作量会按照n(n-1)/2递增。

系统测试的进度安排往往最不合理,作者对进度安排的经验法则:1/3计划,1/6编码,1/4组件测试,1/4系统测试。

然而,很多公司甚至没有测试。

为了保住进度而添加人力,需要考虑重新进行培训、划分任务、系统测试等工作,最终情况会非常糟糕。(Brooks法则:向进度落后的项目中增加人手,只会使进度更加落后。)

项目的时间依赖于顺序上的限制,人员的最大数量依赖于独立子任务的数量。

外科手术队伍

最好和最差的程序员效率可以相差10倍之多。一拥而上的开发方法成本高而效率低。

40年前的程序员效率都能差10倍,现在这个比值怕不是负数。

但对大型项目而言,小型精干的队伍意味着进度非常缓慢,要想完成巨大的工作量,需要外科手术式的队伍。

与一拥而上的方式相反,由一个人完成问题的分解,其他人给与支持的做法更好。

外科医生所代表的角色,应该是一个强有力的技术/项目领导。我有幸参与过一个非技术出生的领导带领的开发,确实…是一场遭难。

贵族专制、民主政治和系统设计

作者认为系统设计中的概念完整性最应考虑,为了设计上的连贯宁可省略一些特性和规则。

易用性是功能和概念复杂度的比值,简洁直白的设计需要概念上的完整性。

因此必须由一个人(或少数默契的人)来保证概念完整性(编写需求/设计文档)。

也就是产品经理/项目经理了。

在设计的时候,实现人员应该做什么呢?作者的简要答案是:设计完成后再雇用实现人员。

作者强调,因为时间进度和想要让实现人员参与设计的愿望是致命危险。(确定需求/规范后,开发的创造性并不会减弱,往往还会增强,所以不必认为设计师剥夺了开发人员的创造力。)

作者举了他自己的例子,我也有幸亲身经历过,当所有开发人员都参与需求/设计文档编写时,整个项目混乱不堪,而文档形同虚设。

实际上,需求,设计,实现三个部分,往往可以同时开始并发进行。

例如,设计有了模糊想法后,开发可以做技术预研,设计数据流,表结构,制作所需工具等。

项目经理/产品经理,开发人员,测试人员各有各的作用和阶段。

画蛇添足

开发第一个系统时,架构师倾向于精炼和简洁,并会谨慎仔细地工作。开发第二个系统时,架构师充满信心,往往会添加很多修饰功能和想法,使系统变成一个“大馅饼”。

避免方法是,尊重有两个以上系统经验的架构师的决定,并警惕特殊诱惑。

俗话说,步子大了容易扯着蛋。遥想当年XP系统大获成功,Vista系统想要全部使用C#开发,然而真开发出来估计现在的电脑都够呛。

贯彻执行

要确保所有项目人员了解并实现统一的决策,常见的做法是文档。

作者把会议分为周例会和年度会两个级别。周例会每周半天,由架构师主持,实施和市场人员参与,主要做出迅速的结论,使工作继续下去。年度会每半年一次,用于解决周例会遗留堆积的问题。

作者接下来讲到了通过电话快速沟通,在如今就是微信了。作者也讲到了测试的重要性,这个现在是标配了。

为什么巴比伦塔会失败

作者花了不少笔墨介绍了打印、分发文档的办法,现代的办法当然是在线文档协作平台了。

当年真是不容易,所有文档要打印出来然后分发,作者说所有打印文件比大厦还高,如今直接在线就解决了。

关于产品负责人和技术主管之间的关系,作者给了三种常见的关系:

  1. 两个角色同属同一个人。这种模式下负责人很难面面俱到。

  2. 产品负责人作为总指挥。这种模式需要产品负责人为技术主管建立权威。

  3. 技术主管作为总指挥。这种模式就是外科手术队伍。

胸有成竹

根据研究,工作量与系统规模是指数关系,这个指数大约是1.5。

书中的公式:工作量 = 常数 x 指令数^1.5 总结章节说Boehm的数据是1.05到1.2

根据一些团队的数据,每周仅有50%的时间进行实际的编码调试工作,其他时间被会议、请假、各种公司事务等占据。

削足适履

作者这里讲了程序的空间成本和时间成本,并举了很多例子。不过例子中最大的内存是2M——令人感慨。

最后提到,技艺的改进最终往往是战略上的突破,例如新的算法。

对程序来说,核心来自数据的表达,数据的表现形式是编程的根本。

最后这句深以为然,良好的数据结构设计,程序就成功了一半。

提纲挈领

文档的框架:目标(资源、约束、优先级),技术说明(性能,手册等),进度,预算,人员组织图等。

Conway定律:人员组织结构会反应到系统设计的架构中。反过来看,如果系统设计需要自由变化,项目组织架构也要为变化做好准备。

也就是说,什么样的人员组织,就会造出什么样的系统结构。如果人员组织混乱,结果必然也是混乱的。

未雨绸缪

大多数项目的第一个开发的系统并不合用,解决的办法是重新开始——全部丢弃或一块块地实现。

没人能无所不知面面俱到,持续重构是必要的。

因此,为舍弃而计划。

计划时就要考虑到舍弃/替换,模块化必不可少,接口设计很重要。

唯一不变的就是变化本身。尤其是与硬件相比,软件开发人员面临着永恒的需求变更。为变化作准备,总比假设变化不存在要好得多。

应对变更的方法:模块化,可扩展接口,接口设计及文档,调用队列或表驱动,自动生成文档,版本管理及变更日志等。

Cosgrove的见解:设计人员不愿提交尝试性的设计文档,不仅是因为惰性和时间压力,还因为不愿将自己暴露在每个人的批评之下。

系统变化时,管理结构也要进行调整。管理和技术应具有互换性。这其中的障碍是社会性的(管理和技术平等,而非管理更高人一等)。

这里说的应该还是以技术领导为核心的外科手术队伍。同时也有一些具体的建议,如职级薪资对等,取消管理头衔等。人员组织架构真是个永恒的话题。

缺陷修复总会以固定几率(20%-50%)引入新的bug。

众所周知,程序员每天的工作就是写bug。

干将莫邪

这一章讲了一些工具方法,如开发机和测试机的区分,使用稳定的虚拟硬件优先进行开发测试工作,对版本和文档的管理(最终发布由经理负责,开发与发布分离),性能分析平台,使用高级语言和工具提高效率等。这些如今都是标配了。

然而我曾经用到的某自研硬件一直没有纯软件虚拟的版本,甚至某些硬件无源码,导致开发调试异常困难。

整体部分

大多数致命/难以察觉的bug的根源:系统各部分的概念不一致。(概念完整性的重要性)

在写代码之前就提交测试规格说明,和自上而下的设计,是两个保证系统整体性的办法。

作者提到的另一个办法是结构化编程,也就是高级语言了。关于goto语句,我的看法是:不一定一定不能用。

祸起萧墙

这一章讲到了进度控制和项目管理的一些内容。例如对于项目经理可以解决的问题,老板不要做出安排。关键路径法,PERT图等。

另外一面

对于用户,以及未来的开发者而言,优秀的文档不可或缺:

描述性总结性内容。目的,环境,输入输出等。

测试用例。正常,边界,异常。

详细设计。流程图,结构图,算法描述,文件结构,数据流,可预见性的修改的讨论,等等。

作者认为流程图被鼓吹的过了。如果没有复杂的逻辑,只是纯线性的流程,那确实用不着流程图。

作者也讲了自文档化的一些方法,如变量命名,代码格式化,大段的文件头注释等,这些现在也是基本操作了。

没有银弹

作者将软件开发分为了根本的次要的两部分:

  • 根本任务指设计方面:数据集合、数据关系、算法及调用流程等,这些都是抽象的概念。
  • 次要任务指编码方面:将设计翻译为编码实现。

作者认为编码工具的进化可以解决次要任务,包括高级语言,图形化编程,AI辅助,程序验证等方法。

但解决根本任务很困难,可能的方法是:购买现成软件,快速原型,增量开发,以及依靠优秀的设计人员。

总之,作者认为软件系统有其固有的复杂性,与语言工具等实现方式无关。 从这里也看到了原型工具、敏捷开发等思想,作为70年代、50年前的书,属实牛逼。

20年后的《人月神话》

核心观点——概念完整性和结构师。20年后,作者更加确信,概念完整性是产品质量的核心。

作者认为瀑布模型有一定的问题,因为软件必然不断迭代,系统也在不断的演化当中,所以瀑布模型应该是可回退的。增量开发、快速原型、每日构建,是作者提到的更好的方式。

也就是敏捷开发了。这里的增量开发模型是对瀑布模型的改进,而现在所谓的敏捷开发只强调快,忽略了文档、测试等质量手段,个人认为是有问题的。

作者之前认为团队应该了解所有的细节,但20年后,作者确信,隐藏细节,更能提高软件设计水平。

隐藏细节,也就是OO的思想了。隐藏细节会倾向于提升接口质量,也让其他人不关心内部实现,更易于多人合作。