Skip to content

时间:2016年1月1日

地点:成都

天气:晴,霾遮日

空气质量:重度污染,203

心情:平静,并无跨年的喜悦,暂忘雾霾的困扰。唯一萦绕心头的是:我似乎很有必要找几本哲学的著作看看,尤其是笛卡尔的哲学思想。

《项目管理修炼之道》已经读完数周,我却找不到一种合适的方式来完成笔记:全书参考颇多,细节繁杂,作者的主要目的似乎是让读者需要时查阅,而不是让读者通过本书看懂项目管理。而我,就是想看懂项目管理。

当我完成这则笔记的时候,逐渐意识到:规划、估算、测量是项目经理引导项目走向成功的三种非常重要的能力。

一.什么是项目?什么是项目经理?

“项目:一个独特的任务或是系统化的流程,其目的是创建新的产品或服务,完成交付产品和服务,标志着项目的结束。项目都有风险,并且受制于有限的资源。

……

项目经理:负责向团队清晰说明完成的含义,并带领团队完成项目的人。完成,是指产品符合组织对这个产品的要求,也能满足客户使用这个产品的需要。”

二.项目管理的框架是什么?

简单而论,项目管理中需要平衡三种要素(传统“铁三角”):成本、时间、质量/范围。但是,本书推荐的方法强调关键驱动因素、约束因素、浮动因素三个方面。

  • 1.首先,从客户的角度写下客户的期望:客户想要什么(功能集合)?期望何时收到交付物(发布时间)?交付物的质量如何(缺陷等级)?

  • 2.其次,从项目服务者的角度写下项目的约束:环境如何?能否灵活安排团队?必须遵守什么流程?团队成员有哪些?团队能做什么?预算多少?

  • 3.再次,对比期望列表和约束列表,以“项目成功的必要因素”为标准,按重要性罗列条目,从“期望列表”中选出一个关键驱动因素(理想情况下应该只有一个),比如:发布时间;从“约束列表”中选出两三个约束因素(理想情况下应该只有一个)。

  • 4.然后,从剩余条目中找出至少三个浮动因素,浮动因素越多,项目越容易管理。

  • 5.最后,对比没有入选的条目,如果有比已经选中的条目更重要的,就进行更换,从而最终确定关键驱动因素、约束因素和浮动因素。

*原书没有明确“关键驱动的因素”要在“期望列表”中选择,但这是显然的,如果客户的期望都不是驱动项目成功的因素,我们还有必要做项目吗?另外,作者在这里的方法其实是:将与项目成功的有关因素全部提炼出来,然后进行简化,从而为后期的项目管理工作确定管理对象,这种方法应该是先分析再建模,化繁为简——这便是笛卡尔的经典思想。

三.与客户沟通时,如何明确真正的驱动因素?

  • 1..预测未来:让出资人设想项目即将交付,而有的功能还未实现,还有严重的缺陷需要修复,要想实现所有功能并修复缺陷是不可能的,这时看出资人如何选择。

  • 2.询问与上下文无关的问题,例如:项目要怎么样才算成功?为什么想得到这样的结果?这种解决方案对你来说价值何在?这个系统要解决什么样的问题?这个系统可能会造成什么样的问题?

四.为什么要编写项目章程?

  • 1.项目章程会明确记录项目的需求(明确驱动因素后就可以挖掘项目需求)和约束。

  • 2.项目章程会帮助项目经理思考如何进行项目规划。

  • 3.整个团队和出资人都可以查看项目章程,以此确保他们对项目有关的决策可以达成一致。

  • 4.启动项目时,编写项目章程可以让大家知道应该完成什么目标,以及项目干系人提出的约束条件。

  • 5.即使不知道完成项目需要的细枝末节,编写章程也有助于发现潜在的问题。

  • 6.项目章程可以帮助项目经理和团队理解风险和成功标准,大家也可以籍此考虑组织和操控项目的方式。

五.项目章程可以包含哪些内容?

