《人月神话》摘要

  一直相信存在某种方法论,能够让软件开发工作的进度能够得到很好的控制,并很大程度的提高生产率。读完本书后,我意识到,能够解决软件开发问题的不是某种方法论,而是一系列的方法、技术、和工具。也发现自己之前太局限于从“开发”角度去思考问题,以后还需多看书,多学习才是。

  以上都是废话,对自己无知的惭愧。后面的内容将是书中各个章节的摘要,并可能还会有一些废话。对于废话,不必太过在意,但是也不介意吐槽~

  个人建议:想读本书的朋友,到网上搜“没有银弹”读读即可。因为由于写作的年代与当今相距甚远,其中的多数方法和建议已很难应用,但是“没有银弹”绝对是亮点章节。

  第一章、焦油坑

  1.    编程系统产品(Program System Product,我理解为软件)

    演化进程:程序->编程系统(接口、系统集成)->编程系统产品;程序->编程产品(通用化、测试、文档、维护)->编程系统产品。这两条线都节约了成本。

 2.  编程的乐趣

  • 创建新事物;
  • 开发的产物能够对别人有用;
  • 编程的过程:各个组件按照相互协作完成预定功能;
  • 不是重复的工作,需要持续的学习新的知识
  • 工作再易于驾驭的介质上:自由的运用自己的想象,创建自己的城堡。

 3.  编程的苦恼

  • 追求完美:计算机要求精确的输入输出、完整的概念/逻辑,这比现实生活要严格许多;
  • 目标、信息、资源都是由别人提供:即很多东西需要依赖别人(注:这就是为何沟通显得尤为重要);
  • 重复琐碎的劳动:如处理琐碎的Bug;
  • 调试和查错是线性收敛的,甚至是二次方的复杂度:越往后Bug越难以发现(后悔没好好学数学,只能这样理解了*_*);
  • 辛勤付出得不到预想的回报:不是指工资,而是项目即将完成的时候,发现市场上已有类似的产品出现,而且好像比自己做得更好~

第二章、人月神话 

   项目滞后的主要原因是缺乏进度的合理安排:

  • 对估算技术缺乏有效研究。乐观主义,通常假设一切都将运作良好;
  • 混淆工作量和进度,以为人月可以互换;
  • 对自己的估算缺乏信心,项目经理不会耐心持续的进行估算;
  • 缺少进度跟踪和监督;
  • 进度偏移时,第一反应是协调人力。

  1.   乐观主义

    乐观主义是程序员的职业病。

  2.  人月

    人员之间的需要沟通交流,新派人手可能成为负担;而且任务还有先后顺序。

  3.  系统测试

    过程时间占比经验:

      计划(1/3):包含技术调研、概念设计(功能规格)

      编码(1/6):最容易估计时间的部分

      构件测试和早起系统测试(1/4):单元测试

      系统测试(1/4):集成测试

  4.  空泛的估算

    在外部的压力下,项目经理在估算时容易屈服。

    开发并推行生产率图表、缺陷率图表、估算规则等工具可以使得项目估计更有依据,相比经验也更能有说服力。

  5.  重复产生的进度灾难

    进度延迟后考虑的做法:

      重新安排进度:注意在开发过程中及时重新估计和调整进度(不一定是延后,而是根据实际情况,部分任务缩减,部分任务延长),任务的粒度也需要注意,不需要太细,也不能太粗。

      削减任务:讨论功能的重要性和优先级,考虑分版本发布,先完成重要、紧急的功能。

    Brooks法则:想落后的项目中增加人手,只会使得进度更加落后。

第三章、外科手术队伍

  软件开发队伍人员尽量少而精——

    文艺程序员比普通程序员在生产率上的差异很大,甚至能达到一个数量级;

    开发成本的主要组成部分是相互的沟通和交流,以及更正沟通不当所引起的不良结果;

    更少的人数更容易保证概念完整性。

  1.  问题

    小型精干队伍的人数一般在10人以内。但是对于大型系统,比如需要1000人年,完成项目的进度显得太长~

    对于大型系统,需要划分模块来完成。而且概念设计部分需要由少而精的人员完成。

  2.  Mills的建议(外科手术队伍)

  • 外科医生(架构师):定义功能、性能技术说明书,设计程序,编写源代码,测试,写技术文档;
  • 副手(开发组长):能完成任何一部分工作,但经验较少。设计的思考者、讨论者、评估人员;
  • 管理员(项目经理):管理财务、人员、办公设备等,可以一个人管两个项目组;
  • 编辑:组织文档;
  • 两个文秘:管理员和编辑各一个(偶也想要啊)
  • 程序职员:维护所有团队的技术记录

  3.  如何运作

  • 概念来自外科医生和副手,保证了完整性并节约了沟通成本
  • 外科医生在金字塔顶端,可以统一分歧
  • 其余人员分工专业化,更为高效

  4.  团队的扩建

    大型系统需要一个系统结构师自上而下的进行所有设计,也有利于协调。概念设计团队的人也要少而精。

