软件工程领域40年不朽神话中的产品哲学
金蝶云社区-Kevin嚼薯片
Kevin嚼薯片
54人赞赏了该文章 611次浏览 未经作者许可,禁止转载编辑于2018年12月21日 14:37:24

作者:Kevin嚼薯片(微信:kevinwork)

注:本文独家发布自金蝶云社区



软件工程的焦油坑

N年前,我还在创业lead团队的某一天,有一个下属塞了一本书让我好好读读,说对我有帮助。那就是我今天要介绍《人月神话》。

初看这本书的名字,以为是一个什么奇怪的狼人小说,但看下去才真的觉得是一本创世著作。首先这本书不同于普通的面向对象程序设计、算法竞赛一类的书,而更像是软件工程类的书。时至今天,而且这本书已经40周年纪念版了,书中提出的很多问题已经解决、甚至已经过时的,但确实提供给了软件项目管理的一些内容知识,同时对于产品经理而言,是一个深入了解软件开发的进阶读物。

其中很多内容确实对很多固化思维模式的转换起到了不少影响,所以我在此乐于结合自己的经历和语言,把书中所提及的内容,做一些系统化的总结,并抽取对产品经理岗位有用的部分。


第一章  产品开发过程中的焦油坑

1. 软件程序分为4种:个人使用的独立构件程序、接口集成的编程系统、通用化的编程产品、编程系统产品,最后者的开发工作量是最前者的9倍。其中软件构件产品化有3倍工作量,将软件构件整合成完整系统所需要的设计、集成、测试又有3倍工作量。

2. 编程行业给从业人员的乐趣:创建事物,开发对其他人有用的东西,灵活组合,不重复任务可以不断学习,易于驾驭使用。

3. 给从业人员的苦恼:难以将做到追求完美,依靠一些自己无法控制的东西(如别人的代码),完成任务才能建立权威,过程中的枯燥劳动,项目越接近完成收敛越慢,总面临产品过时的情况。


第二章  产品开发工作量的人月矛盾

1. 创造活动分为3个阶段:构思-实现-交流。首先我们构思出一个事物,接着通过介质将它实现,然后当某人阅读书本或者使用你创造出来的事物,也就是和作者沟通,从而创造过程结束。

2. 单个任务,在“一切都会运转良好” + “不会延迟”上具有概率上的可能性。然而大型的开发编程活动中,都包含很多任务,各个任务之间还有相互关联,前后关系,所以所有任务叠加都能实现“一切都会运转良好” + “不会延迟”的概率变得很小,甚至接近于无。

3. 成本的确随着开发人员的人数和时间的不同,有很大的变化,进度却并不是如此。     


人员和时间之间的关系:完全可以分解的任务

(1)人数和时间互换仅适用于:某个任务可以分解给参与人员,并且他们之间不需要相互交流。这在割小麦,收棉花的工作中是可行的,在系统编程中近乎不可能。


人员和时间之间的关系:无法分解的任务

(2)由于次序上的限制,任务无法分解时,人手的添加对进度没有帮助。不管多少个母亲,孕育一个生命都需要10个月。


人员和时间之间的关系:需要沟通的可分解任务

(3)对于任务可以分解,但子任务之间需要沟通和交流的任务,必须在计划中考虑沟通的工作量。沟通所增加的负担由两部分组成:1)培训:1 vs 多;2)相互交流:N vs M。相互交流这种情况会随着人数的增加,变得越来越不可收拾,按n(n-1)/2递增。


人员和时间之间的关系:关系错综复杂的任务

(5)软件开发本质上是一项错综复杂关系下的一种实践,沟通交流的工作量非常大,它很快会消耗任务分解所节省下来的个人时间,导致添加人手,实际上是延长了而不是缩减了时间。

4. 软件任务的进度安排,作者给出了自己使用多年的经验法则:1/3 计划、1/6 编码、1/4 构件测试和早期系统测试、1/4 系统测试,所有的构件已完成。

5. 分配了近乎一半时间给测试,编码时间仅占1/6。很少有项目允许给测试分配一半的时间,但大多数项目的测试实际上花费了项目的一半时间。为了避免二次成本,早期的进度策划时,允许充分的系统测试时间是非常重要的。

