焦油坑
这本书一开始就提及“焦油坑”,将软件开发中遇到的一系列问题,比喻成很多大型强大的动物掉入焦油坑。因此提出了,如果我们想解决问题,就必须试图先去理解它。
表面上看起来好像没有任何一个单独的问题会导致困难,每个都能被解决,但是当它们相互纠缠和累积在一起的时候,团队的行动就会变得越来越慢。对问题的麻烦程度,每个人似乎都会感到惊讶,并且很难看清问题的本质。不过,如果我们想解决问题,就必须试图先去理解它。
编程系统产品的演进
左上部分是程序。它本身是完整的,可以由作者在相应的平台运行。
程序变成编程产品。
这是可以被任何人运行、测试、修复和扩展的程序。它可以运行在多种平台,供多套数据使用。要成为通用的编程产品,程序必须按照普遍认可的风格来编写,特别是输入的范围和形式必须扩展,以适用于所有可以合理使用的基本算法。接着,对程序进行彻底测试,确保它的稳定性和可靠性,使其值得信赖。这就意味着必须准备、运行和记录详尽的测试用例库,用来检查输入的边界和范围。此外,要将程序提升为程序产品,还需要有完备的文档,每个人都可以加以使用、修复和扩展。经验数据表明,相同功能的编程产品的成本,至少是已经过测试的程序的三倍。
程序变成编程系统中的一个构件单元。
它是在功能上能相互协作的程序集合,具有规范的格式,可以进行交互,并可以用来组装和搭建整个系统。要成为系统构件,程序必须按照一定的要求编制,使输入和输出在语法和语义上与精确定义的接口一致。同时程序还要符合预先定义的资源限制——内存空间、输入输出设备、计算机时间。最后,程序必须同其它系统构件单元一道,以任何能想象到的组合进行测试。
编程系统产品。
和以上的所有的情况都不同的是,它的成本高达九倍。然而,只有它才是真正有用的产品,是大多数系统开发的目标。
之后简单介绍了软件开发这个行业,并提及了开发中的乐趣和苦恼。
编程的乐趣:
1. 首先是一种创建事物的纯粹快乐。
2. 快乐来自于开发对其他人有用的东西。
3. 看到它们精妙地运行, 得到预先所希望的结果。
4. 学习的乐趣,解决问题的人可以从中学习新的事物。
5. 创造的方式灵活,易于精炼和重建,容易实现概念上的设想。
编程的苦恼:
1. 编程必须追求完美。
2. 由他人来设定目标,供给资源,提供信息,编程人员很少能控制工作环境和工作目标。管理的术语来说,个人的权威和他所承担的责任是不相配的。
3. 概念性设计是有趣的,但寻找琐碎的 bug却只是一项重复性的活动。
4. 投入了大量的精力,产品在即将或完成的时候,却显得陈旧过时。
人月神话
在众多软件项目中,缺乏合理的时间进度是造成项目滞后的最主要原因。
原因:
1. 我们对估算技术缺乏有效的研究。
2. 我们采用的估算技术隐含地假设人和月可以互换,错误的将进度与工作量相互混淆。
3. 对自己的估算缺乏信心,导致不会持续进行估算这项工作。
4. 对进度缺少跟踪和监督。
5. 当意识到进度的偏移时,下意识的反应是增加人力。
思考方式是在估计和进度安排中使用的工作量单位:人月。成本的确随开发产品的人数和时间的不同,有着很大的变化,进度却不是如此。因此我认为用人月作为衡量一项工作的规模是一个危险和带有欺骗性的神话。它暗示着人员数量和时间是可以相互替换的。
由于人和人之间是需要相互交流的,所以人员和时间之间不是增加相同倍数的人员就能减少相同倍数的开发时间。
因为软件开发本质上是一项系统工作——错综复杂关系下的一种实践——沟通、交流的工作量非常大,它很快会消耗任务分解所节省下来的个人时间。从而,添加更多的人手,实际上是延长了,而不是缩短了时间进度。
软件任务的进度安排
1/3 计划
1/6 编码
1/4 构件测试和早期系统测试
1/4 系统测试,所有的构件已完成
1. 分配给计划的时间比寻常的多。即便如此,仍不足以产生详细和稳定的计划规格说明,也不足以容纳对全新技术的研究和摸索。
2. 对所完成代码的调试和测试,投入近一半的时间,比平常的安排多很多。
3. 容易估计的部分,即编码,仅仅分配了六分之一的时间。
向进度落后的项目中增加人手,只会使进度更加落后。
外科手术队伍
需要协作沟通的人员的数量影响着开发成本,因为成本的主要组成部分是相互的沟通和交流,以及更正沟通不当所引起的不良结果(系统调试)。这一点,也暗示系统应该由尽可能少的人员来开发。
大型项目上的每一个部分由一个团队解决,但是该队伍以类似外科手术的方式组建,而并非一拥而上。
首席程序员。他亲自定义功能和性能技术说明书,设计程序,编制源代码,测试以及书写技术文档。首席程序员需要极高的天分、十年的经验和应用数学、业务数据处理或其他方面的大量系统和应用知识。
副手,他是首席程序员的后备,能完成任何一部分工作,但是相对具有较少的经验。他的主要作用是作为设计的思考者、讨论者和评估人员。副手经常在与其他团队的功能和接口讨论中代表自己的小组。他需要详细了解所有的代码,研究设计策略的备选方案。显然,他充当首席程序员的保险机制。他甚至可能编制代码,但针对代码的任何部分,不承担具体的开发职责。
管理员。首席程序员是老板,他必须在人员、加薪等方面具有决定权,但他决不能在这些事务上浪费任何时间。因而,他需要一个控制财务、人员、工作地点安排和机器的专业管理人员,该管理员充当与组织中其他管理机构的接口。Baker 建议仅在项目具有法律、合同、报表和财务方面的需求时,管理员才具有全职责任。否则,一个管理员可以为两个团队服务。
编辑。首席程序员负责产生文档——出于最大清晰度的考虑,他必须书写文档。对内部描述和外部描述都是如此。而编辑根据首席程序员的草稿或者口述的手稿, 进行分析和重新组织,提供各种参考信息和书目,对多个版本进行维护以及监督文档生成的机制。
两个秘书。 管理员和编辑每个人需要一个秘书。管理员的秘书负责项目的协作一致和非产品文件。
程序职员。 他负责维护编程产品库中所有团队的技术记录。该职员接受秘书性质的培训,承担机器码文件和可读文件的相关管理责任。
工具维护人员。现在已经有很多文件编辑、文本编辑和交互式调试等工具,因此团队很少再需要自己的机器和机器操作人员。但是这些工具使用起来必须毫无疑问地令人满意,而且需要具备较高的可靠性。首席程序员则是这些工具、服务可用性的唯一评判人员。他需要一个工具维护人员,保证所有基本服务的可靠性,以及承担团队成员所需要的特殊工具(特别是交互式计算机服务)的构建、维护和升级责任。即使已经拥有非常卓越的、可靠的集中式服务,每个团队仍然要有自己的工具人员。因为他的工作是检查他的首席程序员所需要的工具。工具维护人员常常要开发一些实用程序、编制具有目录的过程库以及宏库。
测试人员。首席程序员需要大量合适的测试用例,用来对他所编写的工作片段,以及对整个工作进行测试。因此,测试人员既是为他的各个功能设计系统测试用例的对头,同时也是为他的日常调试设计测试数据的助手。他还负责计划测试的步骤和为测试搭建测试平台。
语言专家。在大多数计算机项目中,总有一两个乐于掌握复杂编程语言的人。 这些专家非常有帮助,很快大家会向他咨询。这些天才不同于首席程序员,首席程序员主要是系统设计者以及考虑系统的整体表现。而语言专家则寻找一种简洁、有效的使用语言的方法来解决复杂、晦涩或者棘手的问题。他通常需要对技术进行一些研究(两到三天)。通常一个语言专家可以为两个到三个首席程序员服务。
在传统的队伍中大家是平等的,出现观点的差异时,不可避免地需要讨论和进行相互的妥协和让步。由于工作和资源的分解,不同的意见会造成策略和接口上的不一致,例如谁的空间会被用作缓冲区,然而最终它们必须整合在一起。而在外科手术团队中,不存在利益的差别,观点的不一致由首席程序员单方面来统一。这两种团队组建上的差异——对问题不进行分解和上下级的关系——使外科手术队伍可以达到客观的一致性。
贵族专制、民主政治和系统设计
概念完整性应该是最重要的考虑因素。也就是说为了反映一系列连贯的设计思路,宁可省略一些不规则的特性和改进,也不提倡独立和无法整合的系统,哪怕它们其实包含着许多很好的设计。
编程系统(软件)的目的是使计算机更加容易使用。由于目标是易用性,功能与理解上复杂程度的比值才是系统设计的最终测试标准。对于给定级别的功能,能用最简洁和直接的方式来指明事情的系统是最好的。
概念的完整性要求设计必须由一个人,或者非常少数互有默契的人员来实现。而进度压力却要求很多人员来开发系统。有两种方法可以解决这种矛盾。第一种是仔细地区分设计方法和具体实现。第二种是类似外科医生团队,一种崭新的组建编程开发团队的方法。
当建议由体系结构的团队来编写计算机和编程系统的所有外部技术说明时,编程人员提出了三个反对意见:
该说明中的功能过于繁多,而对实际情况中的成本考虑比较少
结构师获得了所有创造发明的快乐,剥夺了实现人员的创造力
当体系结构的队伍缓慢工作时,很多实现人员只能空闲地坐着等待
画蛇添足
想要成功,结构师必须牢记是开发人员承担创造性和发明性的实现责任。
所以结构师只能建议,而不能支配;
时刻准备着为所指定的说明建议一种实现的方法,同样准备接受其他任何能达到目标的方法;
对上述的建议保持低调和平静;
准备放弃坚持所作的改进建议;
第二个系统是设计师们所设计的最危险的系统。而当他着手第三个或第四个系统时,先前的经验会相互验证,得到此类系统通用特性的判断,而且系统之间的差异会帮助他识别出经验中不够通用的部分。
一种普遍倾向是过分地设计第二个系统,向系统添加很多修饰功能和想法,它们曾在第一个系统中被小心谨慎地推迟了。
开发第二个系统所引起的后果与纯粹的功能修饰和增强明显不同,也就是说存在对某些技术进行细化、精炼的趋势。由于基本系统设想发生了变化,这些技术已经显得落后。
结构师如何避免画蛇添足。他可以有意识关注那些系统的特殊危险,运用特别的自我约束准则,来避免那些功能上的修饰;根据系统基本理念及目的变更,舍弃一些功能。
项目经理如何避免画蛇添足。他必须坚持至少拥有两个系统以上开发经验结构师的决定。同时,保持对特殊诱惑的警觉,他可以不断提出正确的问题,确保原则上的概念和目标在详细设计中得到完整的体现。
贯彻执行
手册、或者书面规格说明,是一个非常必要的工具,尽管光有文档是不够的。手册是产品的外部规格说明,它描述和规定了用户所见的每一个细节;同样的,它也是结构师主要的工作产物。
手册不但要描述包括所有界面在内的用户可见的一切,它同时还要避免描述用户看不见的事物。
规格说明的风格必须清晰、完整和准确。用户常常会单独提到某个定义,所以每条说明都必须重复所有的基本要素,所以所有文字都要相互一致。这往往使手册读起来枯燥乏味,但是精确比生动更加重要。
规格说明书定义了兼容性,描述了将达到的目标,列举外部显示的各个部分: 源于某个模型与其他模型差异,带来变化的部分和保持不变的部分;或者是某个给定模型的拷贝不同于其他拷贝的地方;甚至是工程上的变更引起拷贝自身上的差异。而这正是一个规格说明作者所应该追求的精确程度,他必须在仔细定义规定什么的同时,定义未规定什么。
形式化定义的优缺点,形式化定义是精确的,它们倾向于更加完整;差异得更加明显,可以更快地完成。但是形式化定义的缺点是不易理解。记叙性文字则可以显示结构性的原则,描述阶段上或层次上的结构,以及提供例子。它可以很容易地表达异常和强调对比的关系,最重要的是,它可以解释原因。在表达的精确和简明性上,目前所提出的形式化定义,具有了令人惊异的效果,增强了我们进行准确表达的信心。但是,它还需要记叙性文字的辅助,才能使内容易于领会和讲授。出于这些原因,我想将来的规格说明同时包括形式化和记叙性定义两种方式。
在规定系统外部功能的同时,几乎所有的形式化定义均会用来描述和表达硬件系统或软件系统的某个设计实现。语法和规则的表达可以不需要具体的设计实现,但是特定的语义和意义通常会通过一段实现该功能的程序来定义。理所当然,这是一种实现,不过它过多地限定了体系结构。所以必须特别指出形式化定义仅仅用于外部功能,说明它们是什么。
如同前面所示,形式化定义可以是一种设计实现。反之,设计实现也可以作为一种形式化定义的方法。
为什么巴比伦塔会失败
1. 清晰的目标?是的,尽管幼稚得近乎不可能。而且,项目早在遇到这个基本的限制之前,就已经失败了。
2. 人力?非常充足。
3. 材料?在美索不达米亚有着丰富的泥土和柏油沥青。
4. 足够的时间?没有任何时间限制的迹象。
5. 足够的技术?是的,金字塔、锥形的结构本身就是稳定的,可以很好分散压力负载。对砖石建筑技术,人们有过深刻的研究。同样,项目远在达到技术限制之间,就已经失败了。
那么,既然他们具备了所有的这些条件,为什么项目还会失败呢?他们还缺乏些什么?两个方面——交流,以及交流的结果——组织。他们无法相互交谈,从而无法合作。当合作无法进行时,工作陷入了停顿。通过史书的字里行间,我们推测交流的缺乏导致了争辩、沮丧和群体猜忌。很快,部落开始分裂——大家选择了孤立,而不是互相争吵。
团队如何进行相互之间的交流沟通:
1. 非正式途径
清晰定义小组内部的相互关系和充分利用电话,能鼓励大量的电话沟通,从而达到对所书写文档的共同理解。
2. 会议
常规项目会议。会议中,团队一个接一个地进行简要的技术陈述。这种方式非常有用,能澄清成百上千的细小误解。
3. 工作手册
在项目的开始阶段,应该准备正式的项目工作手册。理所应当,我们专门用一节来讨论它。
项目工作手册
1. 是什么
项目工作手册不是独立的一篇文档,它是对项目必须产出的一系列文档进行组织的一种结构。项目所有的文档都必须是该结构的一部分。这包括目的、外部规格说明、接口说明、技术标准、内部说明和管理备忘录。
2. 为什么
针对这些备忘录对产品提出建议或者解释设计
控制信息发布
3. 处理机制
实时更新是至关重要的
4. 现在如何让入手
大型编程项目的组织架构
团队组织的目的是减少不必要交流和合作的数量,因此良好的团队组织是解决上述交流问题的关键措施。
减少交流的方法是人力划分和限定职责范围。当使用人力划分和职责限定时, 树状管理结构所映出对详细交流的需要会相应减少。
树状编程团队:
1. 任务
2. 产品负责人
a) 他组建团队,划分工作及制订进度表。
b) 他主要的工作室与团队外部,向上和水平地沟通。
c) 他建立团队内部的沟通和报告方式。
d) 他确保进度目标的实现,根据环境的变化调整资源和团队的构架。
3. 技术主管和结构师
a) 他对设计进行思考,识别系统的自部分,勾画内外部结构。
b) 他提供整个设计的一致性和概念完整性。
c) 他控制系统的复杂程度。
d) 他提供问题的解决方案,根据需要调整系统设计。
e) 他的工作几乎完全是技术性的。
三种存在关系:
产品负责人和技术主管是同一个人。
产品负责人作为总指挥, 技术主管充当其左右手。
技术主管作为总指挥, 产品负责人充当其左右手。
4. 进度
5. 人力的划分
6. 各部分之间的接口的定义
交流和交流的结果:组织,是成功的关键。交流和组织的技能需要管理者仔细考虑,相关经验的积累和能力的提高同软件技术本身一样重要。
胸有成竹
工作量的估计:
1. 用于计划进度、编码、构件测试和系统测试的比率。仅仅通过对编码部分的估计,然后应用上述比率,是无法得到对整个任务的估计的。
2. 构建独立小型程序的数据不适用于编程系统产品,因此小项目数据的外推是没有意义的。
3. 工作量和代码行数不是线性关系,而是指数型关系。
工作量 = (常数)×(指令的数量)^1.5
结论:
1. 对于常用的编程语句而言,生产效率似乎是固定的。这个固定的生产效率包括了编程中需要注释,并可能存在错误的情况。
2. 生产率随着系统复杂性或者难度增加而降低。
3. 使用适当的高级语言,编程的生产率可以提高5倍。
削足适履
作为成本的程序空间:
由于规模是软件系统产品用户成本中如此大的一个组成部分,开发人员必须设置规模的目标,控制规模,考虑减小规模的方法,就像硬件开发人员会设立元器件数量目标,控制元器件的数量,想出一些减少零件的方法。
对项目经理而言,规模控制既是技术工作的一部分,也是管理工作的一部分。他必须研究用户和他们的应用,以设置将开发系统的规模。首先,仅对核心程序设定规模目标是不够的,必须把所有的方面都编入预算。在先前的大多数操作系统中,系统驻留在磁带上,长时间的磁带搜索意味着它无法自如地运用在程序片段上。
空间预算的多少和控制并不能使程序规模减小,为实现这一目标,它还需要一些创性和技能。
1. 用功能交换尺寸
2. 考虑空间时间的折衷
提纲挈领
计算机产品的文档:
1. 目标:定义待满足的目标和需要,定义迫切需要的资源、约束和优先级。
2. 技术说明:计算机手册和性能规格说明。它是在计划新产品时第一个产生,并且最后成的文档。
3. 进度、时间表
4. 预算:预算不仅仅是约束。对管理人员来说,它还是最有用的文档之一。预算的存在会迫使技术决策的制订,否则,技术决策很容易被忽略。更重要的是,它促使和澄清了策略上的一些决定。
5. 组织机构图
6. 工作空间的分配
7. 报价、预测、价格:这三个因素互相牵制,决定了项目的成败。
软件项目的文档:
1. 做什么:目标。定义了待完成的目标、迫切需要的资源、约束和优先级。
2. 做什么:产品技术说明。以建议书开始,以用户手册和内部文档结束。速度和空间说明是关键的部分。
3. 时间:进度表
4. 资金:预算
5. 地点:工作空间分配
6. 人员:组织图。
为什么要有正式的文档:
1. 首先,书面记录决策是必要的。只有记录下来,分歧才会明朗,矛盾才会突出。
2. 第二,文档能够作为同其他人的沟通渠道。
3. 最后,项目经理的文档可以作为数据基础和检查列表。
项目经理的任务是制订计划,并根据计划实现。但是,只有书面计划是可以精确沟通的。计划中包括了时间、地点、人物、做什么、资金。这些少量的关键文档封装了一些项目经理的工作。如果一开始就认识到它们的普遍性和重要性,那么就可以将文档作为工具友好地利用起来,而不会让它成为令人厌烦的繁重任务。通过遵循文档开展工作,项目经理能更清晰和快速地设定自己的方向。
未雨绸缪
一旦认识到试验性的系统必须被构建和丢弃,具有变更思想的重新设计不可避免, 从而直面整个变化现象是非常有用的。第一步是接受这样的事实:变化是与生俱来的,不是不合时宜和令人生厌的异常情况。开发人员交付的是用户满意程度,而不仅仅是实际的产品。用户的实际需要和用户感觉会随着程序的构建、测试和使用而变化。
软件维护,它主要包含对设计缺陷的修复。
系统软件开发是减少混乱度(减少熵)的过程,所以它本身是处于亚稳态的。软件维护是提高混乱度(增加熵)的过程,即使是最熟练的软件维护工作,也只是放缓了系统退化到非稳态的进程。
干将莫邪
项目的关键问题是沟通,个性化的工具妨碍——而不是促进沟通。其次,当机器和语言发生变化时,技术也会随之变化,所有工具的生命周期是很短的。毫无疑问,开发和维护公共的通用编程工具的效率更高。
辅助机器和数据服务
1. 仿真装置:可靠并不等于精确。
2. 编译器和汇编平台:编译器和汇编软件需要运行在可靠的辅助平台上,为目标机器编译目标代码。
3. 程序库和管理。
4. 编译工具。
5. 文档系统:在所有的工具中,最能节省劳动力的,是运行在可靠平台上的、计算机化的文本编辑系统。
6. 性能仿真装置。
高级语言:使用高级语言的主要原因是生产率和调试速度。
交互式编程:多个级别上数据和程序的共享和保护,可延伸的库管理,以及协助终端用户共同开发的设施。
整体部分
剔除bug的设计。
1. 产品的概念完整性在使它易于使用的同时,也使开发更容易进行以及 bug 更不容易产生。
2. 测试规格说明。在编写任何代码之前,规格说明必须提交给测试小组,以详细地检查说明的完整性和明确性。
3. 自顶向下的设计。好的自顶向下设计从几个方面避免了bug。首先,清晰的结构和表达方式更容易对需求和模块功能进行精确的描述。其次,模块分割和模块独立性避免了系统级的bug。另外,细节的隐藏使结构上的缺陷更加容易识别。设计在每个精化步骤的层次上是可以测试的,所以测试可以尽早开始,并且每个步骤的重点可以放在合适的级别上。
4. 结构化编程。
构建单元调试。
1. 本机调试。
2. 内存转储。
3. 快照。
4. 交互式调试。计算机将多个程序载入到内存中准备运行,被调试的程序和一个只能由程序控制的终端相关联,由监督调度程序控制调试过程。
5. 测试用例。
系统集成调试。
1. 使用经过调试的构件单元。
2. 搭建充分的测试平台。
a) 伪构件
b) 微缩文件
c) 伪文件
d) 辅助程序
3. 控制变更
4. 一次添加一个构件
5. 阶段化、定期变更。
祸起萧墙
如何根据一个严格的进度表来控制项目:
1. 制订进度表:进度表上每一件事,被称为里程碑,它们都有一个日期。里程碑的选择只有一个原则,那就是,里程碑必须是具体的、特定的、可度量的事件,能够进行清晰定义。
2. 减少角色的冲突:首先老板必须区别行动信息和状态信息。他必须规范自己,不对项目经理可以解决的问题做出反应,并且决不在检查状态报告的时候做安排。
对于这种逐渐延迟的进度,Brooks提议简历项目里程碑,并且持续的修订项目计划,这样无论最后的情况变得多么糟糕,它都不会有太大的变化。里程碑是指百分之百的事件,必须有明显的边界和没有歧义。这样就很好有人可以在里程碑进展上弄虚作假。
另一方面
需要什么样的文档:
不同用户需要不同级别的文档。某些用户仅仅偶尔使用程序,有些用户必须依赖程序,还有一些用户必须根据环境和目的的变动对程序进行修改。
1. 使用程序:每个用户都需要一段对程序进行描述的文字。
a) 目的。主要的功能是什么?开发程序的原因是什么?
b) 环境。程序运行在什么样的机器、硬件配置和操作系统上?
c) 范围。输入的有效范围是什么?允许显示的合法范围是什么?
d) 实现功能和使用的算法。精确地阐述它做了什么。
e) 输入-输出格式。必须是确切和完整的。
f) 操作指令。包括控制台及输出内容中正常和异常结束的行为。
g) 选项。用户的功能选项有哪些?如何在选项之间进行挑选?
h) 运行时间。在指定的配置下,解决特定规模问题所需要的时间?
i) 精度和校验。期望结果的精确程度?如何进行精度的检测?
2. 验证程序:除了程序的使用方法,还必须附带一些程序正确运行证明,即测试用例。这些用例可以根据输入数据的范围划分成三个部分。
a) 针对遇到的大多数常规数据和程序主要功能进行测试的用例。它们是测试用例的主要组成部分。
b) 数量相对较少的合法数据测试用例,对输入数据范围边界进行检查,确保最大可能值、最小可能值和其他有效特殊数据可以正常工作。
c) 数量相对较少的非法数据测试用例,在边界外检查数据范围边界,确保无效的输入能有正确的数据诊断提示。
3. 修改程序:调整程序或者修复程序需要更多的信息。
a) 流程图或子系统的结构图。
b) 对所用算法的完整描述,或者是对文档中类似描述的引用。
c) 对所有文件规划的解释。
d) 数据流的概要描述——从磁盘或者磁带中,获取数据或程序处理的序列——以及在每个处理过程完成的操作。
e) 初始设计中,对已预见修改的讨论。特性、功能回调的位置以及出口。原作者对可能会扩充的地方以及可能处理方案的一些意见。另外,对隐藏缺陷的观察也同样很有价值。
4. 流程图:流程图是被吹捧得最过分的一种程序文档。事实上,很多程序甚至不需要流程图,很少有程序需要一页纸以上的流程图。
流程图显示了程序的流程判断结构,它仅仅是程序结构的一个方面。
没有银弹
所有软件活动包括根本任务,打造由抽象软件实体构成的复杂概念结构,次要任务使用编程语言表达这些抽象实体,在空间和时间限制内将它们映射成机器语言。
1. 仔细地进行市场调研,避免开发已上市的产品。
2. 在获取和制订软件需求时,将快速原型开发作为迭代计划的一部分。
3. 有机地更新软件,随着系统的运行、使用和测试,逐渐添加越来越多的功能。
4. 不断挑选和培养杰出的概念设计人员。