第四章、贵族专制、明主政治和系统设计

  1.  概念完整性

    概念完整性应该是系统设计最重要的考虑因素。保证概念完整性最好的方法是由一个人来完成设计,对于后来的设计者,则要求他们牺牲一些创意,以获得纯粹的设计。

  2.  获得概念完整性

    系统设计的最终测试标准:易用性 = 功能 / 理解复杂度。

    软件不仅要功能越多越好,而且需要简洁、直接。简洁和直白来自概念完整性。

    设计的一致性是易用性的另一重要因素。设计一致性要求:每个部分必须反映相同的原理需求的一致平衡(语法上使用的技巧相同,语义上也要具有相似性)。

  3.  贵族专制和民主政治

    概念的完整性要求设计必须由一个人,或者少数互有默契的人员来实现。但进度压力要求系统要由很多人来开发。解决这一矛盾的方法有两个:仔细对设计方法/体系结构与具体实现进行分工;第三章所述的团队的组建方式。

    系统的体系结构(achitecture)指的是完整和详细的用户接口说明。系统的结构师(架构师)需要运用专业技术知识来支持最终用户的利益。

    体系结构师(架构师)的贵族专制统治:体系结构师代表最终用户的利益;其产物的生命周期比实现人员更长;为了概念完整性,系统设计必须由少数人(架构师)控制。

    具体设计实现在创造性方面并不亚于体系结构设计工作:具体实现更大程度决定了产品的成本和性能;而结构设计偏向于易用性。但是具体实现需要依赖于结构设计。

  4.  在等待时,实现人员应该做什么

    软件开发的三个阶段(Blaauw):体系结构(achitecture)、设计实现(implementation)、物理实现(realization)。他们彼此存在依赖,但往往可以同时开始和并发进行。

    上述的划分是水平的划分,实际中再进行垂直的(功能)划分并不会在概念完整性等方面造成不利影响。上述的三个阶段确实存在一定的向上依赖,但是垂直的划分使得工作可以并行进行;另外各个阶段中都有部分工作是不存在向上依赖的。

第五章、画蛇添足

  结构师的主要职责在于只能功能规格说明,他没有产品开发时间、成本方面的责任。理论上结构师的创造性可以是无限的,那么如何来约束这种热情呢?

  1.  结构师的交互准则和机制

    今早的交流和持续沟通:使得结构师有成本意识,也让开发人员对设计有信心,不会混淆责任分工。

    产生估算过高时,结构师有两个选择:削减设计;建议实现人员使用成本更低的实现方法。

    交互准则:

      牢记开发人员承担实现的责任,所以只能建议,不能支配;

      时刻准备为所指定的功能建议一种实现方法,同样准备接受其他任何能够达到目标的方法;

      对上述的建议保持低调和不公开;

      准备放弃坚持所做的改进建议;

    在体系结构上的修改往往会引起开发人员的反对——实现工作展开时,一些次要特性的修改会造成意想不到的成本开销。

  2.  自律——开发第二个系统所带来的后果

    结构师设计的第二个系统往往是最危险的。

    由于对任务不够了解而产生的谨慎,结构师的第一个系统倾向于精炼和简洁;而第二个系统往往会被过分设计(太多的修饰功能、想法);后面的项目会在之前的经验上形成对比总结,所以在简洁性和功能方面,比较容易达到平衡。避免过分设计的方法在于:自律和程序经理的监督。

