【读书笔记】人月神话(一)

news2025/1/13 7:32:54

后续文章都是从本人的知乎博客上搬迁过来。

在软件领域,布鲁克斯博士的《人月神话》是一本关于大型项目管理的经典之作。这本书不仅对每一个软件行业的项目经理(PM)来说是一本必读读物,对每个软件行业的参与者(程序员,测试人员或者是创业者),都是一本不容错过的经典。书中贯穿整个软件开发流程对从业人员都是极有帮助的。

虽然这本书讲到的项目是几十年前开发大型服务器相关项目,但是里面对研发工作的创造性思维,到今天还是有指导性意义的。本人在通读了两遍之后,对项目管理和团队管理上得到了不少的启发,想做一点记录,和各位共享。相信以后还会多次精度其中的章节,以期得到不同的感悟。(书中的斜体是从书中摘录出来)

一. 人月神话

书在一开头就提到了软件工程管理中的一个关键问题:人/月。在项目管理过程中,这个指标实际上是有一些误导作用的,给人的感觉是项目取决于两个关键因素,人和时间(月),而这两个指标仿佛看上去就是一个正比关系,增加人,减少月;减少人,增加月。于是就造成一种简单粗暴的项目管理办法,当项目进展受阻或者进度落后时,直接往项目中增加人手,仿佛这样就可以直接解决问题。而书中直接就针对这个问题指出:

“用人月作为衡量一项工作的规模是一个危险和带有欺骗性的神话”
并提出Brooks法则:“想进度落后的项目中增加人手,只会使进度更加落后。(Adding manpower to a late software project makes it later )”
这里背后的一个原因是,随着软件开发过程越来越成熟,很多人没有将软件开发当成一种创造性的脑力劳动,而逐步地将软件工程当成了劳动密集型的工程,软件规模和工作量是一种线性增长的模型。

即使是劳动密集型的工程,也不是一个简单的换算关系,设想建设一栋大楼,100个工人建一年,不是说36500人一天就可以搞定的。更何况对于软件工程这样一件含有大量创造性工作在内的脑力工程。

章节中提到,我们在进行工作量估算时,往往省略了团队规模扩大之后的一个重要事件成本——沟通成本。而沟通成本由两个部分组成:培训和相互的交流。每个成员需要进行技术、项目目标、总体策略以及工作计划的培训。这种培训是不能分解的,因此这部分增加的工作量随人员的数量呈线性变化。

上述提到的培训成本是线性的,还是可以接受的。而相互之间的交流成本更麻烦一些。一个大型、复杂的软件项目往往都是相互关联的,为了保证一个目标在团队之间达成一致,最坏情况下是每个部分必须分别于其他部分单独协作,则工作量按照n(n-1)递增。这是一个很可怕的增长。

也就是说,当团队增长到一定的规模后,新增人员带来的沟通成本会比开发成本都高的多,反而会拖累项目的进度。反过来也要求在软件设计之初做好业务的拆分,做到不需要每个人都需要和其他人员有深度的关联,在代码上也需要做好解耦的设计。当前流行的DDD、微服务、代码上的设计模式都是基于这样一个原则来试图解决问题。

而在软件项目开始之前就认识到 软件项目不是一个关于人月的神话,对软件工程抱有敬畏之心才是最重要的。

二. 团队组成

上面提到沟通工作量随着团队规模的扩大而呈指数级增长,而往往一个大型项目的工作量往往是很大的,需要同时由很多人的协作才能完成,对于这样一个问题,我们就很有必要考虑下如何处理了。

首先,书中提到:优秀程序员和较差程序员之间的生产效率有非常的差异,一个研究表明:最好的和最差的表现在生产率上平均为10:1,在编程速度和空间上具有5:1的惊人差异!简言之,20000美元/年的程序员的生产率是10000美元/年的程序员的10倍,反之亦然。 其实这个比较好理解,现实场景中也会经常碰到,一个业务经验和编程经验较差的程序员埋的坑,需要经验两倍于他的程序员花两倍的时间去填。如果这样的坑流转到了线上系统的话,花费的代价会更大。

因此,很多人都热衷于拥有一支小型,精干的队伍,由几位经验丰富的程序员组成,而不是几十上百人的“平庸”程序员。但是现实场景往往不允许:

大型系统的工作量巨大,如果是按照工作量估算的话,一支小型而精干的队伍可能在1-2年的时间开发出来,但是2年后,这个产品是否还能在市场上受到欢迎呢?
经验丰富的程序员在人才市场上往往都是可遇不可求,绝大部分都是“平庸”的程序员。
那么如何调和这两方面的矛盾呢?书的第三章提到了作者提到了由harlan mills提出的——“外科手术队伍”的团队:(这里先引用书中全部描述,个人对这段描述理解的不是很明白)

外科医生。mills称之为首席程序员,应该是类似于我们现在的首席架构师。对整个系统的完整性负责,包括技术和业务完整性。

副手。外科医生的后备,主要作用是作为设计的思考者,讨论者和评估人员。副手可以有多名,经常在与其他团队讨论有关功能和接口问题时代表自己的小组。了解所有的代码,研究设计策略的备选方案。可以不负责具体代码的开发。

管理员。他是外科医生的老板,必须在人员、薪酬、办公空间等方面具有决定权,但他绝对不能在这些事务上浪费任何时间。因而,他需要一个控制财务、人员、工作地点和办公设备的专业管理人员,该管理员充当与组织中其他管理机构的接口。 Baker建议,仅在项目具有法律、合同、报表和财务方面的需求时,管理员才具有全职责任。否则,一个管理员可以为两个团队服务。

编辑。外科医生负责文档的生成,出于最大透明度的考虑,他必须创建各种文档,无论是对内部描述还是外部描述。而编辑根据外科医生的草稿或者口述,进行分析和重新组织,提供各种参考信息和书目,对多个版本进行维护,并监督文档生成的机制。

两个文秘。管理员和编辑每个人需要一个文秘。管理员的文秘负责非产品文件和使项目协作一致。

程序职员。他负责维护编程产品库中所有团队的技术记录。该职员接受文秘性质的培训,承担机器码文件和可读文件的相关管理责任。所有的计算机输入汇集到这个职员处。如果需要,他会对它们进行记录或者标识。输出列表会提交给程序职员,由他进行归档和编制索引。另外,他负责将任何模型的最新运行情况记录在状态日志中,而所有以前的结果则按时间顺序进行归档保存。

Mils概念的真正关键是“从个人艺术到公共实践”的编程观念转换。它向所有的团队成员展现了所有计算机的运行和产物,并将所有的程序和数据看做是团队的所有物,而非私人财产。程序职员的专业化分工,使程序员从文书等杂事中解放出来,同时还可以对那些经常被忽视的杂事进行系统整理,确保了它们的质量,并强化了团队最有价值的财富——工作产品。上述概念显然考虑的是批处理程序。当使用交互式终端,特别是在没有纸张输出的情况下,程序职员的职责并未消失,只是有所更改。他会记录小组程序和私有工作拷贝之间的更新,依然控制所有程序的运行,并使用自己的交互式工具来控制产品逐步增长的完整性和有效性。

工具维护人员。现在已经有很多文件编辑、文本编辑和交互式调试等工具,因此团队很少再需要自己的机器和机器操作人员。但是这些工具使用起来必须亳无疑问地具备令人满意的反应和可靠性。外科医生则是对这些工具的服务是否充分可用的唯一评判人员。他需要一个工具维护人员,保证所有基本服务的可靠性,以及承担团队成员所需要的特殊工具(特别是交互式计算机服务)的构建、维护和升级责任。即使已经拥有非常卓越的、可靠的集中式服务,每个团队仍然要有自己的工具维护人员。因为他的工作是检查他的外科医生所需要的工具,而不是其他团队的需要。工具维护人员常常要开发一些实用程序,编制具有目录的函数库以及宏库。

测试人员。外科医生需要大量合适的测试用例,用来对他所编写的工作片段,以及对整个工作进行测试。因此,测试人员既是为他的各个功能设计系统测试用例的对手,也是为他的日常调试设计测试数据的助手。他还负责计划测试的步骤和为单元测试搭建测试平台。