项目章程要设计简短,目的是帮助团队赶紧启动,它不会包含团队对于这个项目“完成”的定义,也不会介绍团队如何组织项目,但是已经足够开展工作。具体可以包括如下内容:

  • 1.远景:发起项目的缘由何在?项目的价值何在?要用描述远景的句子说明项目的价值。

  • 2.需求:某些情况下,项目唯一的需求,就是在特定日期之前发布某些功能。

  • 3.目标:目标与需求不同,项目不一定必须交付它的目标,目标是项目经理希望通过项目要达成的目的,虽然客户和出资人可能不赞同。

  • 4.成功标准:项目完成后,客户能用交付的产品做什么,这就是成功标准的定义。例如:在第一季度发布;客户不需要访问网站就可以打开安装包,下载软件等。要确保成功标准在项目经理的掌控之中(项目经理无法掌控的任务不该包含在成功标准中)。

  • 5.ROI:估算投资回报率。

六、如何区分规划和日程安排?

规划是指制定带有发布条件的项目计划;日程安排是对项目工作的有序描述。

七、如何制定项目规划?

项目规划不必完美无缺,而且也不可能做到。规划的目的是能让项目启动起来,同时能让大家看到成功的希望。有了项目规划,团队成员的注意力就能放到预期的项目产出上来。

项目经理要用规划来整理想法,规划的形式最好能在组织内更多项目中反复使用,可以参考如下模板:

  • 1.产品意图:简单描述产品——为什么要开发这个产品、它能为公司带来哪些效益等等。

  • 2.历史记录:复查之前版本的有关数据:技术债务、发布频率、发布后发现的缺陷数、客户报告的问题等。

  • 3.发布条件:详细列举项目产品的关键可交付物。制订的发布条件要符合SMART原则(确定的、可测量的、可达成的、相关的、可跟踪的)

  • 4.目标:即为项目章程中的目标。

  • 5.项目组织:说明团队的职责分配、如何使用生命周期组织管理工作、要采取哪些关键措施、是否有决策人可以影响当前项目、还要说明项目的一般运作方式等。

  • 6.日程总览:要包括主要里程碑,还要说明人们可以从这些里程碑处可以得到什么。

  • 7.人员配备(人员曲线):说明人员配备情况,如果需要从其他团队调动人手,要说明何时需要多少,何种类型的人员。

  • 8.建议日程:列出主要里程碑,使用甘特图或黄色便利贴均可,注意更新。

  • 9.风险列表:罗列至少前十名的风险因素,以便监控和更新。

/*

项目启动后,便是根据组织项目的生命周期选择合适的日程安排方式,其中,利用写有里程碑或具体任务的便利贴进行日程安排是一种便捷有效的手段。

估算是一种非常重要的技能,例如:在项目管理中,就需要通过工作估算来预测某项任务的完成时间。这里,“化繁为简”的思想再次发挥重要作用:将大任务拆分为小任务(“小石子”),由于小任务更简单,对小任务的估算也就会更加准确。另一方面,与一开始就把整个项目就规划出来相比(这样会出错,而且浪费时间),波浪式规划(一个持续不断而且很详细的日程安排方法,只覆盖几周的时间。完成了一周详细工作安排之后,可以再继续安排一周的详细工作)是本书推荐的一种更合理的规划方式。

在项目管理过程中,项目经理需要掌控项目、控制项目节奏,以下是本书的一些建议:

*/

八、如何掌控项目?

  • 1.掌控项目的节奏。

  • 2.举行中途回顾。

  • 3.为需求排序。

  • 4.用时间盒限定需求相关的工作。

  • 5.将迭代限制在4周或是更少的时间内。

  • 6.使用波浪式规划和日程安排。

  • 7.创建跨职能团队。

  • 8.根据项目的风险选择生命周期模型。

  • 9.保持合理的工作时间。

  • 10.使用“小石子”。

  • 11.管理干扰。

  • 12.管理缺陷,从项目初就开始。