第六章、贯彻执行

  1.  文档化的规格说明——手册

    手册需要描述和规定用户所见的每一个细节,同时需要避免描述用户不可见的部分。结构师必须为自己描述的任何特性准备一种实现方法,但不应试图支配实现过程。

    手册(规格说明)的风格必须清晰、完整和准确。一致性很重要。

  2.  形式化定义

    形式化(术语化、公式化)定义是精确的,倾向完整;但是不易理解,需要记叙性文字的辅助。注意在同一个手册中需要在谁主谁辅上保持一致。

    实现可以作为一种形式化定义方法(如)。实现作为形式化定义的优点:所有问题可以通过试验清晰的得到答案,快捷迅速、无需争辩商讨;缺点:实现作为定义时,体现了过多的内容,即不但描述了系统必须做什么,同时还声明了自己做了些什么(多余的要求)。

  3.  直接整合

    设计好模块间接口的原型,要求在实现过程中按照原型开发。

  4.  会议和大会

    周例会:每周半天,由首席结构师主持,所有结构师参加、实现人员代表和市场计划人员(代表用户)参与。参与人员都可以提出问题和修改意见,但需要提前准备并分发书面建议书。    讨论通过的建议/问题解决方案由相关结构师进行修改,并纳入变更建议说明书中。问题结论由首席架构师发布。

    周例会优点:相同人员数月内每周交流一次,对项目内容都比较了解,无需额外培训;参与人员与产品密切相关,深刻理解所面对的问题,每个人都承担义务;出现问题时,在界线内部和外部同时寻求解决方案;正式的书面建议集中了注意力,强制了决策的制定和执行;明确授予首席结构师决策权力,避免妥协拖延。

    年度(或半年)大会,在功能规格制定前进行。出了周例会成员,程序经理、实现人员、市场人员都会参与,由项目经理主持。集中解决遗留的各种问题,耗时两周,每天需要通知前一天的各项决定。

    年度大会优点:解决了部分决策上的问题,同时使决策更容易被接受和理解。

  4.  多重实现

    多重实现时,根据机器修改手册的消耗可能比根据手册修改机器要高。

  5.  电话日志

    实现人员对规格说明容易理解不当或规格说明本身描述就不够精确,所以结构师鼓励实现人员电话沟通。在此条件下,结构师需要保存电话日志,记录每个问题和相应的解答,并每周进行合并整理,分发给用户和实现人员。

  6.  产品测试

    测试组的工作是根据规格说明检查程序,需要由独立的技术监督部门完成,以保证公正性。

 第七章、为什么巴比伦塔会失败

  巴比伦塔(圣经中的典故):开始,人们使用的是同一种语言,他们建造房屋,并想着建造一个有高塔的城市,所有人都可以聚集在高塔里。上帝听说后,认为有必要让人类经历些挫折,于是他在人类的语言中制造了混淆,相互无法听懂。这样人类就不得不停止制造巴比伦塔。

  1.  巴比伦塔的管理教训

    人类有清晰的目标、人力充足、材料齐全、时间充裕、技术完备。但失败的原因在于:缺乏交流以及交流的结果(组织)。

  2.  大型编程项目中的交流

    团队之间的交流沟通需要利用所有可能的途径:

      非正式途径:电话、口头、即时通讯、邮件等;

      会议:各团队逐一进行简要的技术陈述。很容易澄清细小的误解;

      工作手册:在项目开始阶段即应该准备

  3.  项目工作手册。

    定义:对项目必须产出的一系列文档进行组织的一种结构,而非独立的一篇文档。即定义各类文档存放在什么位置。

    备忘录的管理:编号、整理,便于检索。

    当编程人员仅了解自己负责的部分,而非整个系统的开发细节时,工作效率最高。此方法的先决条件在于精确完整的定义所有接口。

  4.  大型变成项目的组织架构

    团队组织的目的:减少所需的交流和合作的数量。

    减少交流的方法:人力划分和限定职责范围。

    树状组织架构是作为权力和责任的结构出现,不适合交流和沟通(网状)。

    树状编程队伍中,每颗子树必备的基本要素:任务(mission);产品负责人(producer);技术主管或结构师(techenical director or architecture);进度(schedule);人力划分(division of labor);各部分间的接口定义(interface definitions among the parts)。

      产品负责人:组建团队、划分工作、制定进度表。争取和保证必要的资源(外部向上或水平沟通);建立内部沟通/报告方式;确保进度目标的实现,根据环境变化调整资源和团队架构。

      技术主管:对设计进行构思,识别系统的字部分,设计内部结构和外部功能;提供整个设计的一致性和概念完整性;控制系统的复杂程度。提供复杂问题的解决方案,或根据需要调整系统设计。

      建议技术主管为主,产品负责人为辅的组织架构;产品负责人为主时需要预先声明技术主管在技术决策方面的权威(亦可通过办公条件等方面暗示)。

第八章、胸有成竹

  系统编程的时间估计,工作量估计方法:比率估算法(不能仅用编码阶段估计);小型程序数据不适合编程系统产品。

  1.  Portman的数据

    编程进度大约落后计划的1/2,每项工作花费的时间大约是估计的2倍。实际编程和调试的时间只有半个工作周,其他时间都在会议、文字、高优先级的琐碎工作、公司业务、病事假等。