语言专家。随着 algol语言的出现,人们开始认识到,在大多数计算机项目中,总有一两个乐于掌握复杂编程语言的人。这些专家是非常有帮助的,大家会向他咨询。这些天才不同于外科医生,外科医生主要是系统设计者以及考虑系统的整体表现。而语言专家则寻找一种简洁、有效的使用语言的方法来解决复杂、晦涩或者棘手的问题。他通常需要对技术进行一些研究(23天)。通常一个语言专家可以为23个外科医生服务。

这些人员在一起按照如下的方式运作:
在这里插入图片描述

下面写写我对这个团队和运作方式的理解:

所有的对于产品的完整性出于一个人或少数人的思考输出(外科医生 + 副手),相当于首席架构师 + 若干个部件架构师。避免了产品完整性上的歧义,以及出现分歧时沟通讨论造成的沟通成本。有副手降低外科医生做的决策出现方向性的错误。
管理员可以理解为项目的事务性团队,比如后勤,人力等等。
编辑是为了保证所有的思想输出文档化,以文档来保持产品完整性和一致性,减少沟通,当然现在好像通过各种自动化工具来替代了这个环节。但是我们可以把这个看成一个虚拟的人物角色。
程序职员就是程序员了,这里提到了一点是需要为文档服务的,有一点编辑属性在里面,敲掉了文档的重要性(注释、接口文档、测试建议等等)
工具维护人员就是专门的环境准备和运维,在当前的devops潮流下,试图将程序职员和工具维护人员进行合并。
语言专家的话,个人理解是现在没什么太多用的角色,可能在之前的服务器硬件开发时,对一些高级语言需要有一定的了解。而现在我更愿意将这个角色理解为项目顾问。
团队的扩建的关键就在于问题域的拆分,也就是一个项目能拆分成几个外科医生团队。而每个团队成员的各司其职对团队的运作是至关重要的。
在拆分问题域的时候,应该这个团队结构也是嵌套的。
三. 贵族专治、民主政治和系统设计

这个标题看上去很高大上,实际上是想论证少数人保证概念完整性的必要性。另外的一个重要问题就是如何能保证在构建完整性的思考过程中,保证已有的内容传递到开发过程中。也就是架构师和程序员之间的配合。

首先我聊一聊自己对完整性的理解。

横向一致性,也就是说系统模块基于同一个理念进行设计和开发,实际上系统的耦合程度,接口参数个数,甚至函数名/函数个数等命名规则都需要有一致的规范,否则会导致很多歧义的发生。
纵向一致性,一个大型项目的开发时长通常是一年以上,从头到尾的设计一致性也是非常关键的,如果出现前后不一致的设计理念,对程序的稳定性是非常大的冲击。
一致性的传递,团队在配合久了之后,除了书面规定的一致性规范外,还会将这种一致性形成为一种约定俗成的默契,这个对软件开发的进度也是至关重要的一点。
根据书中提到的由一位或者少数几位“外科医生”组成的小队伍来保证完整性,这样的观点就是说是否要有一位杰出的精英,或者说是结构设计师的贵族专制,和一群创造性天赋和构思被压制的平民编程实现人员。

现在让我们来处理具有浓厚感情色彩的问题—贵族统治和民主政治。结构师难道不是新贵?他们是一些智力精英,专门来告诉可怜的实现人员如何工作?是否所有的创造性活动都被这些精英单独占有,实现人员仅仅是机器中的齿轮?难道不能遵循民主的理论,从所有的员工中搜集好的创意,以得到更好的产品,而不是将技术说明的开发工作仅限定于少数人

最后一个问题是最简单的。我当然不认为只有结构师才有好的创意。新的概念经常来自实现人员或者用户。然而,我一直试图表达,并且我所有的经验使我确信,系统的概念完整性决定了其使用的容易程度。不能与系统基本概念进行整合的良好想法和特色,最好放到一边,不予考虑。如果出现了很多非常重要但不兼容的构想,就应该抛弃原来的设计,对不同基本概念进行合并,在合并后的系统上重新开始。

至于贵族专制统治的问题,必须回答“是”或者“否”。就只能存在少数的结构师而言,答案是肯定的,他们的工作产物的生命周期比那些实现人员的产物要长,并且结构师一直处在解决用户问题,实现用户利益的核心地位。若要得到系统概念上的完整性,必须有人控制这些概念。这实际上是一种无需任何歉意的贵族专制统治。