九、如何保持项目节奏?

  • 1.在项目中持续使用集成。

  • 2.为构建创建自动化冒烟测试。

  • 3.按功能实现,而不是按架构(首先实现具有最高价值的功能;按功能调试;按功能测试)。

  • 4.多几只眼睛盯着产品。

  • 5.准备重构。

  • 6.通过用例、用户故事、角色和场景来定义需求。

  • 7.分离需求与GUI设计。

  • 8.尽可能使用低保真度原型。

/*

整个项目管理周期中,必然需要召开很多会议,如同《谷歌和亚马逊如何做产品》中对会议的分析:解决问题、收集信息、传递信息——开会的三大目的。如果一场会议无法达到上述目的中的任意一种,或者说这样的会议对于参加者而言没有价值,那就没有召开的必要。

与估算一样,测量也是项目管理中的重要环节(测量获得的数据可以组成“仪表盘”),最直接的问题就是:测量项目进度——正确、有效的决策必然是建立在准确测量的基础之上。以下是测量项目的一些建议:

*/

十、项目测量有哪些注意事项?

  • 1.使用速度图迭代内容图作为首选。

  • 2.数据是工具,不是目的。图表应该为你服务。

  • 3.如果无法获取需要的数据,项目经理就遇到了比数据更严重的问题,需要首先解决这个问题。

/*

测试是项目管理过程中保障项目质量的一项重要措施。本书对测试的基本建议就是:将测试与开发集成起来,一边开发一边测试,甚至推荐了TDD(测试驱动开发)这样的方法。只有通过了各类测试(不仅仅是系统测试和单元测试)的项目才可以最终交付。

最后,本书作者强调:在项目结束时,即使已经在项目中进行过中期回顾的项目,也一定要再做项目回顾。

*/

《程序员必读之软件架构》——本是朋友买的书,却将电子优惠券送给了我,于是,我顺手买了此书的电子版。当这本书的前半段几乎磨损尽我的耐心时,终于在后半段发现了所谓的干货,以至于我认为有必要整理成一则笔记。

一、软件系统的结构:

“假设一个软件使用了面向对象的编程语言,我喜欢用如下方式来思考它的结构:软件系统由多个容器构成,容器又由多个组件构成,组件由一个或多个类实现。大多数软件系统都可以用这种简单的逻辑结构单元的层级关系来建模。”

1.抽象结构:

  • 类:对我们大多数人来说,在一个面向对象的世界里,类是软件系统的最小结构单元。

  • 组件:组件可以想象成一个或多个类组成的逻辑群组。比如,其他组件可以使用审计组件或认证服务,来确定对特定资源的请求是否放行。组件通常由多个类在更高层次的约束下组合而成。

  • 容器:容器是指一个在其内部可以执行组件或驻留数据的东西。它可以是从网络或应用服务器直到富客户端应用或数据库的任何东西。作为整个系统的一部分,容器通常是可执行文件,但未必是各自独立的流程。比如,我把每个Java EE网络应用或.NET网站都看作一个独立的容器,不管它们是否运行在同一个物理服务器流程中。从容器的角度理解一个软件系统的关键在于,任何容期间的通信可能都需要一个远程接口,比如SOAP网络服务、RESTful接口、Java RMI、Microsoft WCF、报文,等等。

  • 系统:系统是最高的抽象层次,代表了能够提供价值的东西。一个系统由多个独立的容器构成,例如金融风险管理系统、网络银行系统、网站等。

2.静态视图:

  • 语境:设定场景的高层次图,包括关键的系统依赖和参与者。

  • 容器:容器图显示了高层次的技术选择,容器如何分担指责、如何通信。

  • 组件:组件图可以让你看到每个容器的关键逻辑组件及之间的关系。

  • 类:这是一个可选的细节层次。如果想解释某个模式或组件将(或已经)被怎样实现,我会画少量高层次UML类的图。促使我给软件系统的部分分类画图的原因包括软件的复杂性,团队的规模和经验。我画的UML图通常会是草图而非综合性的模型。

