目录
1 焦油坑
2 人月神话
3 外科手术队伍
4 贵族专制、民主政治和系统设计
5 画蛇添足
6 贯彻执行
7 为什么巴比伦塔会失败?
8 胸有成竹
9 削足适履
10 提纲挈领
11 未雨绸缪
12 干将莫邪
13 整体部分
14 祸起萧墙
15 没有银弹
过去几十年的大型系统开发就犹如一个焦油坑,很多大型动物在其中剧烈挣扎,他们中大多数开发出了可运行的系统。不过,其中只有非常少数的项目满足了目标、时间进度和预算的要求。各种团队,大型的和小型的,庞杂的和精干的,一个接一个淹没在了焦油坑中。表面上看起来好像没有任何一个单独的问题会导致困难,每个都能被解决,但是当它们相互纠缠和累积在一起的时候,团队的行动就会变得越来越慢且很难看清问题的本质。
(1)、系统级的软件产品是构件程序工作量的9倍。将其产品化引起了3倍的工作量,而将构件整合成完整系统所产生的设计和集成、测试又加强了3倍的工作量,而这些高成本的构件在根本上是独立的。
(2)、从事软件行业的乐趣:
(3)、从事软件行业的苦恼:
1、缺乏合理的时间进度是造成项目滞后的最主要原因,它比其它所有因素的总和还要大;
2、所有的软件的开发人员都是乐观主义者:相信一切都将运作良好!(我以前是一个积极的乐观者,后来发现我估算的工作量成以三比较符合实际)
3、由于我们纯粹的思维活动总是期望在实现的过程中必会碰到困难,但实际上思维的过程本身可能是有缺陷的,几乎总是有bug的;
4、围绕成本核算技术,混淆了工作量和项目进度,错误的替换了人和月(牢记一个好的例子,一个女人生孩子要十个月,十个女人生孩子还是要十个月),我们估算项目规模的时候,可以将“人月”作为一个项目规模的单位,但一定要清楚,人月不能简单替换;
5、在软件人中分解工作量,其实必然引发了额外的工作量——培训和相互沟通;
6、关于进度计划,经验是1/3计划,1/6编码,1/4构件测试和1/4的系统测试;
7、作为一种科学,我们缺乏数据估计;
8、对自己的估算技术部确定,我们面临客户和管理的压力下,经常缺乏坚实的勇气;
9、Brook法则:向进度落后的项目中增加人手,只会使进度更加落后。
向软件项目中增派人手从三个方面增加了项目必要的总体工作量:
特别需要指出的是,不为系统测试安排足够的时间简直就是一场灾难。
在现实情况中,一旦开发团队观察到进度的偏差,总是倾向于对任务进行削减。当项目延期所导致的后续成本非常高时,这常常是唯一可行的方法。
小型、精干队伍是最好的,即尽可能的少。需要协作沟通的人员的数量影响着开发成本,因为成本的主要组成部分是相互的沟通和交流,以及更正沟通不当所引起的不良结果(系统调试)。
1. 对于效率和概念的完整性来说,最好由少数干练的人员来设计和开发,而对于大型系统,则需要大量的人手,以使产品能在时间上满足要求。如何调和这两方面的矛盾呢?
2. Mills的建议:大型项目的每一个部分由一个团队解决,但是该队伍以类似外科手术的方式组建,而并非一拥而上。
3. 当进行大系统开发时:
要有一个系统结构师从上至下地进行所有的设计。要使工作易于管理,必须清晰地划分体系结构设计和实现之间的界线,系统结构师必须一丝不苟地专注于体系结构。
在进行大型系统的开发时,小型而精干的队伍太慢了(但核心的模块或功能,特别是复杂的,风险最大的应该还是应该保持小型精干的队伍为好);
4、一个首席程序员——也就是我们所谓的架构师,类似于外科手术团队架构提供了一种方法——既能获得由少数头脑产生的产品概念完整性,又能得到多位协助人员产生的总体生产率,还彻底地减少了沟通的工作量。
为了反映一系列连贯的设计思路,宁可省略一些不规则的特性和改进,也不提倡独立和无法整合的系统,哪怕它们其实包含着许多很好的设计。
1、概念完整性是系统设计中最重要的考虑因素;
2、功能与理解的复杂程度之间的比值才是系统设计的最终设计目标,而不仅仅是丰富的功能;
3、为了获得概念完整性,则设计必须由一个人或者具有共识的小型团队来设计;
4、对于大型项目,将概念完整性的设计和具体的实现分离是必要的;
5、如果要得到概念完整性,则必须由少数人来控制这些概念;
6、纪律和规则对行业是有益的。外部的体系结构的规定实际上是增强了小组的创造性而不是限制。
7、体系结构、设计和编码的工作经常可以并行的进行。
8、同工作的水平分割相比,垂直划分从根本上大大减少了劳动量,结果是使交流彻底地简化,概念完整性得到大幅提高。
一种普遍倾向是过分地设计第二个系统,向系统添加很多修饰功能和想法,它们曾在第一个系统中被小心谨慎地推迟了。
实际情况中,尽早交流和持续沟通能使结构师有较好的成本意识,以及使开发人员获得对设计的信心,并且不会混淆各自的责任分工。
面对估算过高的难题,结构师有两个选择:削减设计或者建议成本更低的实现方法--挑战估算的结果
1、尽早交流和持续沟通能使结构师有较好的成本意识,以及使开发人员获得对设计的信心,并且不会混淆各自的责任分工。
2. 面对估算过高的难题,结构师有两个选择:削减设计或者建议成本更低的实现方法--挑战估算的结果。后者是固有的主观感性反应。此时,结构师是在向开发人员的做事方式提出挑战。
想要成功,结构师必须牢记是开发人员承担创造性和发明性的实现责任,所以结构师只能建议,而不能支配;
时刻准备着为所指定的说明建议一种实现的方法,同样准备接受其他任何能达到目标的方法;
对上述的建议保持低调和平静;
准备放弃坚持所作的改进建议。
3、第二个系统是人们所设计的最危险的系统,通常的倾向总是过分的进行设计。
4、为了避免过分的设计,坚持至少拥有两个系统以上开发经验的结构师的决定。同时,保持对特殊诱惑的警觉,他可以不断提出正确的问题,确保原则上的概念和目标在详细设计中得到完整的体现。
即使是大型的设计团队,设计结果也必须由一个或两个人来完成,以确保这些决定是一致的。
允许体系结构师对实现人员的询问做出电话应答解释是非常重要的,并且必须进行日志记录和整理发布。
对于存有疑问的实现人员,应鼓励他们打电话询问相应的结构师,而不是一边自行猜测一边工作,这是一项很基本的措施。
项目经理如何确保每个人听从、理解并实现结构师的决策?对于有多个结构师的小组如何保持系统概念上的完整性。
1、手册、或者书面规格说明,是一个非常必要的工具。手册是产品的外部规格说明,它描述和规定了用户所见的每一个细节;同样的,它也是结构师主要的工作产物。手册不但要描述包括所有界面在内的用户可见的一切,它同时还要描述用户看不见的事物。后者是编程实现人员的工作范畴,而实现人员的设计和创造是不应该被限制的。体系结构设计人员必须为自己描述的任何特性准备一种实现方法,但是他不应该试图支配具体的实现过程。规格说明的风格必须清晰、完整和准确。用户常常会单独提到某个定义,所以每条说明都必须重复所有的基本要素,所以所有文字都要相互一致。
2、规格说明中,形式化定义是精确的,它们倾向于更加完整;差异得更加明显,可以更快地完成。但是形式化定义的缺点是不易理解。记叙性文字则可以显示结构性的原则,描述阶段上或层次上的结构,以及提供例子。应同时包括形式化和记叙性定义两种方式。
3、通过会议的方式,开发人员进行沟通和讨论问题。
4、不同实现之间严格要求相互兼容。如果起初至少有两种以上的实现,那么定义会更加整洁和规范。
5、对于存有疑问的实现人员,应鼓励他们打电话询问相应的结构师,而不是一边自行猜测一边工作。一种有用的机制是由结构师保存电话日志。日志中,他记录了每一个问题和相应的回答。
每周,对若干结构师的日志进行合并,重新整理,并发布给用户和实现人员。这种机制很不正式,但非常快捷和易于理解。
6、项目经理最好的朋友也是每天必须面对的敌人——产品测试组。在最后的分析中,用户是独立的监督人员。在残酷的现实使用环境中,每个细微缺陷都将无从遁形。产品测试小组则是顾客的代理人,专门寻找缺陷。不时地,细心的产品测试人员总会发现一些没有贯彻执行、设计决策没有正确理解或准确实现的地方。出于这方面的原因,设立测试小组是使设计决策得以贯彻执行的必要手段,同样也是需要尽早着手,与设计同时实现的重要环节。
巴比伦塔项目的失败是因为缺乏交流,以及交流的结果--组织。
"因为左手不知道右手在做什么,从而进度灾难、功能的不合理和系统缺陷纷纷出现。
随着工作的进行,许多小组慢慢地修改自己程序的功能、规模和速度,他们明确或者隐含地更改了一些有效输入和输出结果用法上的约定,而因此给其他部分引发了BUG。
解决方案:
团队应该以尽可能多的方式进行相互之间的交流:非正式、常规项目会议,会上进行简要的技术陈述、共享的正式项目工作手册。举行常规项目会议,会议中,团队一个接一个地进行简要的技术陈述。这种方式非常有用,能澄清成百上千的细小误解。
制定项目工作手册,并实时记录变更:首先,必须在页面上标记发生改变的文本,例如,使用页边上的竖线标记每行变化的文字。第二,分发的变更页附带独立的总结性文字,对变更的重要性以及批注进行记录。
1、巴比伦塔项目的失败是因为缺乏交流以及交流的结果——组织。项目人员之间的交流和沟通是项目能否顺利和成功的一个重要因素。
2、缺乏交流引起进度灾难、功能的不合理和系统缺陷纷纷出现。随着工作的进行,许多小组慢慢地修改自己程序的功能、规模和速度,他们明确或者隐含地更改了一些有效输入和输出结果用法上的约定,开始出现偏差。
3、团队如何进行相互之间的交流沟通:
清晰定义小组内部的相互关系和充分利用电话,能鼓励大量的电话沟通,从而达到对所书写文档的共同理解。
常规项目会议。会议中,团队一个接一个地进行简要的技术陈述。这种方式非常有用,能澄清成百上千的细小误解。
在项目的开始阶段,应该准备正式的项目工作手册。
3、项目工作手册不是独立的一篇文档,它是对项目必须产出的一系列文档进行组织的一种结构。项目所有的文档都必须是该结构的一部分。这包括目的、外部规格说明、接口说明、技术标准、内部说明和管理备忘录。
4、需要尽早和自习地设计工作手册结构;
5、事先制订良好的产品结构的工走手册“可以将后来书写的文字放置在合适的章节中”,并且可以提高产品手册的质量。
6、工作手册及时更新是至关重要的,并清楚地记录所有的版本之间的变更。
7、使用项目工作手册的原因:
技术说明几乎是必不可少的。如果某人就硬件和软件的某部分,去查看一系列相关的用户手册。他发现的不仅仅是思路,而且有能追溯到最早备忘录的许多文字和章节,这些备忘录对产品提出建议或者解释设计。
正确的文档结构非常重要。事先将项目工作手册设计好,能保证文档的结构本身是规范的。另外,有了文档结构,后来书写的文字就可以放置在合适的章节中。
控制信息发布,确保信息能到达所有需要它的人的手中。
8、团队组织的目的是减少不必要的交流和合作的数量。减少交流的方法是人力划分和限定职责范围。当使用人力划分和职责限定时,树状管理结构所映出对详细交流的需要会相应减少
编码大约只占了问题的六分之一左右,编码估计或者比率的错误可能会导致不合理的荒谬结果。
对常用编程语句而言。生产率似乎是固定的。这个固定的生产率包括了编程中需要注释,并可能存在错误的情况.
使用适当的高级语言,编程的生产率可以提高5倍。
1、项目组织的目标是为了减少必要的交流和协作量;
2、为了减少交流,组织结构包括人力资源的划分和限定职责范围;
3、传统的树状组织结构反映了权力的组织原理——不允许双重领导;
4、组织中的网状结构,是为了进行调整,以克服传统树状结构交流缺乏的困难;
5、每个项目或者子项目具有两个领导——产品负责人,技术主管或架构师,这两个职能有很大的区别,需要不同的技能;
6、两种角色的任意组合都可以是非常有效的:
产品负责人和技术主管是同一个人:这种情况可以非常轻易的应用于小型的队伍中(可以是3-6个开发人员)。在大型项目中不宜使用,原因是:同时具备产品负责人和技术负责人的人才很难找到,思考者很少,实干者更少;另外:大型项目中,每个觉得都是全职工作,一人身兼两职,未免会顾此失彼。
产品负责人作为总指挥,技术主管充当其左右手:由于产品负责人很难树立自己的技术权威,这也是这种模式的缺点,但产品负责人可以:预先声明或明确定暗示技术负责人的技术权威,支持技术负责人关于技术方面的技术决定;在基本的技术理念上与技术负责人保持一致或相似;在重大的技术问题决策前,事前充分私下沟通,达成一致后,在技术决策上充分支持技术主管的技术决策;产品负责人必须对技术主管的技术才能保持尊重和欣赏。
技术主管作为总指挥,产品负责人充当其左右手:这种情况在小的项目中可以非常有效,在大型项目也不适用。
在大型的团队中,各个小组倾向于不断地局部优化,以满足自己的目标,而较少考虑队用户的整体影响。这种方向性的问题是大型项目的主要危险。
为了满足目标,每个人都在局部优化自己的程序,很少会有人停下来,考虑一下对客户的整体影响。
培养开发人员从系统整体出发、面向用户的态度是软件编程管理人员最重要的职能。
1、除了运行时间之外,内存也是程序一个主要开销,特别是系统软件;
2、程序的规模不是坏事,但不必要的规模是不可取的,软件开发人员必须设置规模目标,控制规模;
3、除了运行时间和内存之外,控制范围硬盘的次数也是很重要的;
4、对项目经理而言,规模控制既是技术工作的一部分,也是管理工作的一部分。必须研究用户和他们的应用,以设置将开发系统的规模。接着,把这些系统划分成若干部分,并设定每个部分的规模目标。由于规模--速度权衡方案的结果在很大的范围内变化,规模目标的设置是一件颇具技巧的事情,需要对每个可用方案有深刻的了解。聪明的项目经理还会给自己预留一些空间,在工作推行时分配。仅对核心程序设定规模目标是不够的,必须把所有的方面都编入预算;
5、在指明模块有多大的同时,确切定义模块的功能;
6、培养开发人员从系统整体出发,面对用户的态度(这就是一切从整体考虑,以客户为中心)是软件项目管理人员的一项重要职责。
7、在速度不变的情况下,更多的功能意味着需要更多的空间,其中一个技巧是用功能交换尺寸,设计人员必须决定用户可选项目的精细程度。
8、考虑空间--时间的折衷。对于给定的功能,空间越多,速度越快。
项目经理可以做两件事来帮助他的团队取得良好的空间--时间折衷。一是确保他们在编程技能上得到培训,而不仅仅是依赖他们自己掌握的知识和先前的经验。特别是使用新语言或者新机器时,培训显得尤其重要。另一种方法是认识到编程需要技术积累,需要开发很多公共单元构件。
9、战略上的突破常来自数据或表的重新表达--这是程序的核心所在。数据的表现形式时编程的根本。
如果要制造一台机器,哪些是关键的文档呢?
目标:定义待满足的目标和需要,定义迫切需要的资源、约束和优先级。
首先,书面记录决策是必要的。只有记录下来,分歧才会明朗,矛盾才会突出。项目经理常常会不断发现,许多理应被普遍认同的策略,完全不为团队的一些成员所知。每个文档本身就可以作为检查列表或者数据库。
项目经理的基本职责是使每个人都向着相同的方向前进。项目经理的主要日常工作是沟通,而不是做出决定;文档使各项计划和决策在整个团队范围内得到交流。
通过周期性的回顾,他能清楚项目所处的状态,以及哪些需要重点进行更改和调整。
1、 在一片文件的汪洋中,少数文档成为了关键的枢纽,每个相关管理的工作都是围绕它们展开的,他们是项目经理的主要工具;
2、文档的跟踪维护是项目监督和预警的机制,文档本身可以作为检查列表、状态控制,也可以作为汇报的数据基础。
3、软件项目文档的内容:
目标。待完成的目标、迫切需要的资源、约束和优先级
产品技术说明。
进度表。
资金预算。
工作空间分配。
人员组织。
4、为什么要有正式的文档
首先,书面记录决策是必要的。人们能从令人迷惑的现象中得到清晰、确定的决策。
第二,文档能作为同其他人沟通的渠道,使整个计划和决策在整个团队范围内得到交流。
最后,文档可以作为数据基础和检查列表。通过周期性的回顾,他能清楚项目所处的状态,以及哪些需要重点进行更改和调整。
项目经理的任务是制订计划,并根据计划实现。只有书面计划是精确和可以沟通的。通过遵循文档开展工作,项目经理能更清晰和快速地设定自己的方向,即时是小型项目也应该如此,尽早对相关的文档进行规范化;
5、项目经理的基本职责或者说存在的目的,就是保证项目的每个人都向着同样的方向前进,而项目经理的主要日常工作则是沟通(而不是做出决策);
6、所以市面上所谓的支持项目管理人员的“完全项目信息管理工具”并不基于反映管理人员行为的有效模型。
变更的客观需要
对于大多数项目,第一个开发的系统并不合用。它可能太慢、太大,而且难以使用,或者三者兼而有之。
用户的实际需要和用户感觉会随着程序的构建、测试和使用而变化。
软件产品易于掌握的特性和不可见性,导致了它的构建人员(特别容易)面临着永恒的需求变更。
目标上(和开发策略上)的一些正常变化无可避免,事先为它们做准备总比假设它们不会出现要好得多。
为变更计划组织结构
当系统发生变化时,管理结构也需要进行调整。只要管理人员和技术人才的天赋允许,老板必须对他们的能力培养给予极大的关注,使管理人员和技术人才具有互换性。
为什么缺陷不能更彻底地被修复?
首先,看上去很轻微的错误,似乎仅仅是局部操作上的失败,实际上却是系统级别的问题,通常这不是很明显。
设计实现的人员越少、接口越少,产生的错误也就越少。
所有修改都倾向于破坏系统的架构,增加了系统的混乱程度。用在修复原有设计上瑕疵的工作量越来越少,而早期维护活动本身的漏洞所引起修复工作越来越多。
随着时间的推移,系统变得越来越无序,修复工作迟早会失去根基 ,尽管理论上系统一直可用,但实际上,整个系统已经面目全非,无法再成为下一步进展的基础。
机器在变化,配置在变化,用户的需求在变化,所以现实系统不可能永远可用。崭新的、对于原有系统的重新设计是完全必要的。
1、对于大多数项目,第一个开发的系统并不合用。可能太慢、太大,而且难以使用,或者三者兼而有之。要解决所有的问题,除了重新开始以外,没有其他的办法,即开发一个更灵巧或者更好的系统。系统的丢弃和重新设计可以一步完成,也可以一块块地实现。所有大型系统的经验都显示,这是必须完成的步骤;
2、一旦认识到实验性的系统必须被构建和丢弃,具有变更思想的重新设计不可避免;
3、用户的实际需要和用户感觉,会随着程序的构建,测试和使用而变化;
4、开发人员交付的是用户满意度,而不仅仅是实际的产品。一次一个有有经验的同事这么和我说,我深受启发,的确是这样,既然交付的主要是满意度,那么怎么样提高用户的满意度呢?要么提高您产品的质量来获取高的用户满意度,要么降低用户的期望!vista不好吗?市场反应不怎么样呢?主要原因就是大力的前期宣传,使用户的期望值太高了!
5、 为变化设计系统,包括细致的模块化、可扩展的函数、精确完整的模块间接口设计、完备的文档。另外,还可能会采用包括调用队列和表驱动技术。最重要的措施是使用高级语言和自文档技术,以减少变更引起的错误。采用编译时的操作来整合标准说明,在很大程度上帮助了变化的调整。
6、变更的阶段化是一种必要的技术。每个产品都应该有数字版本号,每个版本都应该有自己的日程表和冻结日期。在此之后的变更属于下一个版本的范畴。
7、为变更计划组织架构和团队,为变更组建团队要比为变更进行设计更加困难。
8、只要管理人员和技术人员的天赋允许,老板必须对他们的能力培养,给于充分的关注,使管理人员和技术人员具有互换性。
9、程序设计人员,不愿意书写文档,不仅仅因为惰性,更多的是来源于设计的踌躇——要为自己尝试性的设计决策作辩解。
10、程序维护中的一个基本问题是 -- 缺陷修复总会以(20%--50%)的机率引入新的bug。整个过程是前进两步,后退一步。作为引入新bug的一个后果,程序每条语句的维护需要的系统测试比其他编程要多,成本非常高。缺陷不能被彻底修复的原因:
首先,看上去很轻微的错误,似乎仅仅是局部操作上的失败,实际上却是系统级别的问题。其次,维护人员通常不是编写代码的开发人员。
11、对于一个广泛使用的产品,其维护成本通常是开发成本的40%或者更多;
12、维护成本与产品的使用人数有很大关系,用户越多,发现的错误也就越多;bug数随着产品的发布时间的推移,先是下降,然后是上升的;
13、每次修改一个bug,必须运行以前所有的测试用例,确保不会以更隐蔽的方式引入新的bug,这其实就是回归测试;
14、 使用能消除、至少是能指明副作用的程序设计方法,会在维护成本上有很大的回报。设计实现的人员越少、接口越少,产生的错误也就越少;
15、维护工作破坏系统的架构,增加了系统的混乱程度。随着时间的推移,系统变得越来越无序,无法再成为下一步进展的基础。这时,系统的重新设计完全是必要的。系统软件开发是减少混乱度的过程,软件维护是提高混乱度的过程,即使是最熟练的软件维护工作,也只是放缓了系统退化的进程。
每个编程人员也保留着编辑器、排序、内存信息转储、磁盘实用程序等工具。 这种方法对软件项目来说是愚蠢的。首先,项目的关键问题是沟通,个性化的工具妨碍--而不是促进沟通。
交互式编程
MIT的Multics项目的成果之一,是它对软件编程系统开发的贡献。在那些系统编程所关注的方面,Multics(以及后续系统,IBM的TSS)和其他交互式计算机系统在概念上有很大的不同:多个级别上数据和程序的共享和保护,可延伸的库管理,以及协助终端用户共同开发的设施。我确信在某些应用上,批处理系统决不会被交互式系统所取代。
1、项目经理应该制定一套策略,并为通用工具的开发分配资源,并意识到专业工具的需求;其实,对过去的确应该是这样的,但现在已经完全不同,主流的开发所用到通用软件和专业软件现在已经很丰富,对于我们一般的开发来说,已经足够了,需要的是,我们去学习使用,掌握这些工具,而不是去开发,但是,对于学习专门分配资源也是非常必要的,因为巧匠因为它的工具而出名。工具的重要性是不言而喻的,您看做足底按摩的,擦皮鞋的都有一套完备的工具,他们皮鞋擦得好亮,不在于他们的技巧有多好,而在于他们的工具,而不仅仅是一瓶鞋油和一个鞋刷。
2、主程序库应该化分为三部分:一系列独立的私有开发库、正处在系统测试下的系统集成子库、发布版本。在配置管理的理论中,我们的“程序”,包括与其相关的文档,其实也应该分为三个库来管理,即:开发子库、测试子库和发布子库来管理。我们是不是有这三个库呢?这是个问题!
3、高级语言的出现,不仅成倍的提高了生产率,也改进了调试,bug更少,而且更容易debug;
4、在某些应用中,批处理还有它的优势,不会被交互式所替代。
许许多多的失败完全源于那些产品未精确定义的地方。
"细致的功能定义、详细的规格说明、规范化的功能描述说明以及这些方法的实施,大大减少了系统中必须查找的bug数量。 注: 需求文档越详细,bug越少
在编写任何代码之前,规格说明必须提交给测试小组,以详细地检查说明的完整性和明确性 注: 需求文档给测试过一遍
他将程序开发划分成体系结构设计、设计实现和物理编码实现,每个步骤可以使用自顶向下的方法很好地实现。
好的自顶向下设计从几个方面避免了bug。
首先,清晰的结构和表达方式更容易对需求和模块功能进行精确的描述。
其次,模块分割和模块独立性避免了系统级的bug。
另外,细节的隐藏使结构上的缺陷更加容易识别。
第四,设计在每个精化步骤的层次上是可以测试的,所以测试可以尽早开始,并且每个步骤的重点可以放在合适的级别上。
一些糟糕的系统往往就是试图挽救一个基础很差的设计,而对它添加了很多表面装饰般的补丁。自顶向下的方法减少了这样的企图。
1、煞费苦心的、详尽的设计不但使得产品更容易使用,而且更容易开发,bug也少;
2、许许多多的失败,完全源于那些产品未精确定义的地方;
3、在编写代码之前,必须将规格说明提交给外部的测试小组,以详细的检查其完整性和明确性,开发人员无法自己完成这项工作;
4、自上而下地进行设计,逐步细化是最重要的软件开发方法之一,至今天也依然是这样,不管是对于大型的软件和小型的软件;
5、好的自上而下的设计可以从四个方面来避免了bug,减少了失败的风险:首先,清晰的结构和结构更容易对需求和模块功能进行精确的描述;其次,模块的分割和模块之间的独立性避免或者减少了系统级别的bug;第三、细节的抑制或者后置使得对于结构上的缺陷更容易被识别;第四、设计在每个阶段都是可以被测试的,使得测试可以更早的开始,并且每个步骤地重点可以放在何时的级别上。
6、自上而下的设计不是不允许回退,必要时要敢于推翻顶层的设计,重新开始;
7、在结构化编成中,程序的控制结构仅由支配的代码块的给定集合所组成;
8、系统的测试,应该在所有单元测试后开始,而且每次只添加一个构件。
9、搭建一个测试平台是非常必要和值得的,包括构建一个测试代码;
10、必须有人对变更和版本进行控制和文档化,团队成员应使用开发库德各种受控拷贝来工作,配置管理的重要性不言而喻,即使是一个人开发也是这样。
11、如何对待变更的粒度是一个严肃的问题,是小而频繁还是大而时间间隔很大?
当人们听到某个项目的进度发生了灾难性偏离时,可能会认为项目一定是遭受了一系列重大灾难。然而,通常灾祸来自白蚁的肆虐,而不是龙卷风的侵袭。
里程碑:里程碑必须是具体的、特定的、可度量的事件,能够进行清晰定义。
例如:"结构师和实现人员签字认可的规格说明","100%源代码编制完成,纸带打孔完成并输入到磁盘库","测试通过了所有的测试用例"。
如果里程碑很模糊,老板就常常会得到一份与实际情况不符的报告。
慢性进度偏离是士气杀手。[Microsoft的Jim McCarthy说:"如果你错过了一个最终期限(deadline),确保制订下一条deadline
如果在某项活动开始之前就着手估计,并且每两周进行一次仔细的修订,根据实际情况动态调整时间。当里程碑没有正确反映损失的时间,并对人们形成误导,以致事态无法挽回的时候,它会彻底碾碎小组的士气。
保持进度透明可见
一线经理的利益和老板的利益是内在冲突的。一线经理担心如果汇报了问题,老板会采取行动,这些行动会取代经理的作用,降低自己的威信,搞乱了其他计划。所以,只要项目经理认为自己可以独立解决问题,他就不会告诉老板。
有两种掀开毯子把污垢展现在老板面前的方法,它们必须都被采用。
1、一天一天的进度落后比重大灾难更难以识别和防范、弥补,而进度的延误大多是一天一天的积累下来的,因为重大的灾难发生的概率不是很高;
2、里程碑的定义必须是具体的、特定的和清晰可度量的,以至于自欺欺人时,程序员很少就里程碑的进展弄虚作假了;
3、慢性进度偏离是士气杀手;
4、不存在关键路径进度的替代品,使人们能够辨别计划偏移的情况;
5、PERT图的准备工作是使用PERT图最有价值的部分,包括,网状结构的展开,任务之间依赖关系的识别和各个任务链的估算;
6、每个老板都同时需要采取行动的异常信息以及用来分析的预警状态数据,而状态数据是难以取得的,至少难以取得真实的数据;
7、老板的不良反应一定会对真实信息的完全公开造成压制;鼓励真实的汇报和数据完全公开是非常重要的,这取决于老板对来信息的态度;
8、老板和其它所有人都可以通过评审机制来了解项目真正的状态,出于这个目的,里程碑的进度和完成文档是关键。
1、文档和程序对于软件产品一样重要,即使是程序的用户是自己;
2、培训和管理人员基本上没有能向编程人员成功的灌输对待文档的积极态度——文档能在整个生命周期对克服惰性和进度压力起到促进和激励作用,这样的失败,使由于没有能够展示如何有效地、经济的编制文档;
3、大多数的关键文档包含了软件设计的一些重要决策,因此它们应该在程序编制之前开始编写和完成;
4、为了使文档和程序更容易维护和同步,将文档合并到程序中是至关重要的;
5、流程图是被吹捧得最过分的一种程序文档。事实上,很多程序甚至不需要流程图,很少有程序需要一页纸以上的流程图。
软件工程中的根本和次要问题
没有任何技术或管理上的进展,能够独立地许诺十年内使生产率、可靠性或简洁性获得数量级上的进步。因为软件有无法规避的特性:复杂度、一致性、可变性、不可见性。产品复杂度:
复杂度不仅仅导致技术上的困难,还引发了很多管理上的问题。它使全面理解问题变得困难,从而妨碍了概念上的完整性;它使所有离散出口难以寻找和控制;它引起了大量学习和理解上的负担,使开发慢慢演变成了一场灾难。
软件可变性
软件实体经常会遭受到持续的变更压力
现实工作中,经常发生两种情况。
当人们发现软件很有用时,会在原有应用范围的边界,或者在超越边界的情况下使用软件。功能扩展的压力主要来自那些喜欢基本功能,又对软件提出了很多新用法的用户们。
其次,软件一定是在某种计算机硬件平台上开发,成功软件的生命期通常比当初的计算机硬件平台要长。即使不是更换计算机,则有可能是换新型号的磁盘、显示器或者打印机。软件必须与各种新生事物保持一致。
软件不可见性
软件是不可见的和无法可视化的。 其中的秘密就是逐步发育成长,而不是一次性搭建。
软件开发是一件棘手的事情,并不会有魔术般的解决方案,现在是从业者研究和分析革命性进展的时刻,而不是等待或希望它的出现。
现在有可能可以在软件生产率上取得逐步的进展,而不是等待不可能到来的大突破。
1、所有软件活动包括:
根本任务——打造由抽象软件实体构成的复杂概念结构。
次要任务——使用编程语言表达这些抽象实体,在空间和时间限制内将它们映射成机器语言。
2、软件任务中的必要活动,也就是那些和构造异常复杂的抽象概念结构有关的部分:
仔细地进行市场调研,避免开发已上市的产品。
在获取和制订软件需求时,将快速原型开发作为迭代计划的一部分。
有机地更新软件,随着系统的运行、使用和测试,逐渐添加越来越多的功能。
不断挑选和培养杰出的概念设计人员。
3、针对概念上根本问题的颇具前途的方法:购买和自行开发。构建软件最可能的彻底解决方案是不开发任何软件;需求精炼和快速原型;增量开发——增长,而非搭建系统;卓越的设计人员,是那些激动人心、拥有广大热情爱好者的产品往往是一个或者少数伟大设计师们的思想。