6. 为了满足顾客期望的日期而造成的不合理的进度安排,在软件领域比其他的任何领域要普遍的多。解决方案:1)开发并推行生产率表、缺陷率、估算规则等等;2)挺直腰杆,坚持自己的估计。

7. 为落后进度的项目添加人手,会因为成本的增加(重新分配任务的中断,培训新人,额外的沟通)导致进度会更加落后。


第三章 构建如同外科手术一样的产品队伍

1. 相同程度的培训,优秀的人员的生产率是较差成员的10倍;

2. 对于效率和概念上的完整性来说,最好由少数干练的人员来设计和开发,而对于大型系统,则需要大量的人手,以使产品能在时间上满足要求-----相对于普通情况下,如果是大型的可以将领导人拆出来做成一个决策组,来提升协调。

3. Mills建议大型项目分成小部分,每个小部分由一个团队解决,而团队则是以外科手术团队的方式来构建。团队成员的职责如下:


4. 传统两人队伍,每人负责一部分工作的设计和实现;外科手术团队中,外科医生和副手了解所有的设计和全部的代码,保证了工作概念上的完整性。

5. 传统团队中,大家平等,出现观点的差异时,不可避免的需要讨论和进行相互的妥协和让步,由于工作和资源的分解,不同的意见导致会造成策略和接口上的不一致;外科手术团队中,外科医生和副手是上下级关系,并且不分解问题,可以达到客观上的一致性。

6. 外科手术团队中,其他人员职能的专业化分工是高效的关键,它使得成员之间采用非常简单的交流模式。

7. 如果需要几百人参与的大型项目,扩建团队过程的成功依赖于每个部分的概念完整性得到了彻底的提高,决定设计的人员是原来的1/7或者更少。所以,可以让200人解决问题,而仅仅需要协调20个人。整个系统必须具备概念上的完整性,要有一个系统结构师从上到下进行所有的设计;要使工作易于管理,必须清晰的划分体系结构设计和实现之间的界限,系统结构师必须一丝不苟的专注于体系结构。


第四章 专制、民主和系统设计的关系

1. 系统的目标是易用性,能用最简洁和直接的方式来指明事情的系统是最好的。

2. 简洁和直白来自于概念上的完整性。每个部分必须反映相同的原理需求的一致平衡。易用性实际上需要设计的一致性和概念上的完整性。

3. 概念上的完整性要求设计必须由一个人,或具有共识的小型团队来完成。对于非常大型的项目,把设计方法、体系结构方面的工作(更偏需求方面)和具体实现相分离是获得概念完整性的强有力方法。

4. 如果要获得概念上的完整性就必须有人控制这个概念,这是无需任何歉意的必须的贵族专制;

5. 纪律、规则、规矩对整个行业是有益的。外部的限制是为了增强,而不是用来限制一个小组的创造性的。

6. 体系结构、设计实现、物理实现这些工作是可以并行执行的。


第五章 产品架构的画蛇添足

1. 尽早交流和持续沟通能使结构师有较好的成本意识,使开发人员获得对设计的信心,并且不会混淆各自的责任分工;

2. 结构师如何成功地实现影响:

(1)结构师只提出建议,实现留给程序员;

(2)时刻准备着为所指定的说明建议一种实现方法,准备接受其他任何实现的可行方案;

(3)对上述的建议保持低调和平静;

(4)对所建议的进行改进放弃坚持;

(5)听取开发人员对结构上的改进的建议。

3. 结构师开发第二个系统应避免画蛇添足,有意识的关注这个系统的特殊危险,避免功能上的过于修饰,根据系统基本理念及目的变更,舍弃一些功能。

image.png


第六章 产品开发中要贯彻执行

1. 文档化的规格说明:描述和规定了用户所见的每一个细节,保持文字和产品之间的一致性。

2. 形式化定义:必须采用形式定义和记叙性的定义中的一种来作为标准,另外一种作为辅助,他们都可以作为表达的标准。

3. 规格说明应同时包括形式化和记叙性定义两种,但必须以一种作为标准,另一种作为辅助描述,并照此明确地进行划分(形式化地设计定义,记叙性定义加深理解);

4. 允许体系结构师对实现人员的询问做出电话式的应答解释,并且必须进行整理和发布,(现在可以使用电子邮件的形式)。