*由上述4部分构成的软件架构图被作者称为C4。原书后面对于语境图、容器图、组件图的详解,以及“软件文档即指南”的思想,条理清晰,层次分明,对于项目管理工作非常有帮助。例如:软件指南中可以包含的内容:语境、功能性概览、质量属性、约束、原则、软件架构、外部接口、代码、数据、基础设施架构、部署、运营和支持、决策日志。

二、风险风暴:

与“软件系统的结构”一样,本书用作风险识别的方法:“风险风暴”也是一种可以被其他行业所借鉴的方法,至少在我看来,这种方法是相当有趣的——我们完全能够以此建立一种“风险识别模型”。

“风险风暴是一项快速、有趣的技术,提供了一种识别和可视化风险的协同方法。另一方面,这种技术可用于任何能够可视化的东西:从企业架构到业务流程和工作流。它可以在一个软件开发项目的开始阶段使用,也可以一直使用,或者在迭代计划或回顾中使用。”

步骤1:画一些架构图

第一步是在白板或大张的活动挂图纸上画一些架构图。C4是一个很好的起点,因为它提供了一种获得一组抽象层次各异的图的方法,其中一些可用来标出架构中的不同风险。图越大越好。

步骤2:分别识别风险

风险可以是主观的,所以请团队中每个人(架构师、开发者、项目经理、业务人等)都站在架构图前,各自写下他们能够识别的风险,一个风险用一张便利贴。此外,请他们根据概率影响量化每个风险。理想情况下,用不同颜色的便利贴来表示不同的风险优先级。你可以将这部分练习划分为5~10分钟的时间段,以免拖延,这一步应该保持沉默,每个人收好各自的便利贴。这里是一些要寻找的风险的例子:

  • 第三方系统的数据格式意外变更;

  • 外部系统不可用;

  • 组件运行过慢;

  • 组件无法伸缩;

  • 关键组件崩溃;

  • 单点故障;

  • 数据被破坏;

  • 基础设施故障;

  • 磁盘填满;

  • 新技术未按预期工作;

  • 新技术使用过于复杂;

  • 等等。

有了软件开发评估,根据人们的经验,他们对风险的看法可以是主观的。如果你计划使用一种新技术,但愿团队中有人能识别出相关的风险。另外,有人可能会对使用新技术的风险量化得比较高,而其他人如果已经用过同一种技术,可能感觉就不一样。各自识别风险让每个人都可以为风险识别流程作出贡献。你将更好地了解团队感知的风险,而不仅仅是那些设计软件或领导团队的人的看法。

步骤3:汇总图中的风险

接下来,请大家把自己的便利贴贴在架构图上,邻近风险被识别出的区域。举个例子,如果你识别出一个组件会有运行过慢的风险,就把便利贴贴在架构图中那个组件的上方。

这种技术的这个部分是视觉的,一旦完成,你就能一眼看到风险最高的区域在哪里。如果有人识别出类似的风险,随着大家想法的汇总,图的上方会贴满便利贴。

步骤4:对风险设定优先级

现在你们可以拿下每一张便利贴(或一堆便利贴),就如何量化已识别的风险达成共识。

  • 单张便利贴:问识别出风险的人他们的理由是什么,并就其概率影响达成共识。经过讨论,如果概率或影响是“无”,就从架构图上把便利贴拿下来,但别扔掉它(确保你保留了识别风险的记录,包括那些后来被认为概率或影响是“无”的)。

  • 成堆的便利贴:如果每张便利贴的概率和影响都相同,那就完成了。如果不是,则需要用与规划扑克或推广德尔菲法环节中相同的评估方法,就如何量化风险达成共识。看看哪些与众不同,并相应地了解人们量化风险背后的根据。

初次听到《人月神话》的名字时,我以为是科幻小说,就像有人以为是爱情小说一样。只有当我看到它的英文书名:《The Mythical Man-Month》,才恍然大悟——此“月”(month)非彼“月”(moon)。这种理解障碍是语言差异引起的,几天来我都在想,翻译为什么不能更直白一点?《软件工程中的“人员-时间”问题》或其他什么。

