编程的最困难部分,是将做事的方式往追求完美的方向调整
缺乏的时间进度是造成项目滞后的最主要原因:
* 我们对估算技术缺乏有效的研究
* 我们采用的估算技术隐含地假设人和月可以互换
* 由于对自己的估算缺乏信心,软件经理通常不会有耐心地持续地进行估算这项工作
* 对进度缺少跟踪和监督
* 当意识到进度的偏移时,下意识(以及传统)的反应是增加人力
系统编程的进度安排背后的假设:
* 一切都将动作良好,每一项任务仅花费它所“应该”花费的时间
* 用人月作为衡量一项工作的规模是一个危险和带有欺骗性的神话,它暗示着人员数量和时间是可以相互替换的
* 由于我们的乐观主义,通常实际出现的缺陷数量比预料的要多得多。因此,系统测试进度的安排常常是编程中最不合理的部分
* 为了满足顾客期望的日期而造成的不合理进度安排,在软件领域中比其他的工程领域要普遍的多
软件任务的进度安排:
* 1/3计划
* 1/6编码
* 1/4构件测试和早期系统测试
* 1/4系统测试,所有的构件已完成
Brooks法则:向进度落后的项目中增加人手,只会使进度更加落后
项目的时间依赖于顺序上的限制,人员的数量依赖于单个子任务的数量。从这两个数值可以推算出进度时间表,该表安排的人员较少,花费的时间较长(唯一的风险是产品可能会过时)。相反,分派较多的人手,计划较短的时间,将无法得到可行的进度表
需要协作沟通的人员的数量影响着开发成本,因为成本的主要组成部分是相互的沟通和交流,以及更正沟通不当所引起的不良结果(系统调试)。系统应该由尽可能少的人员来开发
Mills建议大型项目的每一个部分由一个团队解决,该队伍以类似外科手术的方式组建:
* 外科医生:首席程度员,天分、经验、能力
* 副手:外科医生的后备,较少的经验
* 管理员:控制财务、人员、工作地点安排和机器的专业管理人员
* 编辑:分析重组开发文档
* 两个秘书:管理员和编辑每人需要一个秘书
* 程序职员:维护编程产品库中所有团队的技术记录
* 工具维护人员:保证所有基本服务的可靠性,以及承担团队成员所需要的特殊工具的构建、维护和升级责任
* 测试人员:大量合适的测试用例,搭建测试平台
* 语言专家:寻找合适的编程语言
进度压力要求很多人员来开发系统,有两种方法解决这种矛盾:
* 仔细地区分设计方法和具体实现
* 一种新的组建编辑开发团队的方法
对于非常大型的项目,将设计方法、体系结构方面的工作与具体实现相分离是获得概念完整性的强有力方法
系统的结构师,是运用专业技术知识来支持用户的真正利益,而不是维护销售人员所鼓吹的利益,体系结构陈述的是发生了什么,而实现描述的是如何实现
整个创造性活动包括了三个独立的阶段:体系结构、设计实现、物理实现,在实际情况中,它们往往可以同时开始和并发地进行
尽早交流和持续沟通能使结构师有较好的成本意识,以及使开发人员获得对设计的信心,并且不会混淆各自的责任分工
想要成功,结构师必须:
* 牢记是开发人员承担创造性和发明性的实现责任,所以结构师只能建议,而不能支配
* 时刻准备着为所指定的说明建议一种实现的方法,同样准备接受其他任何能达到目标的方法
* 对上述的建议保持低调和平静
* 准备放弃坚持所作的改进建议
项目经理如何避免画蛇添足?他必须坚持至少拥有两个系统以上开发经验结构师的决定 ,同时,保持对特殊诱惑的警觉,他可以不断提出正确的问题,确保原则上的概念和目标在详细设计中得到完整的体现
手册、或者书面规格说明,是一个非常必要的工具,尽管光有文档是不够的。手册是产品的外部规格说明,它描述和规定了用户所见的每一个细节。不但要描述包括所有界面在内的用户可见的一切,它同时还要避免描述用户看不见的事物。后者是编程实现人员的工作范畴
思路是大约十个人的想法,但如果想保持文字和产品之间的一致性,则必须由一个或两个人来完成将其结论转换成书面规格说明的工作。对于在整个设计中,保证这些看似琐碎的问题处理原则上的一致性,决不是一件无关紧要的事情
“决不要携带两个时钟出海,带一个或三个”
设立测试小组是使设计决策得以贯彻执行的必要手段,同样也是需要尽早着手,与设计同时实施的重要环节
巴比伦塔的失败原因:交流、组织。交流和交流的结果—组织,是成功的关键。交流和组织的技能需要管理者仔细考虑,相关经验的积累和能力的提高同软件技术本身一样重要
团队如何进行交流:
* 非正式途径
* 会议
* 工作手册
团队组织的目的是减少不必要交流和合作的数量,因此良好的团队组织是解决上述交流问题的关键措施
减少交流的方法是人力划分和限定职责范围
人力划分存在三种可能关系:
* 产品负责人和技术主管是同一个人(小型团队)
* 产品负责人作为总指挥,技术主管充当其左右手(大型团队)
* 技术主管作为总指挥,产品负责人充当其左右手(中小型团队)
工作量=(常数) * (指令的数量)
两个关于工作量的结论:
* 对常用的编程语句而言。生产率似乎是固定的。这个固定的生产率包括了编程中需要注释,并可能存在错误的情况。
* 使用适当的高级语言,编程的生产率可以提高5倍
没有人可以在自始至终提倡更紧密的软硬件设计集成的同时,又仅仅就规模本身对软件系统提出批评
由于规模是软件系统产品用户成本中如此大的一个组成部分,开发人员必须设置规模的目标,控制规模,考虑减小规模的方法,就像硬件开发人员会设立元器件数量目标,控制元器件的数量,想出一些减少零件的方法
规模控制:
* 应该制订总体规模的预算,应该制订后台存储访问的预算
* 在指明模块有多大的同时,确切定义模块的功能
* 保持持续的警觉,确保连贯的系统完整性
数据的表现形式是编程的根本
计算机产品的文档:
* 目标
* 技术说明
* 进度、时间表
* 预算
* 组织机构图
* 工作空间的分配
* 报价、预测、价格
大学科系的文档:
* 目标
* 课程概述
* 学位要求
* 研究报告(申请基金时,还要求计划)
* 课程表和课程的安排
* 预算
* 教室分配
* 教师的研究生助手的分配
软件项目的文档:
* 做什么:目标
* 做什么:产品技术说明
* 时间:进度表
* 资金:预算表
* 地点:工作空间分配
* 人员:组织图
为什么要有正式的文档:
* 书面记录决策是必要的
* 文档能够作为同其他人的沟通渠道
* 项目经理的文档可以作为数据基础和检查列表
变化是与生俱来的,不是不合时宜和令人生厌的异常情况。开发人员将会的是用户满意程度,而不仅仅是实际的产品。用户的实际需要和用户感觉会随着程序的构建、测试和使用而变化
为变更计划系统:细致的模块化、可扩展的函数、精确完整的模块间接口设计、完备的文档,调用队列和表驱动,使用高级语言和自文档技术,数字版本号
为变更计划组织框架:
* 把所有计划、里程碑、日程安排都当作是尝试性的,以方便进行变化
* 使管理人员和技术人才具有互换性
* 管理人员需要参与技术课程,高级技术人才需要进行管理培训
程序维护中的一个基本问题是——缺陷修复总会以(20-50)%的机率引入新的bug。设计实现的人员越少、接口越少,产生的错误也就越少
系统软件开发是减少混乱度(减少熵)的过程,所以它本身是处于亚稳态的。软件维护是提高混乱度(增加熵)的过程,即使是最熟练的软件维护工作,也只是放缓了系统退化到非稳态的进程
“关键的工作是产品定义。许许多多的失败完全源于那些产品未精确定义的地方”
关键的地方和构建无bug程序的核心,是把系统的结构作为控制结构来考虑,而不是独立的跳转语句
系统集成调试:
* 使用经过调试的构建单元(单元测试)
* 搭建充分的测试平台(伪构件,桩、模)
* 控制变更
* 一次添加一个构件
* 阶段(量子)化、定期变更
里程碑:必须是具体的、特定的、可度量的事件,能够进行清晰的定义,有明显边界和没有歧义
“我认为软件开发中困难的部分是规格化、设计和测试这些概念上的结构,而不是对概念进行表达和对实现逼真程序进行验证”
软件系统的内在特性:复杂度、一致性、可变性、不可见性
针对概念上根本问题的颇具前途的方法:
* 购买和自行开发,构建软件最可能的彻底解决方案是不开发任何软件
* 需求精练和快速原型
* 增量开发——增长,而非搭建系统,先运行起来
* 卓越的设计人员
大多数有丰富经经验的程序员拥有自己的私人开发库,可以使他们使用大约30%的重用代码来开发软件。公司级别的重用能提供70%的重用代码量,它需要特殊的开发库和管理支持。公司级别的重用代码也意味着需要对项目中的变更进行统计和度量,从而提高重用的可信程度
每一份发布的程序拷贝应该包括一些测试用例,其中一部分用于校验输入数据,一部分用于边界输入数据,另一部分用于无效的输入数据
一个整洁、优雅的编程产品必须向它的每个用户提供一个条理分明的概念模型,这个模型描述了应用、实现应用的方法以及用来指明操作和各种参数的用户界面使用策略