人月神话

人月神话

焦油坑

  • 编程系统产品(Programming Systems Product)开发的工作量是供个人使用的、独立开发的构件程序的九倍。我估计软件构件产品化引起了3倍工作量,将软件构件整合成完整系统所需要的设计、集成和测试又强加了3倍的工作量,这些高成本的构件在根本上是相互独立的。
  • 编程行业“满足我们内心深处的创造渴望和愉悦所有人的共有情感”,提供了五种乐趣:
    • 创建事物的快乐
    • 开发对其他人有用的东西的乐趣
    • 将可以活动、相互啮合的零部件组装成类似迷宫的东西,这个过程所体现出令人神魂颠倒的魅力
    • 面对不重复的任务,不间断学习的乐趣
    • 工作在如此易于驾驭的介质上的乐趣——纯粹的思维活动,其存在、移动和运转方式完全不同于实际物体
  • 这个行业具有一些内在固有的苦恼:
    • 将做事方式调整到追求完美,是学习编程的最困难部分
    • 由其他人来设定目标,并且必须依靠自己无法控制的事物(特别是程序);权威不等同于责任
    • 实际情况看起来要比这一点好一些:真正的权威来自于每次任务的完成
    • 任何创造性活动都伴随着枯燥艰苦的劳动,编程也不例外
    • 人们通常期望项目在接近结束时,(bug、工作时间)能收敛得快一些,然而软件项目的情况却是越接近完成,收敛得越慢
    • 产品在即将完成时总面临着陈旧过时的威胁

人月神话

  • 缺乏合理的时间进度是造成项目滞后的最主要原因,它比其他所有因素加起来影响还大。
  • 良好的烹饪需要时间,某些任务无法在不损害结果的情况下加快速度。
  • 所有的编程人员都是乐观主义者:“一切都将运作良好”。
  • 由于编程人员通过纯粹的思维活动来开发,所以我们期待在实现过程中不会碰到困难。
  • 但是,我们的构思是有缺陷的,因此总会有bug。
  • 我们围绕成本核算的估计技术,混淆了工作量和项目进展。人月是危险和带有欺骗性的神话,因为它暗示人员数量和时间是可以相互替换的。
  • 在若干人员中分解任务会引发额外的沟通工作量——培训和相互沟通。
  • 关于进度安排,我的经验是为1/3计划、1/6编码、1/4构件测试以及1/4系统测试
  • Brook法则:向进度落后的项目中增加人手,只会使进度更加落后。
  • 向软件项目中增派人手从三个方面增加了项目必要的总体工作量:任务重新分配本身和所造成的工作中断;培训新人员;额外的相互沟通。

外科手术队伍

  • 经验和实际表现之间没有相互联系。我怀疑这种现象是否普遍成立。
  • 小型、精干队伍是最好的——尽可能的少。
  • 两个人的团队,其中一个项目经理,常常是最佳的人员使用方法。[留意一下上帝对婚姻的设计。]
  • 对于真正意义上的大型系统,小型精干的队伍太慢了。
  • 实际上,绝大多数大型编程系统的经验显示出,一拥而上的开发方法是高成本、速度缓慢、不充分的,开发出的产品无法进行概念上的集成。
  • 一位首席程序员、类似于外科手术队伍的团队架构提供了一种方法——既能获得由少数头脑产生的产品完整性,又能得到多位协助人员的总体生产率,还彻底地减少了沟通的工作量。

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

  • 概念完整性是系统设计中最重要的考虑因素。
  • “功能与理解上的复杂程度的比值才是系统设计的最终测试标准”,而不仅仅是丰富的功能。[该比值是对易用性的一种测量,由简单和复杂应用共同验证。]
  • 为了获得概念完整性,设计必须由一个人或者具有共识的小型团队来完成。
  • “对于非常大型的项目,将设计方法、体系结构方面的工作与具体实现相分离是获得概念完整性的强有力方法。”[同样适用于小型项目。]
  • 如果要得到系统概念上的完整性,那么必须控制这些概念。这实际上是一种无需任何歉意的贵族专制统治。
  • 纪律、规则对行业是有益的。外部的体系结构规定实际上是增强,而不是限制实现小组的创造性。
  • 概念上统一的系统能更快地开发和测试。
  • 体系结构(architecture)、设计实现(implementation)、物理实现(realization)的许多工作可以并发进行。[软件和硬件设计同样可以并行。]