事实上,这本关于软件工程和项目管理的著作,最早出版于1975年,中文版的序言作者将其作为“神品”收藏,书中的很多思想至今仍不过时,以至于不止一个读者说,“每隔一两年就会拿出来读一遍。”——也许他们只是想验证书中的预言是否仍然有效。

我所读的是32周年中文纪念版,除了经典而几乎没有争议的“人月”——衡量软件工程生产率的一个指标,作者还补充了更加深刻的“没有银弹”——一篇发表于1986年的论文(全书其实就是一本论文集),虽然“没有银弹”引起了很多争议,但是其中所探讨的问题充满魅力、思想洋溢,甚至我觉得这本书再版时应该改名“没有银弹”。

出于做笔记的习惯,我边读边想:有关软件工程和项目管理方面,全书提出了这么多经典的观点和方法,虽然几十年过去了,但是如今看来,对的当然令人兴奋,错的却也有错的理由。我是不是应该把这些内容都摘录下来,未来也许会用到?但是第18章改变了我的想法——作者亲自对各章的观点和方法进行了归纳和整理。所以,这本书的确很值得珍藏!而我,则根据自己印象最深的几点,完成了下面这则笔记……

一、“没有银弹”:

“软件的复杂度是根本属性,不是次要因素。因此,抽掉复杂度的软件实体描述常常也去掉了一些本质属性。数学和物理学在过去三个世纪取得了巨大的进步,数学家和物理学家们为复杂的现象建立了简化的模型,从模型中抽取出各种特性,并通过试验来验证这些特性。这些方法之所以可行,是因为模型中忽略的复杂度不是被研究现象的根本属性。当复杂度是本质特性时,这些方法就行不通了。”

“爱因斯坦曾不断地重申自然界一定存在着简化的解释,因为上帝不是专横武断和反复无常的。软件工程师却无法从类似的信念中获得安慰,他必须掌握的很多复杂度是随心所欲、毫无规则可言的,来自若干必须遵循的人为惯例和系统。它们随接口的不同而改变,随时间的推移而变化,并且,这些变化不是必需的,仅仅由于他们是不同的人——而非上帝——设计的结果。”

当我们试图用图形来描述软件结构时,发现它不仅仅包含一个,而是很多相互关联、重叠在一起的图形。这些图形可能代表控制流程、数据流、依赖关系、时间序列和名字空间的相互关系等等。它们通常不是有较少层次的扁平结构。实际上,在上述结构上建立概念控制的一种方法是强制将关联分割,直到可以层次化一个或多个图形。”

原书中,这两段话分别针对软件四项内在特性中的两项:“复杂度”和“一致性”而论,这三段话让我有豁然开朗的感觉,所以相当喜欢!

  • 第一段加深了我对数学和物理的理解——我们的学习思路的确是这样的;

  • 第二段反映了一个心结:我们都想将精力放在解决问题本身,而不是因为人为设计不一致造成的无谓却必要的劳动上;

  • 第三段则介绍用图形描述软件结构的一种抽象方法——强制将关联分割。

“没有银弹”全篇(包括16、17章)则深化了我对软件的认识,这源自本篇的中心论点:软件存在根本的和次要的两种困难,为了提高软件开发的效率,人们同时在为解决这两种困难而努力着。如今,解决次要的困难已经取得了巨大进步,但根本的困难仍然困扰着人们——这也是作者“没有银弹”论断的来源。(将软件开发比作人狼——简单明了的东西可能变成落后进度、超出预算、存在大量缺陷的怪物,杀死人狼的武器是银弹,但是解决软件开发困难的银弹可能并不存在,因为人们面对的是软件的根本困难。)

由于作者所有的讨论都是针对软件的根本困难和次要困难,所以,理解这两种困难对于深化软件的认识至关重要,这也是我认为全书最精华的地方——作者讲得深入浅出,又发人深省。

··················································

作者认为,所有的软件活动包括两种任务:

  • 1.根本任务:打造构成抽象软件实体的复杂概念结构。

  • 2.次要任务:使用编程语言表达这些抽象实体,在空间和时间限制内将它们映射成机器语言。

