原文地址:blog.islasher.com/2019/05/29/前端
最近在读《人月神话》,这是一本成书于 1975 年的关于软件工程的书,考虑到计算机领域的飞速发展,这本书真的能够算是计算机历史上洪荒时代的做品了,然而虽然时代久远,可是这本书仍然被无数人推荐必读,可谓畅销数十年。既然如此,做为半路出家的软件开发工程师,我固然要拜读一下了。程序员
我手上这本是 32 周年中文记念版,这本书主要有两个版本,75 年的第一版和 95 年的二十周年版,主要的差异是 20 周年版添加了没有银弹等四个章节。这个 32 周年中文记念版应该就是基于二十周年版的一个翻译版本,32 周年估计是中文出版商的一个宣传噱头。算法
固然,版本不重要,书的内容是主要的,那么书的主要内容是什么呢?编程
书名《人月神话》中的人指的是人力,月指的是工做时间,主要的意思是人月做为一种衡量软件开发工做量的单位有其误导性,举例来讲,1我的能够在10周以内作完的项目,10我的不必定能够在1 周以内完成。其实在书中做者更进一步地指出,单纯地增长开发人力,不只不能对应地减小项目的开发时间,甚至有可能增长开发的时间,由于更多的开发人员须要更多的交流沟通,这部分的时间成本也是很可观的。固然,这本书不只仅是论述这一个的观点,从这个观点出发,本书还介绍了不少其余的大型软件工程的规律和最佳实践。接下来,我将一一介绍该书每一章的主要内容,算是个人读书笔记吧。网络
第一章做者将软件系统开发比做吞噬了恐龙、剑齿虎等史前巨兽的焦油坑,许多大大小小的团队被软件开发的焦油坑所吞噬。架构
做者首先介绍了变成系统产品的演进,指出程序、编程系统、编程产品、编程系统产品几个概念间的区别,其中只有编程系统产品才是真正可用的面向用户的产物。编程语言
而后做者分别介绍了编程的乐趣和苦恼,固然这部分见仁见智,人类的悲欢毕竟并不相通。工具
第二章做者主要介绍了软件开发项目在进度安排上常常出现的问题。也就是书名人月神话的出处。首先,因为咱们对项目开发的进度估计过于乐观,咱们估计出来的工做量一般会低于实际须要的工做量,尤为是对测试所需时间的安排经常是进度估算失误的重灾区,这应该是不少有经验的开发者会在估时的时候乘以一个固定的系数的缘由(1.5 或者 2 甚至 3)。其次人员和时间的关系并不是老是反比的关系,若是任务属于能够彻底分解的理想状态话,是可能达到人员越多时间越少的反比效果的,可是,任务越复杂也就越难以分解,那任务中的沟通需求就会占用更多的时间,甚至可能致使人员越多,项目所需的时间越长。进而能够得出结论:当进度落后的时候,无脑增长开发人手可能并不能加快开发进度,甚至有可能致使进度更加缓慢。向进度落后的项目中增长人手,只会使进度更加落后,这也被成为 Brooks 法则。开发工具
基于上一章的结论:更大的队伍不必定能带来更快的开发进度,那么,问题来了,什么样的队伍才是合适的呢,小团队当然高效,可是你不能期望一个 20 人的小团队在合理的时间内去开发一套完整的操做系统吧?做者在这一章里给出了解决方案:将大项目合理地划分红更小的系统,各个外科手术队伍分别开发这些更小的系统。固然外科手术队伍只是一个小团队的方案,具体细节我认为已经再也不具备很大的参考价值,可是精干的小型队伍这一理念仍然颇有价值。测试
这里我联想到大企业病的问题,企业规模的扩大必然会致使人浮于事、效率低下的问题,因而现在一些大企业都会将企业的业务分割给各个小团队来负责,一个很著名的例子就是亚马逊的两个披萨的原则,有效地避免了大团队的致使的低效问题。
接上一章:短小精干的队伍带来了新的问题,如何对大项目进行合理的分割?这依赖于一个很重要的前提:概念的完整性,具体而言是指在项目的开发过程当中,应该有一个一以贯之的明确的目标和清晰界定的范围,不然随着人员的变更和时间的变迁,这个项目可能会逐渐演变成四不像(我最近在参与的一个项目就是如此,人员的变更致使了项目功能、技术栈的变迁,项目的周期被极大地拉长)。而如何产生概念的完整性呢?答案是贵族专制,少数人决定一个概念并厘清边界,而后据此分割执行,不然人多嘴杂,必然会致使项目在讨论中变成奇怪的样子。
这一章主要是告诫系统设计师们,不要过分设计,尤为是在第二个系统(第一个系统完成后开发的第二个系统)中,不要过分自信,保持警觉,避免初始的概念和目标获得充分的体现,而不让一些次要的功能喧宾夺主。(是否是能够说是保持初心?)
概念的完整性不只仅要在专制的贵族和系统设计师这一层面上充分传达并理解,在系统的实现人员中,也要充分传达。在不理解业务背景的状况下,开发者也很难写出优秀的代码。做者在这一章介绍了不少方法以达到这一目的,包括规格说明手册、形式化定义(个人理解是 Web 开发中的原型图同样的存在)、会议和大会、多重实现(举例:假如JavaScript只有 V8 一个引擎,那若是引擎实现与 ES 标准不一致时,改标准比改引擎实现要容易得多,可是有多个引擎时,与标准不一致的引擎就必须修改本身的实现,从而保证了标准文档的贯彻执行)、电话日志、产品测试。
固然这些方法在现在可能已通过时了,可是经过种种方式保证软件开发的进度不偏离最初的概念和目标,是实现项目成功的重要保障。实际上在当代的软件开发流程中也有一些措施来实现这一目标,如敏捷开发中天天的站会。
咱们都知道巴比伦塔的失败是由于上帝给了人类不一样的语言致使的沟通失效。那么在大型项目中如何保证沟通的顺畅呢?做者详细介绍了项目工做手册的内容、发布方式、更新方式等等,可是当年他们仍然是纸质文档,后来才进化成微缩胶片,现现在咱们有了更方便的字处理工具和文档协做工做,于是这部分的建议就用不上了,可是保持文档的更新和有效获取仍然很重要,不然不一样的人对需求的记忆和理解可能出现误差、进度可能会出现错位等等,致使项目的开发进度被拖慢。
相应的,外科手术队伍也能够有效地下降交流的难度,毕竟人越少,沟通越便捷,这样一来,整个项目经过合理的人力划分和职责限定,就会自上而下造成一个树状结构。做者特意论述了团队中技术负责人和产品负责人的分工与关系,可是我很难将做者的观点映射到当代的开发团队中来,只好略过。
这一章是介绍对变成效率的量化的,种种量化方法将程序员的生产效率细化到指令/年(很差意思,他们当年是写汇编的,高级语言那个时候还不多)。我以为这个实际上意义不大, 可是仍然是一个有趣的参考,最终的结论是工做量=常数*指令数量^1.5,也就是说工做时长跟代码数量的指数关系而不是线性关系,随着代码数量的增加,工做时长是指数级上升的。
这一章主要是讲程序大小的,包括代码大小和内存占用的大小。代码大小如今应该已经不是软件开发的重要考量了吧?可是这一问题在现在的 App 开发中应该也有,虽然不少公司绝不在意占用用户几百 M 的存储空间……固然在前端还存在另一个问题,即过大的代码包会耗费过多的流量,尤为是在早年的移动端开发中,那时候流量很金贵,如今这样的顾虑逐渐变少了,可是一直都存在的顾虑是代码的加载速度,固然这一问题也能够经过分包懒加载来解决了。总而言之,当年的那些经验在前端领域适用的已经很少了,可是在客户端领域可能仍然适用。
内存固然始终是一个问题,可是应该主要考虑不要发生内存泄露的问题,自动的垃圾收集能够解决大部分问题了吧?计算机硬件的进步真的极大地下降了软件工程的难度。
这一章主要是介绍文档的重要性,对于项目经理来讲,文档是很重要的,它包含了项目目标、产品的技术说明、时间、资金预算、工做空间的分配和人员的组织结构。文档的重要性在于首先,明确的书面记录会让分歧更明朗,使混沌的状态变得清晰、明确;其次,文档下降了沟通的负担;最后,文档便于项目经理跟踪项目的进度状态。
这对于程序员来讲多是一个十分不幸的消息:系统必然会面对各类变化,你开发的软件必然会在修修补补中变得面目全非,最初的设计必须在各类妥协中打上各类丑陋的补丁。不管是多么良好设计的系统,都会走向混乱,区别只是这个过程的快慢而已。所以,好的设计会让这个过程尽量地慢,尽量地不那么痛苦,咱们能作的就是眼光尽可能放长远,让咱们的代码尽量地具备高可扩展性而且易于维护。并且,在面对不得不进行的重构时,作好心理准备。
这一章一言以蔽之:磨刀不误砍柴工。好的开发工具和开发环境能够极大地提升开发效率,固然,做者在这一章中介绍具体方法、工具、语言等已经不适用于咱们这个时代了。
咱们将总体的项目分割成更小的部分来开发,可是最终咱们仍然须要将这各个部分合并成一个总体对外提供服务,这就带来了新的问题:各个部分可能独立工做良好,可是当合并成总体时反而致使了新的系统级的 bug。这就要求咱们在设计系统结构时精心设计,减小各个部分间的耦合,各个模块的独立性越高,系统级的 bug 的可能性就越低。此外做者在本章还介绍了一些测试的方法,这部分我不太了解,并且测试的方法、流程可能也已通过时了,毕竟咱们已经有了更好、更方便的版本控制工具和测试流程,可是其中一些理念仍是有意义的,如重构过的模块在合进总体的时候仍然须要对系统总体进行测试,而不是仅仅测试重构过的模块。
项目的进度颇有可能由于各类各样不可避免的因素滞后,这是极可能出现的状况,有的时候甚至可能不知不觉就会落后,难以察觉地落后一天、半天,累积起来整个项目的完成就会遥遥无期。避免这种难以察觉的落后的办法是制定里程碑,将项目的进度安排划分红一个一个阶段并清晰地界定各个阶段须要完成的任务,里程碑边界的清晰、明确十分重要,含糊的里程碑跟没有里程碑没有区别。“其余部分反正会落后”是一种很可怕的想法,是须要项目经理极力去避免的。此外,一线经理不要害怕向老板反映进度落后的真实状况,同时老板遇到进度落后时也不要越俎代庖代替一线经理作决定,不然一线经理会倾向于不报告真实信息。
除了面向开发者的项目文档和说明以外,软件开发也须要编写详尽的面向用户的文档,文档须要包含软件的目的、运行环境、输入输出范围、实现的功能和使用的算法、输入输出的格式、操做指令、选项、运行时间、输出结果的精度和校验方式等等,除此以外,还须要充分的测试用例来讲明程序的功能和边界。另外,对于其余开发者而言,须要提供项目开发所须要的文档(相似 Github 上 how to contribute 的部分吧)。
没有银弹是一篇颇有名气的文章,这篇文章发表于1986年,同时这也是一个广为流传的软件开发的原则,这一原则是指,在将来的十年内(1986-1996),没有任何技术或管理上的进展,可以独立地许诺在生产率、可靠性或简洁性上去的数量级的提升。做者作出这一论断的前提是:全部软件包括根本任务和次要任务,根本任务是打造构成抽象软件实体的复杂概念结构,次要任务是用编程语言表达这些抽象实体。不少技术或管理上的进展在解决次要任务上发挥了巨大做用,可是在主要任务上却进展寥寥,做者进而分析了形成这种境况的缘由,分别从复杂度、一致性、可变性、不可见性论述了他的观点,我在此不作总结了,就我我的的理解而言,软件本质上是须要完成业务需求的,而业务需求则来源于商业决策、社会、文化等等人类文明系统的各个方面,甚至能够说是软件工程是对现实世界的模拟,这个现实的社会系统如此复杂而且变化无穷,以致于任何一种架构设计都不可能囊括全部的可能性,因此,需求必然会变动,没有一发银弹能够应对全部的需求。软件开发的难度不在于开发,而在于设计一个完美的软件架构,而这个架构依赖于对业务的熟悉和前瞻性的展望。
做者进而提出了解决核心问题的方法:首先:不开发软件,不开发软件就不会有问题……买一个就行了(我晕,这也算办法?不过虽然这个方法有些无厘头,可是其实预见了微软为表明的薄膜包装软件的兴盛,由于当年的软件大可能是客户定制化开发的,而不是售卖通用的软件解决方案);其次,快速地搭建原型(Demo吧?),从而更好地肯定用户的需求;第三,增量开发,我以为这个方法最靠谱,也就是把软件当作是生长的有机体,而不是一个建好就能够的建筑,软件会不断成长,先从简单的核心开始,一边交付一边开发,不断增长新的功能,一边增长新的功能,一边重构已有的部分,其实这跟咱们目前的不少项目的开发模式很类似了;最后,培养优秀的设计人员……讲真,我以为这个也过高远了……不能解决眼前的问题,固然,这是有意义的,培养出优秀的系统设计师(如今应该说是架构师?)是十分重要的,可是,这也只能在实践中培养吧,毕竟纸上谈兵是确定不行的。
这一章是《没有银弹》这篇文章发表10年后(1996年),做者对针对这一话题的讨论的一些回应与评价,其中也包括对一些新兴技术的讨论,颇有意思,其中的不少观点在现今仍然不时在网络上出现。此处不一一列举了,文章网上均可以看到。在这篇文章中,做者对一种新的软件开发趋势寄予了比较高的指望:重用,也就是咱们如今说的复用,我以为这一趋势成就了今天的开源社区。
固然做者仍然坚持认为,子弹没有出现。
这一章也是20周年版本新增的内容,20年的发展让第一版的一些观点变得过期,可是仍然有很多观点仍然适用,于是做者在这一章里把以前的每一章的主要观点都抽离出来,并对已通过时了的观点作了说明,能够说这一章是整本书的精华了吧,具体内容我就不列了,做者对每一章的总结与我在上面的整理也有很大的不一样,我只不过是将本身的理解整理出来,做者的总结则更加细致全面。总而言之,十分推荐。
这一章很长很长,算是一篇单独的文章,讨论了不少软件开发相关的技术和管理思想,其中包括:
这本书真的是够老了,已经40多年了,很难想象一本计算机领域的书可以畅销这么久。可是读完以后我发现畅销是有道理的,虽然书里不少概念、例子、技术都属于上古时期的遗迹了,可是书里介绍的软件开发的困难、管理的思路,仍然能够在今天的软件开发中找到对应的场景,原来我今天遇到的困难早在洪荒时代就已经被讨论而且提出过解决方案,并且今天的一些软件开发的流程、管理方案、团队组织等等均可以看到当年那些解决方案的影子。因此读这本书仍是颇有收获的,能够理解实际开发过程当中遇到的困难和这些困难的应对方法,不管你是在开发团队中担任什么角色,是产品经理仍是开发者抑或技术负责人,我都十分推荐这本书。 读完这本书还有一个感觉:国内的软件开发行业真的是十分落后,简直是小做坊式的开发,但愿每个老板、项目经理、产品经理、开发者都能读一读软件开发相关的书籍,了解软件开发特有的规律,不要再摸着石头过河了。 固然,这本书毕竟已是老古董了,读的时候有不少地方会很难理解,建议跳过这些细节,关注那些细节背后的原理和规律,尤为是十分推荐对照着 《人月神话》的观点:是与非 这一章来读,能够起到提纲挈领、高屋建瓴的效果(后悔本身读到后面才知道有这么一章)。