画蛇添足

  • 尽早交流和持续沟通能使结构师有较好的成本意识,以及使开发人员获得对设计的信心,并且不会混淆各自的责任分工。
  • 结构师如何成功地影响实现:
    • 牢记是开发人员承担创造性的实现责任;结构师只能提出建议。
    • 时刻准备着为所指定的说明建议一种实现的方法,准备接受任何其他可行的方法。
    • 对上述的建议保持低调和平静。
    • 准备对所建议的改进放弃坚持。
    • 听取开发人员在体系结构上改进的建议。
  • 第二个系统是人们所设计的最危险的系统,通常的倾向是过分地进行设计。
  • 为功能分配一个字节和微秒的优先权值是一个很有价值的规范化方法。

贯彻执行

  • 即使是大型的设计团队,设计结果也必须由一个或两个人来完成,以确保这些决定是一致的。
  • 必须明确定义体系结构中与先前定义不同的地方,重新定义的详细程度应该与原先的说明一致。
  • 出于精确性的考虑,我们需要形式化的设计定义,同样,我们需要记叙性定义来加深理解。
  • 必须采用形式化定义和记叙性定义中的一种作为标准,另一种作为辅助措施;它们都可以作为表达的标准。
  • 设计实现,包括模拟仿真,可以充当一种形式化定义的方法;这种方法有一些严重的缺点。
  • 直接整合是一种强制推行软件的结构性标准的方法。
  • 如果起初至少有两种以上的实现,那么(体系结构)定义会更加整洁,会更加规范。
  • 允许体系结构师对实现人员的询问做出电话应答解释是非常重要的,并且必须进行日志记录和整理发布。
  • 项目经理最好的朋友就是他每天要面对的敌人 —— 独立的产品测试机构/小组。

为什么巴比伦塔会失败?

  • 交流的重要性:
    • 巴比伦塔项目的失败是因为缺乏交流,以及交流的结果——组织。
    • “因为左手不知道右手在做什么,从而进度灾难、功能的不合理和系统缺陷纷纷出现。”由于对其他人的各种假设,团队成员之间的理解开始出现偏差。
    • 团队应该以尽可能多的方式进行相互之间的交流:非正式、常规项目会议,会上进行简要的技术陈述、共享的正式项目工作手册。
  • 项目工作手册
    • 项目工作手册“不是独立的一篇文档,它是对项目必须产生的一系列文档进行组织的一种结构。”
    • 项目所有的文档都必须是该(工作手册)结构的一部分。
    • 需要尽早和仔细地设计工作手册结构。
    • 事先制订了良好结构的工作手册“可以将后来书写的文字放置在合适的章节中”,并且可以提高产品手册的质量。
    • 每一个团队成员应该了解所有的材料(工作手册)。[我想说的是,每个团队成员应该能够看到所有材料,网页即可满足要求。]
    • 实时更新是至关重要的。
    • 工作手册的使用者应该将注意力集中在上次阅读后的变更,以及关于这些变更重要性的评述。
    • 仍然需要用变更条和修订日期[或具备同等功能的方法]来标记文字;仍然需要后进先出(LIFO)的电子化变更小结。
    • 强烈地认为使每个人看到每件事的目标是完全错误的;各个部分应该被封装,从而没有人需要或者允许看到其他部分的内部结构,只需要了解接口。
  • 组织架构:
    • 团队组织的目标是为了减少必要的交流和协作量。
    • 为了减少交流,组织结构包括了人力划分(division of labor)和限定职责范围(specialization of function)。
    • 传统的树状组织结构反映了权力的结构原理 —— 不允许双重领导。
    • 组织中的交流是网状,而不是树状结构,因而所有的特殊组织机制(往往体现成组织结构图中的虚线部分)都是为了进行调整,以克服树状组织结构中交流缺乏的困难。
    • 每个子项目具有两个领导角色 —— 产品负责人、技术主管或结构师。这两个角色的职能有着很大的区别,需要不同的技能。
    • 两种角色中的任意组合可以是非常有效的:
      • 产品负责人和技术主管是同一个人。
      • 产品负责人作为总指挥,技术主管充当其左右手。
      • 技术主管作为总指挥,产品负责人充当其左右手。

胸有成竹

  • 仅仅通过对编码部分的估计,然后乘以任务其他部分的相对系数,是无法得出对整项工作的精确估计的。
  • 构建独立小型程序的数据不适用于编程系统项目。
  • 程序开发呈程序规模的指数增长。
  • 全职程序员仅将50%的时间用于编程和调试。
  • 当使用适当的高级语言时,程序编制的生产率可以提高5倍。

