笔者已经看过的经典书籍里,对于这本的阅读可以说是最坎坷的了——17年买入,18年1月份才翻开看了四章之后不知何故放弃,直到2019年的1月19号再次打开,而且非常巧合的是2018年打开此书的时间也是1月19号,所以是整整一年之后再次翻开这本经典之作。
1. 前言
笔者能力有限,不敢称呼本文为读后感,标题是为了维护一致性,本文更像是一篇读书笔记。
随着阅读量的增长,笔者慢慢开始坚信——除了那种《算法》,《TCP/IP详解》这样的纯工具书外,诸如《Clean Code》,《重构》这样的经典之作,在这些作品中,除了正确的做事方法外,你都会非常清晰地感受到作者的做事态度,他们的为人处世之道,对世界的认识和理解,都会或有意或无意地从字里行间流露出来。作为读者,尤其是无缘获得大师耳提面命机会的普罗大众来说,这无疑是一种天大的恩惠。
今天所提到的《人月》正是其中的佼佼者。作为畅销四十余年的不朽之作,书中每一章都非常短小,但内容丰富,字字珠玑,让人看着没有心理压力。作者的深刻反思与总结,并以准确而优美的文字进行描述,这一份思维深度和文字底蕴,真是让人叹为观止。正如第一版序言里说的:本书是一部文集,而不是教材。
虽然时隔多年,但其中指出的错误现象在今天依然是屡见不鲜。这也正印证了黑格尔所说的—— "我们从历史中得到的唯一的教训就是我们从没有从历史中得到过教训"。
2. 感悟
2.1 焦油坑
本书以“焦油坑”一章开篇,这一得名于自然界的产物,远古时代困住了无数的洪荒巨兽。而作为人类历史以来,甚至未来都会是最复杂的一项工作——大型软件开发,自诞生以来似乎也被"焦油坑"所困扰,顺利走出来的寥寥无几,绝大多数都在其中苦苦挣扎,表面上看起来没有任何一个单独的问题会导致困难,每个问题都能获得解决;但是当它们纠缠和积累在一起的时候,团队的行动就会变得越来越慢。随着时间的推移最后慢慢陷入绝望最终导致项目无疾而终。
但同时作者也在本章中也总结了编程的乐趣——创造全新的事物,并且该事物对他人是有用的;而且在创造的过程中你需要不断地进行学习,从而获得持续学习的乐趣等等。这些快乐不仅满足了我们内心深处进行创建的渴望,而且还唤醒每个人内心的情感。
任何事物带来快乐的同时,不可避免有着随之而来的苦恼,于编程而言——追求完美;由他人设定目标,提供资源和信息,寻找琐碎的BUG等等。
2.2 人月神话
本书所包含的十几个章节标题中,被单独拿出来作为书名,意义自然不同一般。项目延期之后,人们的第一反应就是堆人,但往往会导致更严重的滞后,而本章节作者就用一系列的数据和严谨的推论告诉读者这种条件反射只会火上浇油。人和月的互换只能是一个神话,就像“一个孕妇怀胎十月,十个孕妇怀胎一月就能生孩子”。
作者在本章节中以其丰富的经验对进度安排给出指导建议:
- 1/3 计划
- 1/6 编码
- 1/4 构件测试和早期系统测试
- 1/4 系统测试,所有构件已完成
2.3 概念完整性
最好的团队组成应该是类似外科手术队伍结构——领头羊只能有一个,其他人辅助它来完成任务。没有高低贵贱,只是分工不同。这样我们能够获得减少沟通,提交生产效率等等诸多好处,而且最重要的是我们将获得概念的完整性。
将设计交由一个人或者非常少数忽悠默契的人来完成才能保证概念的完整性,而将体系结构,设计实现和物理实现相分离则是获得概念完整性的强有力方法,这一点契合了我们现在已经作为常识的“关注点分离”理念。
在本话题的相关章节中最让笔者印象深刻的是作者在第四章开篇序言中就以建筑业举例——建筑大师需要:
- 首先融会贯通其前辈建筑师的成果
- 同时完全掌握他们那个时代的建筑技术
- 最后还要能够恰如其分地运用这些技术,避免轻浮地炫耀,并绝不花哨。
以上三点,笔者觉得不仅仅适用于建筑行业,在任何行业的有志之人都需要谨记这三条法则,才能创造出杰出之作。那些喊着创新,革命的,借用郭德纲的一句话——"拿着痰桶炒菜,你打算自己享用吗?"
2.4 巴比伦塔的失败
作者将巴比伦塔失败的原因之一归结于缺乏交流,缺乏组织。而我们能从中得来的教训之一在大型软件开发,要无比重视交流的重要性。本书初版之后四十余年的现在,人们所发明的很多技术和规范很大程度上都是为了加强“交流”,减少不必要的交流,增加交流的效率——团队组织的目的是减少所需的交流和合作的数量。制定规范也是。
正如作者直接在文中以文字形式表达的“交流和交流的结果——组织,是成功的关键”。但我们要谨记交流和组织的技能需要锻炼,相关经验的积累和能力的提高同软件技术本身一样重要,不要因为一时的失败而放弃,也不要因为成绩而固步自封。
对于交流,文档这一工具起着非常大的作用,例如项目经理的基本职责是使每个人都向着相同的方法前进,所以其主要职责是沟通,而不是做决定。因此他需要大量的文档来极大减轻他的负担 。
2.5 未雨绸缪
人们总是希望一切的事情都尽在掌握之中,所以总是试图在制定完美计划之后一路顺风顺水地执行下去。但是软件维护是一个提高混乱度(增加熵)的过程,所以出现前进两步,后退一步;甚至前进一步,后退一步都是很正常的。而且随着维护的深入,会发现用在修复原有设计上瑕疵的工作量越来越少,而早期维护活动本身所引起的漏洞的修复工作越来越多。正如大思想家斯宾塞·约翰逊曾经说过“唯一不变的是变化本身”,我们要为变更设计系统,为变更计划组织架构。
2.6 整体部分
在设计的过程中,我们要做到自上而下的设计,在设计的每个步骤中,尽可能地使用级别较高的表达方法来表示概念和隐藏细节,直到必要的时候再进一步的细化。文中的这段话让笔者想起SICP中教授们试图传达给学生们的一个屠龙之术——“推迟做出决定的时机,因为只有尽可能地退出做出决定的时机,你之后的行为才不会被当下做出的决定所影响,所阻碍”。而且细节的抑制使得结构上的缺陷更加容易识别。
作者在本章中还详细给出了控制变更的最佳实践——阶段化,定期变更。
- 直到下一次定期发布前都使用快速补丁。
- 而在当前的发布中,其将已经通过测试并进行了文档化的修补措施整合到系统平台中。
另外作者还给出了系统集成测试阶段的最佳实践——一次添加一个构件。我们总是倾向于将所有的构件全部组合到一起再测试,但是,请拒绝诱惑。正如《重构》里说的,我们要遏制住心魔,小步前进!
2.7 祸起萧墙
进度落后往往并不是因为大灾难,而通常只是因为那些仅仅会导致延迟半天到一天的事件的堆积最终致使整个进度延期一年。
对于里程碑的确立,必须是具体的,特定的,可度量的事情,能够清晰定义。不能清晰定义的里程碑是难以处理的负担。
关键路径技术是衡量是否延期的重要方法,每个人都要尽量让自己的工作远离关键路径。
老板要克制住越俎代庖做决定的心魔,那样才能得到真实的项目状态报告。这里让笔者联想到家庭教育,家长总是希望孩子能说出自己的心里话,但是孩子说出后又横加指责,不问孩子的意见而横加干预,最后又去责怪孩子什么话都憋在心里不说出来。
2.8 另外一面
试图维护不同文件之间的同步关系,是一件非常费力不讨好的事情。
对于程序而言,"合并文档"才是比较好的解决方案,而且最好做到自文档化。感觉这些应该是类似代码里的注释,以及诸如Swagger等等。
2.9 没有银弹
这涉及到软件工程中的根本和次要问题。复杂性,一致性,可变性以及不可变性这四个根本特性决定了软件开发中很难出现银弹。而且作者甚至觉得人们对银弹的追求,有点类似于古往今来对炼金术的追求。
但作者同时指出面向对象这一颗铜弹有前途——强制的模块化和清晰的接口等等可以极大增加效率。
3. 二十年的《人月神话》
1995年左右,在《人月神话》20周年纪念版本中,作者对过去20年来读者非常关心的几个问题进行了详细的叙述——“哪些在当时就是错误的?哪些是已经过时的?而哪些是软件工程领域中新近出现的?”
正如本章开头所说,《人月神话》是关于人与团队的书,所以时至今日,过去了四十余年,书中的内容依然毫无过时的迹象。不过作者依然对书中的观点进行了详细的梳理,先是列举出依然适用的观点——诸如:
- 软件研发过程中概念完整性的核心地位(诸如MAC的界面上的概念一致性,即使第三方应用也有着非常相似的界面,这对用户来说是非常棒的体验);
- 体系结构和设计实现,物理实现相分离(感觉非常类似于现在被视为尝试的"关注点分离"原则)等等。
之后作者也大方地承认在诸如信息隐藏方面的错误判断。真的是让人感概大师的胸襟。
不过最让笔者动容的是作者在章节末尾表达出来的旺盛好奇心,以及面对新知识时候的欣喜,真的是让人敬佩不已。