5. 项目经理最好的朋友就是他每天面对的对手:独立的产品测试机构/小组。


第七章 为什么巴比伦塔会失败——沟通的重要性

1. 原因:缺乏交流以及交流产生的结果(组织)

2. 交流的作用:

(1)团队成员之间产生理解的偏差的处理,

(2)应该尽可能团队应该尽可能多的方式进行相互之间的交流(非正式的简要的技术陈述会、共享的正式项目工作手册)

3. 项目工作手册

(1)项目工作手册不是独立的一篇文档,它是对项目必须产生的一系列文档进行组织的一种结构

(2)项目所有的文档都是工作手册中的一部分

(3)应当尽早和仔细地设计工作手册结构

(4)事先制定良好结构的工作手册可以将后来的东西添加进去,提高产品质量

(5)每个团队成员都应该了解工作手册

(6)注意实时的更新

(7)工作手册的使用者更多的注意与上个版本中的变更在哪;

(8)尽可能的采用较为先进的,易于查看的方式保存文档;

(9)用变更条和修订日期等方式来标记文字;仍然需要栈结构的电子化记录变更小结;

(10)各个部分封装起来,尽可能看它提供什么接口,入口是什么出口是什么掌控好即可;

4. 组织架构

(1)组织架构的目的是减少一些不必要的交流和协作量;

(2)为了减少不必要的交流组织结构包括了人力划分和限定职责范围;

(3)不要出现双重领导的情况,容易导致变更不可控;

(4)交流的话是网状的,当然根据情况需要适应性调整;

(5)每个子项目有两个不同的领导,分别掌控对外和对内,需要不同的技能,一个是项目经理,一个是架构师(技术主管);

5. 两种角色组合是有效的

(1)项目经理和技术主管是同一个人

(2)产品负责人做老大,而技术主管是副手

(3)技术主管是老大,产品负责人当副手


第八章 开发过程中的胸有成竹

1. 仅通过对编码部分的估计,然后应用计划进度、编码、构件测试和系统测试的比率是无法得到对整个任务的估计的

2. 构建独立小型程序的数据不适用于编程系统产品(就好像把100米短跑记录外推,得出人类可以在3分钟之内跑完1英里的结构一样)

3. 程序开发随着规模的大量增长而增长

4. 全职的程序员仅将50%时间用于编程和调试

5. 对常用的编程语句而言,生产率似乎是固定的。这个固定的生产率包括了编程中需要注释并可能存在错误的情况


第九章 对产品削足适履

1. 规模是软件系统产品用户成本中一个很大的组成部分,对项目经理而言,规模控制既是技术工作的一部分,也是管理工作的一部分。必须研究用户和用户的需求,以设置待开发系统的规模;

2. 在大型项目中,为了满足目标,每个人都在局部优化自己的程序,很少会有人停下来,考虑一下对客户的整体影响,这种导向和缺乏沟通是最大的危险。

3. 在整个实现过程期间,系统结构师必须保持持续的警觉,确保连贯的系统完整性。

4. 培养开发人员从系统整体出发、面向用户的态度是软件编程管理人员最重要的职能。

5. 为了帮助团队取得良好的“空间-时间”折中: 确保他们在编程技能上得到培训,而不仅仅是依赖他们自己的才能和先前的经验;认识到编程需要技术积累,需要开发很多公共单元构件。


第十章 产品文档的提纲挈领

1. 少数文档会成为项目的关键枢纽,每个项目管理的工作都围绕着它们运转,它们是经理们的主要个人工具;

2. 对于软件项目,关键是:目标、用户手册、内部文档、进度、预算、组织机构图和工作空间分配

3. 对每个关键文档维护提供状态监督和预警机制;

4. 每个文档本身就可以作为检查列表或者数据库;

5. 项目经理的基本职责是使每个人都向着相同的方向前进,所以他的主要工作是沟通,而不是做出决定;

6. 项目经理的文档可以作为数据基础和检查列表。通过周期性的回顾,他能清楚项目所处的状态,以及哪些需要重点进行更改和调整。


第十一章 对于产品的未雨绸缪

1. 试验性工厂和增大规模:对于大多数项目,第一个开发的系统可能太慢、太大,而且难以使用。系统的丢弃和重新设计可以一步完成,也可以一块块地实现。