第二个问题的答案是否定的,因为外部技术说明的编制工作并不比具体设计实现更富有创造性,它只是一项性质不同的创造工作而已。在给定体系结构下实现其设计,同样需要同编制技术说明一样的创造性、同样新的思路和卓越的才华。实际上,产品的成本性能比在很大程度上依靠实现人员,就如同易用性在很大程度上依赖结构师一样。

实际上,这里我最关注的一点就是书中提到程序编制工作同样具有创造性,是一种不同性质的创造工作。代码的简练,性能,可维护性都是一种创造性的工作。

好了,接下来的问题就是,当‘‘贵族阶级‘'的架构师做完整性设计时,‘‘平民阶级‘‘的程序员应该做点什么呢,是在等待么

书中指出;整个创造性的活动包括了三个独立的阶段,体系结构architecture,设计实现implementation和物理实现realization。在实际情况中,它们往往可以同时开始和冰法地进行。

实际上,整个软件工程的过程都是在不断细化这个过程,并不断提升这些过程的并发度的过程。从最初的瀑布模型到迭代模型,到敏捷开发,到devops。都是这样一个不断演进的精进的过程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/19493.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

详解c++---类和对象(三)

目录标题拷贝构造函数为什么会有该函数拷贝构造的特性第一个性质的详解第二个性质详解第三个性质的详解什么时候得自己写拷贝构造函数哪些场景会用到拷贝构造函数运算符重载函数为什么会有运算符重载运算符重载的形式>和>的运算符重载和的运算符的重载-和-的运算符重载运…

用anacnda创建虚拟环境用不用指定python版本

用anaconda创建了python虚拟环境以后,想用pycharm指定这个python解释器。 首先,在我创建虚拟环境并未指定python版本的情况下,在使用anaconda prompt的命令 conda create -n envs_name(未指定python版本)以后&#xff…

智能油井在线监控解决方案,第一时间掌握所有动态

随着物联网、云计算等技术的不断革新,物联网技术已经渗透到工业生产的方方面面。例如智能油井;油田地域广阔,分布着大量各种油井,油井开采设备的连续稳定运行是保证石油开采的首要条件。但是油井生产过程中,各井之间距…

C++ 多线程 线程安全队列设计

这是看《C并发编程实战》这本书学的,这里我要为这本书辟谣一下,虽然是这本书前面翻译得很烂,但是从第6章开始,应该是换了个人翻译,虽然还是能难懂,但是难懂的是代码逻辑,而不是语言逻辑&#xf…

MySQL8.0优化 - 锁 - 全局锁、死锁

文章目录学习资料锁的不同角度分类锁的分类图如下其他锁之:全局锁其他锁之:死锁概念产生死锁的必要条件如何处理死锁如何避免死锁学习资料 【MySQL数据库教程天花板,mysql安装到mysql高级,强!硬!-哔哩哔哩…

Java——继承下的抽象类与接口

文章目录壹、抽象类贰、接口前言: 我们前一章写了继承性,这一章节,一起来学习Java中的抽象类与接口相关知识。 壹、抽象类 1、定义:用关键字abstract修饰的类称为抽象类(abstract类)。 2、格式&#xff1…

进程调度例题解析

文章目录例题1 一个四道作业的操作系统中,设在一段时间内先后到达6个作业,它们的提交时间和运行时间见表例题2 一个具有两道作业的批处理系统,作业调度采用短作业优先的调度算法,进程调度采用以优先数为基础的抢占式调度算法&…

智慧矿山解决方案-最新全套文件

智慧矿山解决方案-最新全套文件一、建设背景二、建设思路智能矿山建设存在的问题1、行业上存在的问题2、承建商存在的问题3、矿井自身存在的问题三、建设方案四、获取 - 智慧矿山全套最新解决方案合集一、建设背景 采矿业是我国国民经济的基础和支柱产业,而矿山智慧…

云安全防护总体架构设计

安全需求和挑战 从风险管理的角度讲,主要就是管理资产、威胁、脆弱性 和防护措施及其相关关系,最终保障云计算平台的持续安全,以及 其所支撑的业务的安全。 云计算 平台是在传统 IT技术的基础上,增加了一个虚拟化层,并…