相应的,软件就存在两种困难:

  • 1.根本的困难:软件特性中固有的困难。

  • 2.次要的困难:出现在目前生产中,但并非那些与生俱来的困难。

作者的观点是:

“我认为软件开发中困难的部分是规格说明、设计和测试这些概念上的结构,而不是对概念进行表达和对现实逼真程度进行验证。”

所以,软件无法规避的内在特性是(虽然书中没有明说,但我能感觉到,这些就是作者所说的根本困难):

  • 1.复杂度:没有任何两个软件部分是相同的(至少在语句的级别上)……数字计算机本身就比人类建造的大多数东西复杂……软件系统的状态又比计算机的状态多若干个数量级……软件的复杂度是根本属性,不是次要因素……

  • 2.一致性:许多情况下,因为是开发最新的软件,它必须遵循各种接口。另一些情况下,软件的开发目标就是兼容性……很多复杂性来自保持与其他接口的一致方面,对软件的任何再设计,都无法简化这些复杂特性……

  • 3.可变性:软件实体经常会遭受到持续的变更压力……系统中的软件包含了很多功能,而功能是最容易感受变更压力的部分……软件可以很容易地进行修改——它是纯粹思维活动的产物,可以无限扩展……所有成功的软件都会发生变更……功能扩展的压力主要来自那些喜欢基本功能,又对软件提出了很多新用法的用户们……软件一定是在某种计算机硬件平台上开发,成功软件的生命期通常比当初开发软件所用的计算机硬件平台要长……简言之,软件产品扎根于文化的母体中,如各种应用、用户、自然及社会规律、计算机硬件等等。后者持续不断地变化着,这些变化无情地强迫软件也随之变化……

  • 4.不可见性:软件是不可见的和无法可视化的……软件的客观存在不具有空间的形体特征……除去软件结构上的限制和简化方面的进展,软件仍然保持着无法可视化的固有特性,从而剥夺了一些具有强大功能的概念工具的构造创意。这种缺憾不仅限制了个人的设计过程,也严重阻碍了思路相互之间的交流。

*注:这里,未必说作者所说的都是对的,我们当然需要批判性思维,但是当这方面的知识远逊于作者时,将其作为知识吸收,从而促进自己的思考,显然是个不错的选择。

文章中剩余的部分则讨论了解决次要困难的突破(高级语言、分时、统一编程环境),以及解决根本困难的可能途径(Ada和其他高级编程语言、面向对象编程、人工智能、专家系统、“自动”编程、图形化编程、程序验证、环境和工具、工作站)——当然这些都被作者否定了。

最后,作者提出了自己所认为的一些可能解决根本困难的方法(参考如今的软件开发,作者30多年前的观点多么具有前瞻性啊!):

  • 1.购买和自行开发。

  • 2.需求精炼和快速原型。

  • 3.增量开发——增长,而非搭建系统。

  • 4.卓越的设计人员。

二、“人月神话”:

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

——出自原书第2章,这恐怕是全书最著名的论断。

“人月”是软件开发中,衡量生产率的一个指标(类似的还有“人天”、“人年”等,都是表示人员数量和开发时间)——也就是衡量软件开发规模的指标。

按照书中的观点:现实的项目开发过程中,由于人员之间需要沟通交流,所以,单纯的增加人员,并不一定能缩短整个项目的开发时间。

这是因为,新增加的人员,无论如何都要接受项目培训,原有的项目人员则要暂时放下手中的工作,为新人提供培训;同时,原有的项目分工需要重新分配,这些都属于额外的工作——如果没有新进人员,原有的工作结构和节奏就不会被破坏。所以,只有当新进人员的数量所最终提供的生产率,大于他们对原有项目结构和节奏所破坏的生产率的情况下,才能够缩短整个项目的开发时间——这从逻辑上是非常容易理解的,更何况作者还有图例说明。

因此,越是接近项目后期,增加人手对原有项目的“破坏性”就越大——现实偏偏是越到后期,才发现项目滞后,于是本能地增加人手。可见,如果一定要增加人员,选择在项目开发早期是最明智的做法。