2. 唯一不变的就是变化本身:开发人员交付的是用户满意程度,而不仅仅是有形的产品。用户的实际需要和用户感觉会随着程序的构建、测试和使用而变化,事先为变化做好准备。

3. 为变更设计系统:变更的阶段化是一种必要的技术。每个产品应该有数字版本号,每个版本都应该有自己的日程表和冻结日期,在此之后的变更属于下一个版本的范畴。

4. 为变更计划组织架构:程序员不愿意为设计写文档,因为他需要为这种设计做辩解。使管理人员和技术人才可以进行互换,所以项目目标、进展和管理问题必须在高级人员整体中得到共享。

5. 程序的维护主要是由于各种变更组成的,维护成本受用户数目的影响,用户越多,所发现的BUG越多,通常是其开发成本的40%或者更多。每次修复后要先运行所有的测试用例来避免新BUG。

6. 使用能消除或至少能指明副作用的程序设计方法,会在维护成本上有很大的回报。设计实现的人员越少、接口越少,产生的错误也就越少。

7. 所有修改都倾向于破坏系统的架构,增加了系统的熵(混乱度)。即使是最熟练的软件维护工作也只是延缓了系统退化到最混乱的程度的进程,以至于有时候须有重新进行设计。


第十二章 干将莫邪——产品开发利器

1. 项目经理应该制定一套策略,并为通用工具的开发分配资源,同时也需要意识到专业工具的需求

2. 开发系统的队伍需要自己的目标机器,进行调试开发工作,安排一位成员专门维护这个东西,保证机器上的标准软件是及时更新和实时可用的

3. 主程序库中应该划分成(1)独立开发私有库,即开发环境;(2)正在测试的库,即测试环境;(3)发布版本,即线上环境;

image.png


第十三章 系统开发的整体部分

1. 详尽的体系结构工作可以使产品更加易于使用,而且更容易开发,且BUG不容易产生。

2. 编写代码前,规格说明书必须提交给外部测试人员测试。

3. 系统开发分为体系结构设计、设计实现和物理编码实现,每个步骤都可以使用自上而下的方法很好地实现。

4. 软件系统开发过程中出乎意料的困难部分是系统集成测试,系统调试花费的时间会比预料的更长,它的困难证明了需要一种完备系统化和可计划的方法。

5. 系统集成调试要求只能在每个部分都能正常运行之后开始。

6. 系统测试期间,一次只能添加一个构件。


第十四章 祸起萧墙——如何避免灾难

1. 根据一个严格的进度表来控制大型项目第一步是制定进度表(由里程碑和日期组成)。

2. 里程碑必须是具体的、特定的和可度量的时间,能进行清晰的定义。

3. 大型项目的估计行为需要每两周或者一周左右进行一次重新估计时间,期间各种错误估计都会随着计划结束变得越来越少。

4. 必须关心每一天的滞后,它们是大灾祸的基本组成元素。

5. 必须有评审机制,使所有成员可以通过它了解真正的状态。出于这个目的,里程碑的进度和完成文档是关键。


第十五章 除产品开发外的另外一面

1. 对于软件产品,程序和文档同样重要。

2. 即使是给程序员自己用的东西也必须有一些辅助,因为长时间不改之前的代码,会忘。

3.培训、学习、以及管理人员应该对文档有积极的态度。

4. 每个发布的程序应该提供一些测试用例。

5. 流程图不要太精细,除非要求。

6. 为了使文档易于维护,在程序代码中通过添加注释是必要的


第十六章 没有银弹——最后的忠告

1. 仔细地进行市场调研,避免开发已上市的产品;在获取和制定软件需求时,将快速原型开发作为迭代计划的一部分;有机地更新软件,逐渐添加越来越多的功能;不断挑战和培养杰出新生代的概念设计人员。

2. 软件系统特性:复杂度、一致性、可变性和不可见性。

3. 未来希望:面向对象编程(目前正在大规模使用),人工智能,专家系统,自动化编程,图形化编程,程序自验证,新的计算机环境和工具,工作站。

4. 如果需要快速解决可以使用的方法:购买,自行开发需求软件,需求精炼和快速原型,增量开发而不是直接搭建系统,使用卓越的设计人员。




欢迎【关注】我,和给我【点赞】。

赞 54