第九章、削足适履

  本章在内存资源非常昂贵时有意义,如今总结一句话:时间空间可互换、实现需要考虑性能标准,有时候从结果而非过程来考虑问题能够得到更好的解决方案。

第十章、提纲挈领

  前提:在堆积如山的文档中,少数是关键枢纽,每一件项目管理工作都围绕着他们运转。这些文档是项目经理最重要的个人工具。

  技术、周边组织机构、行业传统等因素定义了项目必须准备的一些文书工作。这些文书工作看起来令人厌烦,但是他们往往包含了一些管理方面的内容:每份文档的准备工作是集中考虑,并使各种讨论意见明朗化的主要时刻;文档有利于明确工作阶段;文档的跟踪维护是项目监督和预警机制;文档本身可以作为检查列表、状态控制,也可以作为汇报的数据基础。

  任何管理任务的关注焦点都是:时间、地点、人员、项目内容、资金。

  1.  软件项目文档

    内容:目标。定义待完成的目标、迫切需要的资源、约束和优先级;

    内容:产品技术说明。以建议书开始,用户手册和内部文档结束。性能说明是关键部分;

    时间:进度;

    资金:预算;

    地点:工作空间分配;

    人员:组织图。人员与接口说明相互依存。组织结构需要根据系统设计自由变化。

  2.  为什么要有正式的文档

    书面记录决策是必要的。记录

    文档可以作为同其他人沟通的渠道。项目经理的基本职责是使每个人都想着相同的方向前进,其主要工作是沟通,非决定。

    文档可以作为数据基础和检查列表。通过文档能够搞清项目所处状态,需要做的更改和调整。

    文档非常重要,但是不存在“完全信息管理系统”。因为管理人员80%的时间都用在沟通上:倾听、报告、讲授、规劝、讨论和鼓励。

    项目经理的任务是制定并实现计划,只有书面计划是精确和可沟通的。

第十一章、未雨绸缪

  1.  试验性工厂和增大规模

    必须为舍弃而计划。第一个版本必然会存在很多问题,所以做好把其当做一个试验品的准备。要注意试验品是否应当发布给用户。

  2.  唯一不变的是变化本身

    接受变化,但并非客户所有的需求变更都应该整合到设计中。

  3.  为变更计划系统

    技术手段:设计细致的模块化、可扩展的函数、精确完整的模块间接口设计和完备的文档。

    变更的阶段化:版本号、日程表、冻结日期、变更内容。

  4.  为变更计划组织架构

    选择高效的技术人员,解决各种技术问题;对技术人员进行培训;废除职位头衔,让成员能够接受职务变更。

  5.  前进两步,后退一步

    缺陷修复总会以20%-50%的概率引入新的Bug;

    回归测试的成本很高;

    选择程序设计方法时,需要考虑其副作用,并指明。

  6.  前进一步,后退一步

    在系统维护过程中,更多关注的是功能实现,系统原有设计日益被忽略,每次的修改都可能导致潜在的新问题,修改成本日益增加。必要时,需要考虑代码重构或重新设计。

第十二章、干将莫邪(利器)

  工具要通用化,个性化的工具妨碍沟通。建议每个团队一个工具管理人员,工具小组方式则相对效率更低。

  考虑使用高级语言、成熟框架,性能测试工具,调试工具,测试用例生成工具等。

第十三章、整体与部分

  1.  剔除Bug的设计

    系统各个部分的开发者都会做出假设,这些假设的不匹配会导致致命或难以察觉的Bug。细致的功能定义、仔细的规格说明、规范化的功能描述说明很有必要。

    测试规格说明:完整性和明确性

    自上而下的设计,横向划分为:体系结构设计、设计实现、物理实现;纵向以模块划分,且模块从大到小不断细化。优点:

      清晰的结构和表达方式更容易对需求和模块功能进行精确的描述;

      模块分割和模块独立性避免了系统级Bug;

      细节的抑制使得结构上的缺陷容易暴露出来;

      设计在每个精化步骤上都是可测试的。

    遇到极端问题时,可能需要考虑逆转过程,直至推翻顶层设计,重新开始。

  2.  单元调试

    略

  3.  系统集成调试

    需要在各个部分都能够正常运行之后开始。这个阶段耗费的时间往往比预计的要长。

    使用伪构件(dummy component,包含接口、可能的伪数据和一些小的测试用例)。

    控制变更。控制构件单元版本。

    一次添加一个构件。能够有利于问题定位。

    阶段化变更。定期进行大范围的构件更新等,周期不宜太短。