削足适履

  • 除了运行时间以外,所占据的内存空间也是主要开销。特别是对于操作系统,它的很多程序是永久驻留在内存中。
  • 即便如此,花费在驻留程序所占据内存上的金钱仍是物有所值的,比其他任何在配置上投资的效果要好。规模本身不是坏事,但不必要的规模是不可取的。
  • 软件开发人员必须设立规模目标,控制规模,发明一些减少规模的方法 —— 就如同硬件开发人员为减少元器件所做的一样。
  • 规模预算不仅仅在占据内存方面是明确的,同时还应该指明程序对磁盘的访问次数。
  • 规模预算必须与分配的功能相关联;在指明模块大小的同时,确切定义模块的功能。
  • 在大型的团队中,各个小组倾向于不断地局部优化,以满足自己的目标,而较少考虑对用户的整体影响。这种方向性的问题是大型项目的主要危险。
  • 在整个实现的过程期间,系统结构师必须保持持续的警觉,确保连贯的系统完整性。
  • 培养开发人员从系统整体出发、面向用户的态度是软件编程管理人员最重要的职能。
  • 精炼、充分和快速的程序。往往是战略性突破的结果,而不仅仅技巧上的提高。
    • 这种突破常常是一种新型算法。
  • 更普遍的是,战略上突破常来自于数据或表的重新表达。数据的表现形式是编程的根本。

提纲挈领

  • 对于计算机硬件开发项目,关键文档是目标、手册、进度、预算、组织机构图、空间分配、以及机器本身的报价、预测和价格。
  • 对于大学科系,关键文档类似:目标、课程描述、学位要求、研究报告、课程表和课程的安排、预算、教室分配、教师和研究生助手的分配。
  • 对于软件项目,要求是相同的:目标、用户手册、内部文档、进度、预算、组织机构图和工作空间分配。
  • 因此,即使是小型项目,项目经理也应该在项目早期规范化上述的一系列文档。
  • 以上集合中每一个文档的准备工作都将注意力集中在对讨论的思索和提炼,而书写这项活动需要上百次的细小决定,正是由于它们的存在,人们才能从令人迷惑的现象中得到清晰、确定的策略
  • 项目经理的基本职责是使每个人都向着相同的方向前进
  • 项目经理的主要日常工作是沟通,而不是做出决定;文档使各项计划和决策在整个团队范围内得到交流
  • 只有一小部分管理人员的时间 —— 可能只有20% —— 用来从自己头脑外部获取信息。
  • 支持管理人员的“完备信息管理系统”并不基于反映管理人员行为的有效模型。

干将莫邪

  • 项目经理应该制订一套策略,以及为通用工具的开发分配资源,与此同时,他还必须意识到专业工具的需求。
  • 开发操作系统的队伍需要自己的目标机器,进行调试开发工作。相对于最快的速度而言,它更需要最大限度的内存,还需要安排一名系统程序员,以保证机器上的标准软件是即时更新和实时可用的。
  • 系统文档中的巨大容量带来了新的不理解问题, 但是它比大多数未能详细描述编程系统特性的短小文章更加可取。
  • 调试是系统编程中很慢和较困难的部分,而漫长的调试周转时间是调试的祸根。
  • 有限的数据表明了系统软件开发中,交互式编程的生产率至少是原来的两倍。

祸起萧墙

  • 里程碑必须是具体的、特定的、可度量的事件,能进行清晰能定义。
  • 如果里程碑定义得非常明确,以致于无法自欺欺人时,程序员很少会就里程碑的进展弄虚作假。
  • 进取对于杰出的软件开发团队,同优秀的棒球队伍一样,是不可缺少的必要品德。
  • 对于大型项目,一个对里程碑报告进行维护的计划和控制(Plan and Control)小组是非常可贵的。

另外一面

  • 最小化文档负担的3个关键思路:
    • 借助那些必须存在的语句,如名称和声明等,来附加尽可能多的“文档”信息。
    • 使用空格和格式来表现从属和嵌套关系,提高程序的可读性。
    • 以段落注释,特别是模块标题的形式,向程序中插入必要的记叙性文字。
  • 程序修改人员所使用的文档中,除了描述事情如何以外,还应阐述它为什么那样。对于加深理解,目的是非常关键的,但即使是高级语言的语法,也不能表达目的。
posted @ 2020-02-22 18:15  coding-for-self  阅读(176)  评论(0编辑  收藏  举报