MobaXterm工具使用/Docker安装Redis/Redisinsight工具使用

✨✨个人主页:沫洺的主页 📚📚系列专栏: 📖 JavaWeb专栏📖 JavaSE专栏 📖 Java基础专栏📖vue3专栏 📖MyBatis专栏📖Spring专栏📖SpringMVC专栏📖SpringBoot专…

c++——map和set的使用

目录 一. 关联式容器 二. 键值对 三. 树形结构 Ⅰ. set 1. set的介绍 2. set的模版参数 3. set的构造 4. set的迭代器 5. set的容量 6. set其他操作 7. set的使用代码 Ⅱ. map 1. map的介绍 2. map的模板参数说明 3. map的构造 4. map的迭代器 5. map的容量 6…

Qt OpenGL(二十三)——Qt OpenGL 核心模式-给三角形上色

Qt OpenGL(二十三)——Qt OpenGL 核心模式-给三角形上色 本篇文章本来打算和上一篇文章写到一块的,但是考虑到VAO和VBO的概念是学习OpenGL核心模式绕不开的一个概念,所以单独再写一篇了,并且后面切换到使用Qt封装的VAO和VBO的时候,流程和这个也差不多,所以还是要做到理…

爬虫脚本代理池调度

爬虫脚本代理池调度 有时在使用爬虫或者使用脚本需要频繁访问一个网站,这种时候很容易被服务器给ban掉ip,这种情况就可以使用代理池。从代理池中进行调度获取新的ip进行访问。 使用的是开源免费的python项目地址如下: https://github.com/j…

【GPGPU编程模型与架构原理】第二章 2.1 计算模型

本章介绍以CUDA和OpenCL 并行编程中的一些核心架构概念来展示GPGPU的计算、编程和存储模型。本章还介绍虚拟指令集和机器指令集,逐步揭开GPGPU体系结构的面纱。 2.1 计算模型 计算模型是编程框架的核心,计算模型需要根据计算核心的硬件架构提取计算的共…

使用TinyPNG API压缩图片

使用TinyPNG API压缩图片 在撰写论文的时候,美观,大气,上档次的图标能够很好地给自己的论文加分,好的可视化结果也能够让审稿人赏心悦目。但是有时候在可视化图片的时候有可能原始图像过大从而很占内存;这时候就希望能…

Python+Numpy+CV2/GDAL实现对图像的Wallis匀色

Wallis匀色原理: # f(x,y):Wallis匀色后结果 # g(x,y):输入的待匀色影像 # mg:待处理影像的灰度均值 # mf:参考影像的灰度均值 # sg:待处理影像和的标准偏差 # sf:参考影像的标准偏差 f(x,y)(g(x,y)−mg)⋅(sf/sg)mf匀色代码逻辑解释&#xff1…

从阿里云“数字证书管理服务”申请免费的SSL证书

最近网站的SSL证书即将到期,之前是从FreeSSL申请的证书,而且是通过OpenSSL自己生成CSR文件的方式申请的证书,操作还是比较繁琐。(具体参考: https://blog.csdn.net/weixin_42534940/article/details/90745452 &#xf…

一、几种常用的设计模式

设计模式分类 创建者模式:对象实例化的模式,创建型模式用于解耦对象的实例化过程。 常用:单例模式、工厂方法模式、抽象工厂模式、建造者模式 。 不常用:原型模式结构型模式:把类或对象结合在一起形成一个更大的结构。…

Tilemap瓦片资源

1、Tilemap Tilemap一般称之为 瓦片地图或者平铺地图,是Unity2017中新增的功能,主要用于快速编辑2D游戏中的场景,通过复用资源的形式提升地图多样性 工作原理就是用一张张的小图排列组合为一张大地图 它和SpriteShape都是用于制作2D游戏的…

CEAC 之《企业信息化管理》1

👨‍💻个人主页:微微的猪食小窝 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 微微的猪食小窝 原创 收录于专栏 【CEAC证书】 1综合布线是智能建筑的信息高速公路。 A、正确 B、错误A2直通线的一根双绞线的两端执行不同…