第十四章、祸起萧墙

  通常灾祸来自白衣的肆虐,而非龙卷风的侵袭。

  1.  里程碑还是沉重的负担

    里程碑澄清了划分的比较模糊的阶段,定义了确定时间点需要的完整的产物。里程碑的边界需要是明显的,无歧义的。里程碑需要能够正确的反应损失的时间,避免慢性进度偏离影响士气。

    建议活动之前开始估计,每两周对计划进行一次仔细的修订。

  2.  关键路径法(Pert图)

    那些任务的滞后会影响最终的完成日期。非关键任务允许一定的落后时间。

    相对对每个任务估计完成时间,关键路径法更能够鼓励超前完成,也指明了补偿其他任务滞后时间的方法。

  3.  地毯的下面

    程序经理发现计划偏离时,存在于老板的利益冲突:老板需要行动计划,分析的状态数据;程序经理会认为非致命性的进度偏离是可通过团队内部解决的,老板的行动可能会影响计划或个人威信。冲突(让程序经理公开信息)的解决方法:

    减少角色冲突:老板避免对程序经理能够解决的问题进行干预,绝不在检查状态报告时做安排。

    猛地拉开地毯:评审机制。每周小屏,每月大评。项目经理需要解释延迟原因,并指出应对方案和需要的帮助。

第十五章、另外一面

  对开发人员光是介绍文档的重要性,并讲解写文档的技巧和要点,还不如做一份给他们看。

  1.  需要什么样的文档

    使用程序的文档内容:

      目的(程序的主要功能是什么,解决了什么问题);

      环境(机器、硬件配置、操作系统等);

      输入范围,输出范围;

      实现功能和使用的算法;

      输入-输出格式(必须是确切完整的);

      操作指令;

      功能选项;

      运行时间;

      精度和校验;

      精度及如何校验精度。

    验证程序的文档内容:

      测试用例。给程序使用者提供信心。

    修改程序文档内容:

      流程图或子系统的结构图;

      对所用算法的完整描述;

      对所有文件规划的解释;

      数据流处理的概要描述,以及每个处理过程中晚餐的操作;

      初始设计中,对已遇见修改的讨论;特性、功能回调以及出口的位置;原作者对可能会修改的地方及可能处理方案的一些意见。

   2.  流程图

    从代码生成流程图非良好实践。

   3.  自文档化的程序

    维护文档和代码的一致性是费力不讨好的事情。建议将注释以文字记录到代码头部,注意格式。维护记录也可记录其中。

第十六章、没有银弹——软件工程中的根本和次要问题

本章节是精华,建议精读,这里简要列举

  在未来十年内,无论是在技术还是管理方法上,都看不出有任何突破性的进步,能够独自保证在十年内大幅度地提高软件的生产率、可靠性和间接性。

  软件活动包括:

    根本任务,打造构成抽象软件实体的复杂概念结构

    次要人物,使用编程语言表达这些抽象实体,在空间和时间限制内将它们映射成机器语言。作者出于必要任务考虑的四点建议:

      仔细进行市场调研,避免开发已上市的产品;

      获取和制定软件需求时,将快速原型开发作为迭代计划的一部分;

      有机地更新软件,随着系统的运行、使用和测试,逐渐添加越来越多的功能;

      不断挑选和培养杰出的概念设计人员。

  1.  根本困难 

    软件开发困难的部分:规格说明、设计和测试这些概念结构,而非对概念进行表达和对实现逼真程度进行验证。

    软件内在特性:复杂度、一致性、可变性和不可见性。

  2.  次要问题上的突破

    高级语言;

    统一的编程环境。

  3.  银弹的希望

    高级语言;

    面向对象编程;

    人工智能;

    专家系统;

    “自动”编程;

    图形化编程;

    程序验证;

    环境和工具。

  4.  针对根本问题颇有前途的方法

    购买而非自行开发

    需求精炼和快速原型

    增量开发——增长而非搭建系统。

    卓越的设计人员

      杰出设计人员的培养方法:

        尽可能早的,有系统的识别顶级的设计人员;

        为设计人员指派一位职业导师,负责他们技术方面的成长,仔细为他们规划职业生涯;

        为每个方面制定和维护一份职业计划,包括设计大师的精挑细选的学习过程,正式的高级教育和短期的课程;

        为成长中的设计人员提供相互交流和激励的机会。

  

    

     

posted @ 2012-02-22 21:19  洗洗睡吧  阅读(1331)  评论(0编辑  收藏  举报