··················································

本章也留下了两个问题:

  • 1.既然按照作者的意思,“人月”作为衡量软件生产率的指标,有其不合理之处(通常情况下,人员和时间并不能完全置换,典型的情况就是Brooks法则),那么,更好的指标是什么呢?如果我们理解作者所说的是针对“进度落后的项目”这种极端情况,那么一般情况下,如今所采用的“人月”指标,就仍然是合理的吧?

  • 2.作者在第19章对一次性构建项目的“瀑布开发模型”表示了反对,而是支持渐进式精化的“增量开发模型”,这就涉及本章作者自己的软件开发进度经验法则:1/3计划,1/6编码,1/4构件测试和早期系统测试,1/4系统测试。为了这种测试仍然能在“增量开发模型”中适用,是不是可以理解为,在增量开发的每一个阶段,都可以继续应用这种经验法则呢?

三、“类比”——简单有效的研究方法:

“类比”——虽然看起来很普通,但这是全书给我最大的启发,因为这是一种适用于很多领域的研究方法,包括如今仿生学中的飞行器设计、电子商务中的购物车概念等。以下是这本书中有关“类比”的几个例子:

  • 1.“外科手术式的团队”——整个开发团队由首席程序员负责,其他人辅助其工作——这是对外科手术的类比:护士、麻醉师等都是辅助,主刀医生只有一位(如果不止一位,该多么可怕)。

  • 2.“图形化界面”——窗口、图标、菜单、指针选取的软件操作界面,这是对桌面工作的类比(当然,也做了必要的优化和调整)。

  • 3.“增量式开发”——先完成一个主体,然后逐步添加功能,这是对生长的类比(自然界的生物都是逐步生长和进化的,不会因为养分的增多就会加速生长)。

书中这些有关软件开发的重大变革,如今并不鲜见,但它们的出现都是从“类比”而来。研究者正是发现了某些潜在的联系和规律,将其应用到自己的领域,从而形成了变革。以上这些变革是重要的,但是造成这些变革的思想更重要的。一旦运用自如,“类比”就是一种简单有效的研究方法。

四、摘录一些观点和方法:

书中还有一些令人印象深刻的观点和方法,我翻着书摘录了一些,作为笔记和参考:

  • 1.从程序变成产品,成本至少上升9倍,因为其中包括了大量的测试、文档、接口等。

  • 2.概念完整性是产品质量的核心。保证产品/项目的概念完整性至关重要,人数越少,越容易保证设计概念的完整性。产品概念的完整性可以使开发、使用变得容易,而且更不易产生bug。所以,产品的概念由一个人来控制,其他人提供向其各种工作支援的团队——“外科手术式”的团队是高效的。

  • 3.功能与理解上复杂程度的比值才是系统设计的最终测试标准,但是功能本身或简洁都无法成为一个好的评判标准。

  • 4.易用性需要设计的一致性和概念的完整性。

  • 5.不能与系统基本概念整合的良好想法和特色,最好放到一边。否则,就抛弃原来的设计。

  • 6.警惕过分地设计“第二个系统”,因为第一个系统的成功容易使设计师的信心膨胀,但先前的经验还不足以帮助其判断和验证。

  • 7.设计师和开发人员要尽早交流并持续保持沟通,实现是开发人员体现创造性的责任,设计师不应该越俎代庖。设计师负责面向用户的设计,而开发人员负责具体的实现。

  • 8.文档是必要的,规格说明的风格必须清晰、完整、准确,这会使说明手册读起来枯燥无味,但精确比生动更加重要。

  • 9.编制文档或手册时,采用形式化定义(精确)和叙述性定义(可以解释原因)相结合的方式,但两种定义必须分主次:一种作为标准,另一种作为辅助描述。

  • 10.项目经理需要成立一个独立的产品测试机构/小组。

  • 11.树状结构几乎不能用来描述交流沟通,因为交流是通过网状结构进行的。

  • 12.团队的搭建必须根据参与的人员来组织,而不是将人员纯粹地按照理论进行安排。

  • 13.开发人员必须设置规模的目标,控制规模,考虑减小规模的方法。

  • 14.设计人员必须决定用户可选项目的粗细程度。

  • 15.文档的跟踪维护是项目监督和预警的机制。文档本身可以作为检查列表、状态控制,也可以作为汇报的数据基础。

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

  • 17.项目经理的任务是制定计划,并实现计划。

  • 18.为舍弃而计划,必须构建一个用来抛弃的系统。

  • 19.版本控制、阶段(量子)化、定期变更:每个产品都应该有数字版本号,每个版本都应该有自己的日程表和冻结日期,在此之后的变更属于下一个版本的范畴。

  • 20.所有修改都倾向于破坏系统的架构,增加了系统的混乱程度(熵)。用在修复原有设计上瑕疵的工作量越来越少,而早期维护活动本身所引起的漏洞的修复工作越来越多。随之时间的推移,系统变得越来越无序,修复工作迟早会失去根基。

  • 21.系统软件开发是减少混乱度(减少熵)的过程,所以它本身是处于亚稳态的。软件维护是提高混乱度(增加熵)的过程,即使是最熟练的软件维护工作,也只是放缓了系统退化到亚稳态的进程。

  • 22.个性化的工具妨碍而不是促进沟通。项目经理应该制定一套策略,并为通用工具的开发分配资源。与此同时,他还必须意识到对专业工具的需求,对这类工具的开发不能吝啬人力和物力。

  • 23.计算资源匮乏时,把机器时间分割成不同的块,然后给不同的小组使用,是一种很好的方法。

  • 24.受控、使发布的进展变得正式:为每个编程人员分配一个空间来供其存放程序拷贝、测试用例等,每个人员可以自由处置自己的空间,但是当他向集成经理提交程序拷贝到系统集成子库后,没有集成经理的批准,原作者无法再修改代码。

  • 25.使用级别较高的表达方法来表现概念和隐藏细节,直到有必要进行进一步的细化。

  • 26.一些糟糕的系统往往就是试图挽救一个基础很差的设计,而对它添加了各种表面装饰般的补丁。

  • 27.关键的地方和构建无bug程序的核心,是把系统的结构作为控制结构来考虑,而不是独立的分支语句。

  • 28.对变更和差异进行记载。

  • 29.系统测试过程中,一次添加一个构件。

  • 30.有时必须回退,推翻顶层设计,重新开始。

  • 31.项目进度表中的里程碑必须是具体的、特定的、可度量的事件,能够清晰定义。

  • 32.项目进行中,必须关心每一天的滞后,它们是大灾祸(整个项目落后)的基本组成元素。

  • 33.自文档化代替软件流程图:通过向源程序中必须存在的语句附加“文档”信息;调整源程序的格式表现从属和嵌套关系;利用注释向源程序插入必要的记叙性文字。

  • 34.采用“快速原型+增量式开发”的软件开发方法。

  • 35.项目经理面临的中心问题是如何设计架构和流程,来提高而不是压制主动性和创造力。

  • 36.彻底提高软件健壮性和生产率的唯一途径,是提升一个级别,使用模块或者对象组合来进行程序的开发。

  • 37.不要盲目添加产品的功能。功能建议的吸引力在初期阶段是很明显的,性能代价在系统测试时才会出现。而随之功能一点一点地增加,手册慢慢地变厚,易用性损失以不易察觉的方式蔓延。

  • 38.定义用户群:他们是谁?他们需要什么?他们认为自己需要什么?他们想要的是什么?必要时,可以用合理的猜测(假设)来代替成本高昂的调查。

  • 39.将体现结构和设计实现、物理实现相分离:在大型系统开发中,由一位主结构师把系统分解成子系统,系统边界应该划分在使子系统间接口最小化(接口越少、越简单,bug就越少)和最容易严格定义的地方。

  • 40.把任何东西变成代码之前,可能要往复迭代两个或更多的体系结构-设计-实现循环。