V
VRGL
Unregistered / Unconfirmed
GUEST, unregistred user!
软件开发新思维
--介绍Cockburn的新书 Agile Software Development
胡健
小引
软件开发是什么
人啊,人
团队的力量
法无定法
多余的话
小引
Alistair Cockburn 是一位国际知名的软件开发专家。他在1991年受IBM之邀对一个OO项目设计一套方法。作了一番文献查阅之后,感到非常不满意。失望之余,决定下问项目开发组,请教他们认为什么是最好的工作方式。结果就这样讨论出了可行的方法过程。这给了Cockburn极大的启发,他并且还注意到程序员们所用的语汇和文献上的大不一样。这真是“柳暗花明又一村”。他从此一发不可收拾,积极造访其他项目,考察这些项目是怎样运作的。在与项目组成员的交谈讨论中,他特别注意他们所用的语汇,并加以吸收。
通过这些采访和自己的二十几年的开发和管理经验,Cockburn发展出了一套软件开发的思想,包括什么是软件开发,软件开发人中人的特点,开发团队应如何组织,怎样选择开发过程等。他最近的新书 Agile Software Development 全面系统地阐述了他的思想,建立了他的一套独特的话语系统(大部分语汇是多年来在项目造访中积累起来的)。其实,在书的草稿中(draft version 2b1),Cockburn曾说过写作这本书的原因之一就是他认为他目前的语汇已经能与绝大多数的项目开发人员的语汇基本一致了,可以把它们整理出来了。
此书大致可分为四个部分:软件开发的性质,作为开发主体的个人,相互合作的团队以及方法过程。
软件开发是什么
讨论软件开发,首先得对软件开发有个定义或定性(即什么性质的问题)。软件开发是什么呢,有几种有代表性的说法:
数学观,以CAR Hoare 为代表[1];
工程观,以Bertrand Meyer 为代表[2];
艺术/工艺观,许多程序员如是说[3];
作者认为这些说法都对,同时又都不对。狭义地说,编程本身是一种个体的、富灵感的、逻辑性强的活动,但现代的软件开发更是一种群体的工程活动。
为了进一步揭示软件开发的特点,作者(有些出人意外地)把目光投向了游戏。作者对游戏的种类进行了分析,并详细比较了攀岩与软件开发共有的特点,如:合作与目标寻求、团队、技能、训练、工具、资源有限、计划、修正、乐趣等等,最后把软件开发定性为:一种创造与交流的合作游戏(a cooperative game of invention and communication)。游戏的首要目标是交付正确工作的系统,次要目标是生成一些“沉淀”(residue)产品为下一次的游戏进行积累。
游戏的参与者有项目出资人、管理人员、应用域专家、软件设计开发人员、测试人员与文档写作人员。他们需要互相帮助合作以达到目标。其中,开发人员扮演着重要的角色,他们要完成的主要动作是:
理解问题空间,并设想出技术上可行的方案来解决问题;
把头脑中的“内部”过程用可执行的计算机语言表达出来;
留下必要的工作标记(marker)以支持首要目标(项目组内的交流)和次要目标(传递这次开发的设计思想),这里“必要”的标准是刚好满足要求就行(sufficient-to-purpose)。
简言之,这场游戏中所见的只是人的创造性思想以及这些思想在人和人、人和计算机之间的交流。
人啊,人
如此说来,人的因素应当是软件开发中最为重要的了。作者在广泛的项目采访中也发现,一个项目的成功与否,人的因素起着决定性的作用。一个成功的团队几乎总是能做出需要的系统,这与技术和软件开发过程没什么必然的联系。但软件开发中对人的研究却出奇地少。根据作者调查,第一本这方面的专著是 Weinberg 在1969年写作(正是软件工程的观点兴起之时 [4])、1971年出版的 The Psychology of Computer Programming (此书的“银版”-- Silver anniversary edition 于1998年出版)。在沉寂了15年之后,DeMarco 和 Lister 写了 Peopleware: Productive Projects and Teams。有趣的是,又是15年过去了,作者的这本 Agile Software Development 可能是这个领域的第三个“里程碑”了。
作者在1994年就明确地提出了人是“非线性”的观点。这种非线性表现在,给一个人双倍的输入(如双倍的时间,或双倍的报酬诱惑),你不能期待着他就能做到双倍的输出(双倍的思考质量,或双倍的代码行)。在这本书中,作者更进一步地讨论了人的特点,特别是这些特点在软件开发中的作用。
首先,人是不可预料的。作者用了一个有趣的摩登单词 funky(这里有“奇异”,“复杂”,“不可思议”之意)来描述个人。人的 funkiness 表现在
自发冲动(spontaneous):可能会突然心血来潮去干一件事;
自相矛盾(contradictory):如时而口若悬河,时而缄口不语;
变化无常:人的个性可能会随时间(每小时、每天、每年)或/和环境(房间、温度、同事)而变化。
人也是非常多样化的[5]。有人善抽象思维、有人喜具体细节,有人夸夸其谈、有人沉默寡言,有的领导专行独断、有的上司民主亲善,等等。人的多样性也可以解释为什么文献里记载的软件开发方法过程如此之多,这是因为每一种方法都可以找到自己的一群支持者。
人的哪些弱点会导致一个项目的失败呢?作者归纳了五条:
犯错误。人要犯错误是很常见的,不足为奇。特别是在软件开发中,能第一次就把事情完全做对 的情况不多。克服这种弱点的办法一般是“往复式”(iterative)或“递增式”(incremental) 开发过程[6]。
倾向保守,墨守成规,缺乏冒险精神。最明显的例子是一般的项目经理宁愿使用已成常规的 瀑布式开发过程(尽管实践证明这种方法有很大的缺陷),也不愿使用新一些的递增式开发方法。
只想创新,不愿调查研究并使用已有的解决方案或软件组件。程序员中只想创新的冲动特别明显, 这大概是由于从小在学校接受的教育是要创新的缘故。一种纠正的办法是鼓励复用。
习惯难改、行为又不能保持一致。一个常见的例子是,对某些人来说(比如本人),要使自己的工作台 一贯地保持整洁,是多么痛苦的一件事情。同样,在软件开发中,要求改变工作习惯并保持下去,也就可想而知了。
不愿受纪律约束[7]。这是上一个弱点的直接后果。那么, 在软件开发中,如何来克服这个弱点呢?作者认为 有两种相反的途径:一是用高度纪律性的过程,二是用宽容性的过程。著名的XP是前者的代表,而作者的 水晶系列方法则是后者的思路。
那么,人有哪些特点会使一个项目成功呢?作者归纳如下:
善于寻找(good at looking around)。这是指当一个人在一定的范围内能根据自己的智能和经验 迅速地发现要找的东西,或注意到一些不寻常的东西。在软件开发中对人的这个特点的一个应用便是设置 设计文档合适的详细度,一般来说设计文档可以粗一些,能通过它很快地找到相应的源码部分就行了。
学习能力。人们在项目的开发中可以逐步学到新技术、应用域知识、开发过程以及如何与同事合作。一个项目 完成时,新手可能就变成老手了。
可塑性。人们在接受了新思想之后能够极大地改变自己的行为。例如,C3项目在Kent Beck 接手以后, 大力推行化繁为简的设计/编码原则,同样一班人马在接受了 新的观念之后,取得令人惊叹的效果。
工作自豪(或成就)感。人总是希望在工作中显示能力,取得成绩,获得一种自豪感 (pride-in-work)。这种动力也体现在本职工作之外,如利用自己的长处帮助他人或团队 (pride-in-contribution),或发现问题主动报告或解决。
作者列出了相当一些良好的工作方式,它们虽然是对个人而言,但要有效地实施却有赖于个人和管理层的共同努力。偏重个人的方式有:
从具体着手。人在开始工作,或学习新东西时,一般喜欢从一个具体 的实例入手,通过自己琢磨,或与别人讨论,来理解“这一个”,进而理解“这一类”。 所谓“举一反三,触类旁通”是也[8]。
使用实物。在项目的某些阶段,如需求分析时,可以用一些实物来帮助人们更好了解系统。 这些东西要看得见、摸得着、随手能移、信手便改,一般来说低技术的东西效果更好, 如纸张、卡片、纸盒等等。 CRC(Class-Responsibility-Collaborator)卡便是这样一种技术。
依葫芦画瓢。“拷贝和修改”(copying and altering)是人们在工作中常用的方法,如写 一份计划时,通常是找到一份类似的计划,然后改动一番。同样在软件开发中,碰到一个问题时, 常用的方法是找到解决类似 问题的程序,再加以修改[9]。
而以下这些方式则需要个人与管理层的共同努力:
回报激励。编程很大程度上是一种“本能激励”(intrinsic motivated)的活动,因此,要有效地 激励程序员,除了物质上的奖励之外,主要是要让他们从工作中获得自豪感和成就感。其实,在递增式开发 过程中,经常的(哪怕是微小的)成就可以让程序员感到他们的工作得到了回报 (pride-in-accomplishment)。
频繁反馈。频繁的反馈既有利于个人和团队的学习,也有利于系统开发。一个开发过程中应该有频繁的反馈 机制,如用户使用反馈,系统测试反馈,开发过程检讨等等。
默想与交流。程序员在考虑一个问题的解决方案时,需要一个安静的环境,以进入一种所谓“流” (flow)的创造状态[10]。但软件开发又是一种需频繁交流的活动, 需要一个较紧密的环境, 因此需要处理好这两者之间的关系。作者建议在设置工作环境时(如坐位安排)应加以考虑。
工作与个性相匹配。在一个项目中,分配工作时最好能使工作的性质与个人的个性相匹配,这样 能使个人的强项得以最大程度的发挥。
充分发挥优秀人才的作用。一个优秀的程序员对项目的成功有着非常大的(甚至是决定性的)影响。 通常,高手出马,一个顶俩(或更多)。
团队的力量
现代的软件开发,几乎不太可能一个人包打天下。软件开发活动是一种群体活动。要使这个群体有效地运转,作者认为最重要的莫过于成员之间的相互交流与合作了。
信息对流
信息对流(convection currents of information)是作者的一个语汇,它用热气流动来比拟信息的流动。一个人的存在、他的姿势、他的声音、他的脚步,都是在向周围环境放射着信息,为别人所接收。同时,他也接收着别人放射出来的信息,从而形成了信息的对流。
作者详细分析了一个最常见的问题与解答过程,假设A知道一些信息,而B正需要这些信息。那么要考虑:
B要用多久才能发现A有所需的信息,
完成信息从A到B的传送的所消耗的能量是多少。
作者从两人的工作地点来对这两个问题进行了分析:
坐在同一台机器前(如作pair-programming)
坐位相邻
同一间屋子
办公室相邻
同一幢楼但不同楼层
不同的城市或国家
答案是不言而喻的。
作者还提出了“渗透交流”(osmotic communication)的概念。这是指在一个公用的的办公室里,你在专注于自己工作的同时,会不由自主地听到一些背景声音,如别人正在讨论某个问题,并能从中不自觉地提出一些感兴趣的信息。这可以使发现信息和传递信息的成本得以下降。
基于以上的观察,作者认为一个项目组最好能够都在一个(大)办公室之内,这样能最大限度地提高信息交流的效率。更进一步地,如果项目组有不同专业的人员,如程序员和应用域专家,他们的坐位应该混合安排,即避免分组安排时容易出现的小圈子效应。另外一点要注意的是,如果一个大房间里有两个或以上的项目组,那么它们之间则应最大程度的加以隔离,减少干扰流(draft)。
布置办公室时要考虑的一个重要事情是放置“信息发射源”(information radiator)。这里,一个信息发射源一般是指挂(贴)在墙上的大尺寸的图表,这样人们过上过下时都能看见。一个好的信息发射源应该具备两个特点:内容随时更新,看上去一目了然。这种信息发射源最常见的内容有:总体项目进度、开发工作完成情况、系统测试情况、系统运行状态等等。
跃过交流的沟堑
为了提高交流的效率,作者还以两人在一个白板前的讨论为例,详细分析并列出了11项交流的要素(modalities in communication)。它们是:物理上的近距离性(physical proximity);三维性(three-dimensionality);气味(smell);动觉(kinesthetics);肢体接触[11](touch),如拍拍肩膀;声音(sound);视觉(viusal);要素同步(cross-modality timing);低负载(low latency),因此可以有实时问答;信任与学习(trust and learning);共用持久性的信息发射器(use a shared,persistent information radiator),如白板。作者认为具备了所有这些要素的交流是最有效的。
如果去掉其中的一个或多个要素,会给交流带来怎样的影响呢?
只去掉物理上的近距离性:交流可通过电视会议来进行,这基本上保持了其他的要素。
再去掉视觉:则可用电话方式,但它已失去了大部分要素了。
再去掉声音:则可email方式,与电话相比,则失去了实时性。
去掉提问的可能性:那么这时信息只是单向流动了,如看录象、读书等。
作者又考虑对一个已存在的交流方式来说,可以通过增加它的要素来提高交流的有效性。例如,作者坦言,他对“Design Patterns”[12] 中的某些模式(pattern)还是不甚了了(并推测很多读者想必也是如此),因此建议此书可配上录象带,由pattern的作者来讲解一番,这样肯定会帮助读者理解。
提高交流的有效性还有一个重要的问题就是很多时候需要把讨论中信息记录下来,如记录在纸张上,或在白板上。作者称之为给信息加上“粘滞性”(stickiness)。这些记录下来的信息可以保存起来,供以后需要时查看。作者还提到了一些具体的方法。例如,把大张的白纸贴满墙上,大家可以随时随地在上面写写画画。一张纸画满了,就把它卷起来,标上日期,然后存放起来。
集体主义放光芒[13]
一个项目组的成员可能来自五湖四海(特别是大项目),为了一个共同的目标[14],走到一起来了。如何高效得去达到这个目标呢?很重要的一点是,大家要心(尽量)往一处想,劲(尽量)往一处使。如何做到这一点呢?作者认为可以通过如下方法让每个成员作一些小的、容易做到的改变:
告诉每个人现在项目的主攻方向是什么;
现在选择这个主攻方向的理由是什么;
告诉每个人他现在的行动对项目有什么作用。
这样,每个人可能只是把他的方向往目前项目的方向上调整了一点点,但产生的合力是很大的,能取得了事半功倍的效果。
要提高集体(团队)的战斗力(工作力),还有一个重要的方面,那就是在项目组中建立起良好的人文环境。使大家心情舒畅,愿意互相合作,互相帮助。作者从友好与冲突,团队意识和团队文化等方面讨论了这个问题。
友好与冲突(amicability and conflict)。友好是信任与合作的基础。作者把友好定义为 “愿意倾听别人的想法,说话无恶意”,并且认为可以从一个团队内部的友好程度(amicability level),看出同事间交流时的信息开放或封闭程度。友好(与人为善)能造成一种气氛,使大家畅所欲言,特别是不同的意见。这里作者把交流不同意见称之为冲突,并且认为这样的冲突是必须的,没有冲突或冲突不足对工作是不利的。
建立团队意识(team building)。现代企业一般都很重视团队意识或协作精神的培养。有些公司在开始一个项目时把所有成员拉到一个地方去活动一两天,以使大家增进了解,在工作中能很好地合作。这种做法在实践中也很有效。但有些程序员却不太以为然,说道:“我对我们是不是能一起烧烤或一起爬墙不感兴趣,我只对我们是否能一起做出软件感兴趣”[15]。那么,什么是更有效的方式呢?作者引用了一些相关文献的建议,认为最好的活动是能让大家一起做出一些只有在一起才能干出的活。
团队文化(team culture)。一个项目组往往具有自己独有的团队文化。它会受到所在的企业或组织的文化的影响,也会受到国家民族的文化的影响。团队文化有各种表现形式,作者引用文献着重讨论了项目组的四种组织结构:
等级结构(hierarchical):这是传统的结构,多见于老牌大公司。
随机结构(random):为等级结构的反面(无政府主义倾向严重),多见于新成立的小公司。
协作结构(collaborative):成员们通过交流与君子协定来推动工作进行。
同步结构(synchronous):为协作结构的反面,即用不着言语交流。成员们各司其职,配合默契。
团队文化还有一个重要方面便是职业亚文化(professional subculture),也就是每一个职业特点形成不同工作方式与习惯,作者列举如下:
项目经理需要有条不紊的工作作风,需要能预测任务的完成日期以及成本等。
OO程序员需要抽象思维能力,在思考问题时需要安静,不喜欢被打扰。
需求分析员需要对系统功能与接口做细致的逐条梳理。
市场营销人员需要杰出的想象力和人际交往能力。
对待这些亚文化的差异,作者提出可从三个方面入手:
对业界来说,鼓励对软件开发团组的社会人类学研究。
对技术多面手来说(如同时善长于编程、数据库、设计、项目管理和教学者), 他们可以成为不同角色间的“翻译者”
对每个人来说,应该了解其他的亚文化价值系统,并在实践中表现出耐心和理解 [16]。
法无定法[17]
Methodology这个词一般译作“方法学”或“方法论”,即“study of methods”。而作者使用这个词是用的Merriam-Webster字典中的定义:“a series of related methods or techniques。” 即“一组相关的方法或技术”。而 method的定义是“systematic procedure”,类似“technique”。作者也提到一位同行在1993年告诉他的一句话:“methodology is a social construction。”过了两年,他才开始理解这句话的含义,并给出自己的定义为:“A methodology is the conventions that your group agrees to。” 即你的团组同意遵循的一组习惯做法。这实际是个“social construction”(社会建设),社会性的一个重要的方面便是协调团组成员之间的活动,促进交流与合作。下面将试着把methodology译为“一套方法”。
要素
作者认为,一套方法需考虑的(客体)结构要素有:
角色(roles)。每个团组成员的工作要求、他的技能以及他的个性特点。
个性(personality)。人员的个性特点(似乎为角色的一部分)。
技能(skills)。角色需要的技能,如在一个项目中,程序员需要具备或学习OO、Java和单一测试。
团队(teams)。一个项目可能只有一个组,如开发组,或多个组,如开发组、分析组和测试组。
技术(techniques)。完成一项任务所需的知识和过程,如编写使用情形(use case), 项目回顾(project retrospective)。
活动(activities)。团组成员的日常工作,如计划、编程、测试、开会。
过程(process)。活动如何随时间展开,每项活动的的前提与后置条件。一般来说,这是一个工作流程。
工作产品(work products)。工作产品可以是临时性的如CRC卡,或永久性的如源码和设计文档。
阶段进展(milestones)。在某一时刻一个阶段任务的完成情况,如源码是否交付、文档是否完成。
标准(standards)。如编码标准(coding standard)、画图标准等。
质量(quality)。质量可以是对活动而言,也可是对工作产品而言。
团队价值取向(team values)。价值取向将极大地影响团队的工作模式,如想着“尽快面市” 的团队就和看重家庭的团队的工作模式不同(加班加点和下班准时回家)[18]。
工具(tools)。项目组使用的工具。
对于一套方法本身(主体),作者提出了如下这些概念要素:
方法大小(methodology size):所控制的要素的数量,要素如系统发布(deliverable)、标准、活动等。
正规性(ceremony):方法的精确度与控制的松紧度。如对一项使用情形(use case)作检讨回顾,正规性低的方法 允许利用午饭时间边吃边做,而高正规性的方法则可能要求花两三天来做。
方法重量(methodology weight):这是方法大小与正规度的乘积,这只是一个概念性的,并非一个精确数字。
问题大小(problem size):问题中的元素与它们的交叉复杂性。他很大程度上取决于估测者的知识与看问题的角度。
项目大小(project size):项目组人员数量。但需注意,这个测度与“问题大小”是不同的,不可混淆。
系统要紧性(system criticality):系统出错时会造成的影响,如饮料机(本来要咖啡,结果出来可乐) 和飞机(可能机毁人亡)的系统要紧性显然不同。
精确性(precision):表述一个问题时精确到什么程度,如到类图(class diagram)还是到源码。
准确性(accuracy):表述一个问题时的正确程度,如GUI,后期的描述一般要比初期的准确。
相关性(relevance):对某一个问题是否加以考虑,如讨论GUI时可以不考虑domain model。
宽容性(tolerance):当实际与制定的规章偏移时,能容许多大的偏移。
可视性(visibility):“外人”是否能容易地看出项目组是不是在遵循所规定的方法,如IS9001便很强调可视性。
比例尺(scale):描述一样东西时允许多少组成元素同时出现。如UML中的package使我们能用不同的比例尺来看待使用情形(use case)和类(class)。
稳定性(stability):改变的可能性。如项目初期的变化最大(两眼茫然),中期变化较小(大势已定), 后期相对稳定(小修小补)。
设计原则
把这些结构与概念要素综合起来,可以为设计一套方法提供一个系统的思路。从这些要素和对个人和团队的分析出发,作者根据自己的经验,提出了七大设计原则:
1.面对面的交流是费用最低、速度最快的信息交换方式。
如果可能,项目组成员应该坐在一起,这样交流起来方便,使开发工作能有效进行。这句话反过来说,如果项目组很大,则这种面对面交流变得困难,交流费用上升,交流质量下降,从而会增加软件开发的困难。所以如果生产率和资金是关键因素的话,那么应该尽可能使用人数少(因此能坐在一起)的团队。
2.方法超重时代价昂贵。
前面提到“方法重量”是方法控制的结构要素与正规性的乘积。所以,当控制要素数量增加(典型的如分析、规划、设计、图表等文档这样的工作产品),正规性提高时(典型的如频繁的开会、报告),那么开发进程将受到很大影响。但是如果重量太轻,也许生产率一时上去了,但质量却下来了,结果要花更多的时间来排错。所以,对这个“度”的设置需要小心。
3.大的团队需要重一些的方法。
团队大起来以后,特别是坐位一分散,成员之间的直接交流便减少,如果没有一套有效的协调与交流的方式,工作易于陷入混乱,影响开发效率与质量。但如果过重,就会导致原则2所说的后果。所以还是有一个“轻重”度权衡的问题。
4.系统越要紧/重要,正规性应越高。
如上所述,正规性提高将导致费用上升。但另一方面,正规性提高的确有助于少犯错误。而这一点对重要性很高的系统是必须的(如航天飞机和核电厂项目),所以费用比一般系统要高也是在情理之中,可以接受的了。
5.增加反馈与交流可以减少中间产品。
这里的“中间产品”是指在一个组内部使用的工作产品,作者把它们称之为“允诺性便签”(promissory notes),主要是指那些描述计划中的(所以允诺要完成的)的活动的文字材料,如分析、设计、测试计划等。作者认为有两种方式可以减少中间产品。一是尽快拿出工作系统(尽管只有部分功能)。这样能极大地促进用户、系统分析人员、设计师和测试人员之间的交流与反馈,使得有些中间产品成为没有必要了。二是减少项目组人员,使得大家能坐在一起,面对面交流,有些中间文字东西也没必要再写了。
6.纪律、技能、理解与过程、形式、文档的对立。
这个原则来源于Jim Highsmith的三句话[19]。纪律(discipline)是指一个人(主动)选择要求的工作方式,而过程(process)是指人(被动)听命而行;技能(skill)含有创造性的能力之意,而形式化或手续化(formality)则是要求按步就班;理解(understanding)是指知识,包括那些隐藏的知识,如在项目中谁知道什么、那些讨论成为设计的一部分等,而文档(documentation)则只是理解(知识)的一部分。探索性的活动需要强调纪律、技能和理解,而软件开发很大程度上正是一种探索性的活动。
7.从非瓶颈活动中求效率。
每个项目一般都有一个瓶颈所在。如果项目进度因为瓶颈受阻,那么提高项目的总体效率的通常做法是调更多的精兵强将人员去支援瓶颈处的工作。其实还有一种做法,便是对非瓶颈处(特别是瓶颈的“上游”)的人员的工作进行调整,让他们在把结果提交给瓶颈之前多花些时间把他们的工作尽可能的稳定下来,从而减少瓶颈处的“重做”(rework)负荷(软件开发中总是有“重做”)。这是一个以效率换稳定的策略。
在设计方法时,应充分考虑这些要素与原则。一个重要的推论是“不同的项目应该有不同的一套方法”,作者提供了一个思路, 用一个三维坐标系统来表示不同的方法。项目组人数作为x坐标,系统要紧性作为y坐标,系统优先因素作为z坐标。x坐标取值为1-6人,20人,40人,100人,200人和500人;y坐标取值C(loss of comfort), D(loss of Discretionary money),E(loss of Essential money)和L(loss of Life)。这样xy不同的组合就形成了不同的坐标格,表示一个项目的基本特征。例如,“C6”表示一个项目有6人,系统出错时会引起一些不方便。而“D20”则表示一个有20人的项目,如果系统出错会导致损失一些金钱。对每一个xy坐标格,z实际上说明了项目的一些其他特征。作者用这个思路来设计了他的水晶方法系列(Crystal methodology family),“D6”类称之为 Crystal Clear,“D20”类为Crystal Yellow,“D40”类为Crystal Orange。在此框架下,XP可归入C4至E14。
对于项目的具体运作,作者还从实践经验中归纳出一些“甜蜜之处”(sweet spots)[20],并认为如果采用的一套方法靠近这些甜蜜之处,那么开发的效率可以提高。
二到八人坐在一起。
专家用户在场。
一月递增周期。
全自动回归测试(单元或/和功能测试)。
有经验的开发人员[21]。
构造与生长
一套方法应该是动态的、自适应的,也就是说,一套方法要在适应开发环境中构造和生长。作者把一个软件项目比拟为一个生态系统。系统中的各组成部分如人员个性、坐位、工作语言等都在相互作用、相互影响之中。当然,一个良好而稳定的系统的形成与发展主要取决于项目组成员的交互作用[22]。如果大家能理解个人、团队和方法的特征,那么他们就能更好地选择(或设计出)一个适合于自己这个项目的初始方法并不断地发展之,而推动发展的一个关键之处在于经常性的检查与调整。这是一个随时间而进行的过程,作者提出的具体步骤为:
现在。随时可做的(不一定要手上有项目),主要是增加对目前所在的公司的开发方法的了解。具体方式是(最好几个人)去找人一对一地谈话,收集如下信息:
项目名,受访者在项目中的角色;
项目数据(如起止日期,最多时的人数,应用领域,使用的技术);
项目历史;
做错的/不要再重复的;
做得好的/可保留的;
优先因素;
其他。
对这些信息进行分析,找出不同项目的共同之处。
项目开始时。要做的是设计出一个初始方法,这可以分两步进行:
由两人对目前的项目进行分析,提出草案。具体步骤为:在人数、系统要紧性、优先因素的三维坐标中 找到这个项目的位置;找出这个(待提出)方法的概念要素,如正规性、文档的范围与详细程度、递增周期长度等; 选择一个相近的现成方法,如XP、RUP等;
召开团组全体或代表会议(半天到一天),充分讨论候选方法,并加以修改、“定稿”,成为项目的初始方法。
第一个递增周期的中间。需要一个1-3小时的会议,讨论目前的方法是否工作,有无根本性的错误,能否在第一个周期结束时拿出一个哪怕是很小的、但是测试过的、可运行的工作系统。要达到此目的,必要时需对工作系统的功能作一些调整。
每个递增周期之后。应该有一个专题检讨会(relection workshop),短至2-4小时,长可2-3天。经过一个周期之后,可以全面地对所用的方法的各组成单元进行评价。要讨论的两个主要问题是“学到了什么”和“什么可以做的更好”,据此对方法进行一些修改,作为下个周期的方法。
(第二个以后的)每个递增周期的中点。可以召集一个会议或个别谈话。这个检讨的目的主要是尝试新的想法和做法。因为经过了两三个成功的周期之后,项目组成员们有足够的经验来作新的“冒险”[23],即使不成功,也有后路,不会影响大局。但作者认为如果周期为三周或更短,则这个中点检讨可以不做。
多余的话
我去年(2001)七月左右第一次读到这本书时的草稿(draft version 2b1)时,第一感觉就是耳目一新。对书中所列举的对个人和团体的分析都有一些似曾相识之感(相信干过几年软件开发的同行都会有同感),但从未这样集中、全面而详细地读过。读第一遍产生的“冲击波”消退后,我开始重读并作了一些笔记,以求更好地理解并掌握作者的主要思路,但在阅读中却觉得材料有些零乱和重复。这本书去年底正式出版以后,和version 2b1对照着又读了一遍,发现基本材料(我想有90%)没变,但次序和结构有些变化。很明显,作者在尽力把这些材料有机地组织起来并表述出来。
总的说来,我觉得这本书提供了一个新的角度来看待软件开发活动和新的思路来设计开发方法。书中提供的材料大部分来自作者丰富的实践经验,对软件开发实践有很高的参考价值,值得软件项目参与者,包括出资者、管理者与开发者反复研读。我认为美中不足的是,作者试图建立来统率这些材料的框架并非严谨完美,从结构上说,这本书给我的感觉更象是一本结构化的技术散文集,而非严格意义上的学术著作。不过,从另一方面说,这也许是一个优点,让读者能从这些丰富的材料中,根据自己的知识和经验来构造出自己的“理论”框架。
在这篇介绍文章中,我试图根据我的理解来勾勒出的作者的主要思路,使读者诸君对这本书有个大概的印象。文章基本依据书的顺序,为方便读者阅读原文,再简要说明如下:
“Introduction: Unknowable and Incommunicable”:引论,主要说明人要正确地认识事物和准确交流是件非常 困难的,甚至是不可能的。本文未作介绍。
“Chapter 1: A Cooperative Game of Invention and Communication”:在本文的“软件开发是什么”中介绍。
“Chapter 2: Individuals”:在本文的“人啊,人”中介绍。
“Chapter 3: Communicating, Cooperating Teams”:在本文的“团队的力量”中介绍。
“Chapter 4: Methodologies”:在本文的“法无定法”中的“要素”与“设计原则”中介绍。
“Chapter 5: Agile and Self-adapting”:在本文的“法无定法”中的“构造与生长”中介绍。
“Chapter 6: The Crystal Methodologies”:是作者对其水晶方法系列的简介。本文未作介绍。
这本书和Jim Highsmith的Agile Software Development Ecosystems 是计划中的“Agile Software Development Series”(系列丛书)的两本基础书。作者称这套丛书的核心思想是:
不同的项目需要不同的一套方法。
注重技能、交流和团队的项目要比注重过程的项目有效。
这套丛书可分为三大类:
个人技术,如作者的“Writing Effective Use Cases”。
群体技术,如作者的“Surviving Object-Oriented Projects”。
方法实例,如作者的“Crystal Clear”。
从这里可以看出,作者关于软件开发的思路是技能、交流与团队为纲,方法过程为目,“纲举目张”。
鸣谢
感谢agilechina.org的诸位同伙对写作本文的鼓励以及对初稿提出的意见和建议。
注释:
注释部分有些是正注,有些则为“胡批”,博看官一笑,不必当真。
1. Tony Hoare 是计算机科学的奠基者之一。1999年从牛津大学退休。此公老骥伏枥,志在一统。最近几年从事的研究之一便是计算机科学的统一理论。
2. Bertrand Meyer 是现代软件工程的先驱之一,他的著作 Object Oriented Software Construction 被视为OO技术的经典。“契约设计”(Design by Contract)是他对软件开发技术的重要贡献(Meyer的一篇关于“契约设计”的 介绍短文,参考译文见 http://members.tripod.com/jian_hu/meyer/contract.html)。 他最近有一篇文章 Software Engineering in the Academy(参考译文见 http://members.tripod.com/jian_hu/meyer/teaching.html), IEEE Computer 2001年5月 是谈院校的软件工程教学的,也可从中较全面地了解他对软件工程的看法。
3. 本人曾经有一位同事就是人们头脑中艺术家的典型形象:长发垂背、胡子拉碴、不修边幅,整天龟缩在一个阴暗的房间里,瞪着鬼火一样一闪一闪的屏幕。
4. 有趣的是,(19)60年代末70年代初,也是结构化程序开始盛行之时。1968年 Edsger W. Dijkstra 著名的“Go To Statement Considered Harmful”, Communications of the ACM, Vol. 11, No. 3, 1968,打响了对“GoTo党乱动派”的第一枪。
5. 俗语说:人上一百,形形色色。或曰:林子大了,什么鸟都有。其实,林子不大,鸟的种类也未必单一。
6. 作者书中的 iterative 的含义和现在常用的意思不太一样。书中给的定义是:a scheduling and staging strategy that allows rework of ieces of the system,所以,译成“反复”似乎恰当一些。而incremental在书中的定义为:a scheduling and staging strategy in which peices of the system are developed at different rates or times and integrated as they are developed,此处译为“递增”,但其义似乎更接近于 Martin Fowler 的 The New Methodology 中的 iterative。
7. 毛主席早就说过:加强纪律性,革命无不胜。
8. 书中作者引了 Lave 和 Wenger 的 Situated Learning中的一段:“The world carries its own structure, so that specificity always implies generality”。特殊性总是蕴涵着普遍性,这简直就是我们从中学到大学的政治课里面学的经典原理之一。
9. 广义上说,这是一个复用(reuse)问题。
10. 这似乎有些玄得象练气功或参禅了,但准确地说可能是进入了忘我而想物(程序)的境界。
11. 郑重声明:这里的“肢体接触”与议会全武行无关。
12. “四人帮”的“Design Patterns: Elements of Reusable Object-Oriented Software” 引发了这几年的经久不衰的pattern热潮,Grady Booch 更认为这是超越Object的三个迹象之一(另两个是多视角描述软件系统架构和Aspect-Orientd Programming)。“四人帮”之名也许来自中国文革的王张江姚四人帮。有趣地是,pattern “四人帮”希望 他们和正宗“四人帮”推动文化大革命一样,能带来一个“设计(小)革命”,当然不愿象正宗“四人帮”那样因为他们的“反革命”思想而末日来临。而更为有趣的是,中国曾在1980年底审判文革“四人帮”,而计算机领域在1999年也有一次“审判pattern四人帮”,控告他们“对计算机科学犯下的罪行”,详见 http://www.c2.com/cgi/wiki?ShowTrialOfTheGangOfFour。
13. 书上的小标题是“Teams as Communities”。这里“team”应是指项目组,偏重于“物理”上的一堆人,而“community”更有“精神”上的同信(心)协力之意。这层意思也许老词“集体”,或新词“团队” 都可以表达出来吧。
14. 目标是系统开发。这个目标可能不是革命的,但一般来说不会是反革命的。
15. 这句话本人深表赞同,尽管有些“狗坐箢篼--不受抬举”之嫌。
16. 老山战士当年喊出的“理解万岁”应该是放之四海而皆准的。
17. 四川新都宝光寺有联曰:“世外人法无定法然后知非法法也,天下事了犹未了何妨以不了了之。”对我等靠敲键盘养家糊口的俗人来说,却是“做开发虽然法无定法却需有法法也,建系统总是了犹未了还得慎了了之”。
18. 曾在网上看见过一首顺口溜:一等男人外面有个家,二等男人外面有朵花,三等男人舞厅随便抓,四等男人下班就回家。
19. Jim Highsmith says:“Don't confusedo
cumentation with understanding;
Process is not discipline;
Don't confuse formality with skill。”
20. 当然,这里的“sweet spots”与圣经中的“流着奶与蜜”的地方无关。
21. 对XP的批评之一便是说XP是“hire the best, fire the rest”。
22. 金观涛在1980年代在“整体的哲学”一书中提出的组织的产生与生长的理论也许可以借鉴,即一个组织能稳定存在是因为它的子系统之间的功能是耦合的,而组织的生长是组织从一个稳态相另一个稳态的演进。
23. 邓小平的教导:“胆子再大一点,步子再快一点”此时可用。
--------------------------------------------------------------------------------
修改记录
2002年3月:完成全文,并作部分小修改。
2002年2月:前半部分发表于agilechina.org。
胡健
Email: jian4_hu2@hotmail.com
Web: http://members.tripod.com/jian_hu
--介绍Cockburn的新书 Agile Software Development
胡健
小引
软件开发是什么
人啊,人
团队的力量
法无定法
多余的话
小引
Alistair Cockburn 是一位国际知名的软件开发专家。他在1991年受IBM之邀对一个OO项目设计一套方法。作了一番文献查阅之后,感到非常不满意。失望之余,决定下问项目开发组,请教他们认为什么是最好的工作方式。结果就这样讨论出了可行的方法过程。这给了Cockburn极大的启发,他并且还注意到程序员们所用的语汇和文献上的大不一样。这真是“柳暗花明又一村”。他从此一发不可收拾,积极造访其他项目,考察这些项目是怎样运作的。在与项目组成员的交谈讨论中,他特别注意他们所用的语汇,并加以吸收。
通过这些采访和自己的二十几年的开发和管理经验,Cockburn发展出了一套软件开发的思想,包括什么是软件开发,软件开发人中人的特点,开发团队应如何组织,怎样选择开发过程等。他最近的新书 Agile Software Development 全面系统地阐述了他的思想,建立了他的一套独特的话语系统(大部分语汇是多年来在项目造访中积累起来的)。其实,在书的草稿中(draft version 2b1),Cockburn曾说过写作这本书的原因之一就是他认为他目前的语汇已经能与绝大多数的项目开发人员的语汇基本一致了,可以把它们整理出来了。
此书大致可分为四个部分:软件开发的性质,作为开发主体的个人,相互合作的团队以及方法过程。
软件开发是什么
讨论软件开发,首先得对软件开发有个定义或定性(即什么性质的问题)。软件开发是什么呢,有几种有代表性的说法:
数学观,以CAR Hoare 为代表[1];
工程观,以Bertrand Meyer 为代表[2];
艺术/工艺观,许多程序员如是说[3];
作者认为这些说法都对,同时又都不对。狭义地说,编程本身是一种个体的、富灵感的、逻辑性强的活动,但现代的软件开发更是一种群体的工程活动。
为了进一步揭示软件开发的特点,作者(有些出人意外地)把目光投向了游戏。作者对游戏的种类进行了分析,并详细比较了攀岩与软件开发共有的特点,如:合作与目标寻求、团队、技能、训练、工具、资源有限、计划、修正、乐趣等等,最后把软件开发定性为:一种创造与交流的合作游戏(a cooperative game of invention and communication)。游戏的首要目标是交付正确工作的系统,次要目标是生成一些“沉淀”(residue)产品为下一次的游戏进行积累。
游戏的参与者有项目出资人、管理人员、应用域专家、软件设计开发人员、测试人员与文档写作人员。他们需要互相帮助合作以达到目标。其中,开发人员扮演着重要的角色,他们要完成的主要动作是:
理解问题空间,并设想出技术上可行的方案来解决问题;
把头脑中的“内部”过程用可执行的计算机语言表达出来;
留下必要的工作标记(marker)以支持首要目标(项目组内的交流)和次要目标(传递这次开发的设计思想),这里“必要”的标准是刚好满足要求就行(sufficient-to-purpose)。
简言之,这场游戏中所见的只是人的创造性思想以及这些思想在人和人、人和计算机之间的交流。
人啊,人
如此说来,人的因素应当是软件开发中最为重要的了。作者在广泛的项目采访中也发现,一个项目的成功与否,人的因素起着决定性的作用。一个成功的团队几乎总是能做出需要的系统,这与技术和软件开发过程没什么必然的联系。但软件开发中对人的研究却出奇地少。根据作者调查,第一本这方面的专著是 Weinberg 在1969年写作(正是软件工程的观点兴起之时 [4])、1971年出版的 The Psychology of Computer Programming (此书的“银版”-- Silver anniversary edition 于1998年出版)。在沉寂了15年之后,DeMarco 和 Lister 写了 Peopleware: Productive Projects and Teams。有趣的是,又是15年过去了,作者的这本 Agile Software Development 可能是这个领域的第三个“里程碑”了。
作者在1994年就明确地提出了人是“非线性”的观点。这种非线性表现在,给一个人双倍的输入(如双倍的时间,或双倍的报酬诱惑),你不能期待着他就能做到双倍的输出(双倍的思考质量,或双倍的代码行)。在这本书中,作者更进一步地讨论了人的特点,特别是这些特点在软件开发中的作用。
首先,人是不可预料的。作者用了一个有趣的摩登单词 funky(这里有“奇异”,“复杂”,“不可思议”之意)来描述个人。人的 funkiness 表现在
自发冲动(spontaneous):可能会突然心血来潮去干一件事;
自相矛盾(contradictory):如时而口若悬河,时而缄口不语;
变化无常:人的个性可能会随时间(每小时、每天、每年)或/和环境(房间、温度、同事)而变化。
人也是非常多样化的[5]。有人善抽象思维、有人喜具体细节,有人夸夸其谈、有人沉默寡言,有的领导专行独断、有的上司民主亲善,等等。人的多样性也可以解释为什么文献里记载的软件开发方法过程如此之多,这是因为每一种方法都可以找到自己的一群支持者。
人的哪些弱点会导致一个项目的失败呢?作者归纳了五条:
犯错误。人要犯错误是很常见的,不足为奇。特别是在软件开发中,能第一次就把事情完全做对 的情况不多。克服这种弱点的办法一般是“往复式”(iterative)或“递增式”(incremental) 开发过程[6]。
倾向保守,墨守成规,缺乏冒险精神。最明显的例子是一般的项目经理宁愿使用已成常规的 瀑布式开发过程(尽管实践证明这种方法有很大的缺陷),也不愿使用新一些的递增式开发方法。
只想创新,不愿调查研究并使用已有的解决方案或软件组件。程序员中只想创新的冲动特别明显, 这大概是由于从小在学校接受的教育是要创新的缘故。一种纠正的办法是鼓励复用。
习惯难改、行为又不能保持一致。一个常见的例子是,对某些人来说(比如本人),要使自己的工作台 一贯地保持整洁,是多么痛苦的一件事情。同样,在软件开发中,要求改变工作习惯并保持下去,也就可想而知了。
不愿受纪律约束[7]。这是上一个弱点的直接后果。那么, 在软件开发中,如何来克服这个弱点呢?作者认为 有两种相反的途径:一是用高度纪律性的过程,二是用宽容性的过程。著名的XP是前者的代表,而作者的 水晶系列方法则是后者的思路。
那么,人有哪些特点会使一个项目成功呢?作者归纳如下:
善于寻找(good at looking around)。这是指当一个人在一定的范围内能根据自己的智能和经验 迅速地发现要找的东西,或注意到一些不寻常的东西。在软件开发中对人的这个特点的一个应用便是设置 设计文档合适的详细度,一般来说设计文档可以粗一些,能通过它很快地找到相应的源码部分就行了。
学习能力。人们在项目的开发中可以逐步学到新技术、应用域知识、开发过程以及如何与同事合作。一个项目 完成时,新手可能就变成老手了。
可塑性。人们在接受了新思想之后能够极大地改变自己的行为。例如,C3项目在Kent Beck 接手以后, 大力推行化繁为简的设计/编码原则,同样一班人马在接受了 新的观念之后,取得令人惊叹的效果。
工作自豪(或成就)感。人总是希望在工作中显示能力,取得成绩,获得一种自豪感 (pride-in-work)。这种动力也体现在本职工作之外,如利用自己的长处帮助他人或团队 (pride-in-contribution),或发现问题主动报告或解决。
作者列出了相当一些良好的工作方式,它们虽然是对个人而言,但要有效地实施却有赖于个人和管理层的共同努力。偏重个人的方式有:
从具体着手。人在开始工作,或学习新东西时,一般喜欢从一个具体 的实例入手,通过自己琢磨,或与别人讨论,来理解“这一个”,进而理解“这一类”。 所谓“举一反三,触类旁通”是也[8]。
使用实物。在项目的某些阶段,如需求分析时,可以用一些实物来帮助人们更好了解系统。 这些东西要看得见、摸得着、随手能移、信手便改,一般来说低技术的东西效果更好, 如纸张、卡片、纸盒等等。 CRC(Class-Responsibility-Collaborator)卡便是这样一种技术。
依葫芦画瓢。“拷贝和修改”(copying and altering)是人们在工作中常用的方法,如写 一份计划时,通常是找到一份类似的计划,然后改动一番。同样在软件开发中,碰到一个问题时, 常用的方法是找到解决类似 问题的程序,再加以修改[9]。
而以下这些方式则需要个人与管理层的共同努力:
回报激励。编程很大程度上是一种“本能激励”(intrinsic motivated)的活动,因此,要有效地 激励程序员,除了物质上的奖励之外,主要是要让他们从工作中获得自豪感和成就感。其实,在递增式开发 过程中,经常的(哪怕是微小的)成就可以让程序员感到他们的工作得到了回报 (pride-in-accomplishment)。
频繁反馈。频繁的反馈既有利于个人和团队的学习,也有利于系统开发。一个开发过程中应该有频繁的反馈 机制,如用户使用反馈,系统测试反馈,开发过程检讨等等。
默想与交流。程序员在考虑一个问题的解决方案时,需要一个安静的环境,以进入一种所谓“流” (flow)的创造状态[10]。但软件开发又是一种需频繁交流的活动, 需要一个较紧密的环境, 因此需要处理好这两者之间的关系。作者建议在设置工作环境时(如坐位安排)应加以考虑。
工作与个性相匹配。在一个项目中,分配工作时最好能使工作的性质与个人的个性相匹配,这样 能使个人的强项得以最大程度的发挥。
充分发挥优秀人才的作用。一个优秀的程序员对项目的成功有着非常大的(甚至是决定性的)影响。 通常,高手出马,一个顶俩(或更多)。
团队的力量
现代的软件开发,几乎不太可能一个人包打天下。软件开发活动是一种群体活动。要使这个群体有效地运转,作者认为最重要的莫过于成员之间的相互交流与合作了。
信息对流
信息对流(convection currents of information)是作者的一个语汇,它用热气流动来比拟信息的流动。一个人的存在、他的姿势、他的声音、他的脚步,都是在向周围环境放射着信息,为别人所接收。同时,他也接收着别人放射出来的信息,从而形成了信息的对流。
作者详细分析了一个最常见的问题与解答过程,假设A知道一些信息,而B正需要这些信息。那么要考虑:
B要用多久才能发现A有所需的信息,
完成信息从A到B的传送的所消耗的能量是多少。
作者从两人的工作地点来对这两个问题进行了分析:
坐在同一台机器前(如作pair-programming)
坐位相邻
同一间屋子
办公室相邻
同一幢楼但不同楼层
不同的城市或国家
答案是不言而喻的。
作者还提出了“渗透交流”(osmotic communication)的概念。这是指在一个公用的的办公室里,你在专注于自己工作的同时,会不由自主地听到一些背景声音,如别人正在讨论某个问题,并能从中不自觉地提出一些感兴趣的信息。这可以使发现信息和传递信息的成本得以下降。
基于以上的观察,作者认为一个项目组最好能够都在一个(大)办公室之内,这样能最大限度地提高信息交流的效率。更进一步地,如果项目组有不同专业的人员,如程序员和应用域专家,他们的坐位应该混合安排,即避免分组安排时容易出现的小圈子效应。另外一点要注意的是,如果一个大房间里有两个或以上的项目组,那么它们之间则应最大程度的加以隔离,减少干扰流(draft)。
布置办公室时要考虑的一个重要事情是放置“信息发射源”(information radiator)。这里,一个信息发射源一般是指挂(贴)在墙上的大尺寸的图表,这样人们过上过下时都能看见。一个好的信息发射源应该具备两个特点:内容随时更新,看上去一目了然。这种信息发射源最常见的内容有:总体项目进度、开发工作完成情况、系统测试情况、系统运行状态等等。
跃过交流的沟堑
为了提高交流的效率,作者还以两人在一个白板前的讨论为例,详细分析并列出了11项交流的要素(modalities in communication)。它们是:物理上的近距离性(physical proximity);三维性(three-dimensionality);气味(smell);动觉(kinesthetics);肢体接触[11](touch),如拍拍肩膀;声音(sound);视觉(viusal);要素同步(cross-modality timing);低负载(low latency),因此可以有实时问答;信任与学习(trust and learning);共用持久性的信息发射器(use a shared,persistent information radiator),如白板。作者认为具备了所有这些要素的交流是最有效的。
如果去掉其中的一个或多个要素,会给交流带来怎样的影响呢?
只去掉物理上的近距离性:交流可通过电视会议来进行,这基本上保持了其他的要素。
再去掉视觉:则可用电话方式,但它已失去了大部分要素了。
再去掉声音:则可email方式,与电话相比,则失去了实时性。
去掉提问的可能性:那么这时信息只是单向流动了,如看录象、读书等。
作者又考虑对一个已存在的交流方式来说,可以通过增加它的要素来提高交流的有效性。例如,作者坦言,他对“Design Patterns”[12] 中的某些模式(pattern)还是不甚了了(并推测很多读者想必也是如此),因此建议此书可配上录象带,由pattern的作者来讲解一番,这样肯定会帮助读者理解。
提高交流的有效性还有一个重要的问题就是很多时候需要把讨论中信息记录下来,如记录在纸张上,或在白板上。作者称之为给信息加上“粘滞性”(stickiness)。这些记录下来的信息可以保存起来,供以后需要时查看。作者还提到了一些具体的方法。例如,把大张的白纸贴满墙上,大家可以随时随地在上面写写画画。一张纸画满了,就把它卷起来,标上日期,然后存放起来。
集体主义放光芒[13]
一个项目组的成员可能来自五湖四海(特别是大项目),为了一个共同的目标[14],走到一起来了。如何高效得去达到这个目标呢?很重要的一点是,大家要心(尽量)往一处想,劲(尽量)往一处使。如何做到这一点呢?作者认为可以通过如下方法让每个成员作一些小的、容易做到的改变:
告诉每个人现在项目的主攻方向是什么;
现在选择这个主攻方向的理由是什么;
告诉每个人他现在的行动对项目有什么作用。
这样,每个人可能只是把他的方向往目前项目的方向上调整了一点点,但产生的合力是很大的,能取得了事半功倍的效果。
要提高集体(团队)的战斗力(工作力),还有一个重要的方面,那就是在项目组中建立起良好的人文环境。使大家心情舒畅,愿意互相合作,互相帮助。作者从友好与冲突,团队意识和团队文化等方面讨论了这个问题。
友好与冲突(amicability and conflict)。友好是信任与合作的基础。作者把友好定义为 “愿意倾听别人的想法,说话无恶意”,并且认为可以从一个团队内部的友好程度(amicability level),看出同事间交流时的信息开放或封闭程度。友好(与人为善)能造成一种气氛,使大家畅所欲言,特别是不同的意见。这里作者把交流不同意见称之为冲突,并且认为这样的冲突是必须的,没有冲突或冲突不足对工作是不利的。
建立团队意识(team building)。现代企业一般都很重视团队意识或协作精神的培养。有些公司在开始一个项目时把所有成员拉到一个地方去活动一两天,以使大家增进了解,在工作中能很好地合作。这种做法在实践中也很有效。但有些程序员却不太以为然,说道:“我对我们是不是能一起烧烤或一起爬墙不感兴趣,我只对我们是否能一起做出软件感兴趣”[15]。那么,什么是更有效的方式呢?作者引用了一些相关文献的建议,认为最好的活动是能让大家一起做出一些只有在一起才能干出的活。
团队文化(team culture)。一个项目组往往具有自己独有的团队文化。它会受到所在的企业或组织的文化的影响,也会受到国家民族的文化的影响。团队文化有各种表现形式,作者引用文献着重讨论了项目组的四种组织结构:
等级结构(hierarchical):这是传统的结构,多见于老牌大公司。
随机结构(random):为等级结构的反面(无政府主义倾向严重),多见于新成立的小公司。
协作结构(collaborative):成员们通过交流与君子协定来推动工作进行。
同步结构(synchronous):为协作结构的反面,即用不着言语交流。成员们各司其职,配合默契。
团队文化还有一个重要方面便是职业亚文化(professional subculture),也就是每一个职业特点形成不同工作方式与习惯,作者列举如下:
项目经理需要有条不紊的工作作风,需要能预测任务的完成日期以及成本等。
OO程序员需要抽象思维能力,在思考问题时需要安静,不喜欢被打扰。
需求分析员需要对系统功能与接口做细致的逐条梳理。
市场营销人员需要杰出的想象力和人际交往能力。
对待这些亚文化的差异,作者提出可从三个方面入手:
对业界来说,鼓励对软件开发团组的社会人类学研究。
对技术多面手来说(如同时善长于编程、数据库、设计、项目管理和教学者), 他们可以成为不同角色间的“翻译者”
对每个人来说,应该了解其他的亚文化价值系统,并在实践中表现出耐心和理解 [16]。
法无定法[17]
Methodology这个词一般译作“方法学”或“方法论”,即“study of methods”。而作者使用这个词是用的Merriam-Webster字典中的定义:“a series of related methods or techniques。” 即“一组相关的方法或技术”。而 method的定义是“systematic procedure”,类似“technique”。作者也提到一位同行在1993年告诉他的一句话:“methodology is a social construction。”过了两年,他才开始理解这句话的含义,并给出自己的定义为:“A methodology is the conventions that your group agrees to。” 即你的团组同意遵循的一组习惯做法。这实际是个“social construction”(社会建设),社会性的一个重要的方面便是协调团组成员之间的活动,促进交流与合作。下面将试着把methodology译为“一套方法”。
要素
作者认为,一套方法需考虑的(客体)结构要素有:
角色(roles)。每个团组成员的工作要求、他的技能以及他的个性特点。
个性(personality)。人员的个性特点(似乎为角色的一部分)。
技能(skills)。角色需要的技能,如在一个项目中,程序员需要具备或学习OO、Java和单一测试。
团队(teams)。一个项目可能只有一个组,如开发组,或多个组,如开发组、分析组和测试组。
技术(techniques)。完成一项任务所需的知识和过程,如编写使用情形(use case), 项目回顾(project retrospective)。
活动(activities)。团组成员的日常工作,如计划、编程、测试、开会。
过程(process)。活动如何随时间展开,每项活动的的前提与后置条件。一般来说,这是一个工作流程。
工作产品(work products)。工作产品可以是临时性的如CRC卡,或永久性的如源码和设计文档。
阶段进展(milestones)。在某一时刻一个阶段任务的完成情况,如源码是否交付、文档是否完成。
标准(standards)。如编码标准(coding standard)、画图标准等。
质量(quality)。质量可以是对活动而言,也可是对工作产品而言。
团队价值取向(team values)。价值取向将极大地影响团队的工作模式,如想着“尽快面市” 的团队就和看重家庭的团队的工作模式不同(加班加点和下班准时回家)[18]。
工具(tools)。项目组使用的工具。
对于一套方法本身(主体),作者提出了如下这些概念要素:
方法大小(methodology size):所控制的要素的数量,要素如系统发布(deliverable)、标准、活动等。
正规性(ceremony):方法的精确度与控制的松紧度。如对一项使用情形(use case)作检讨回顾,正规性低的方法 允许利用午饭时间边吃边做,而高正规性的方法则可能要求花两三天来做。
方法重量(methodology weight):这是方法大小与正规度的乘积,这只是一个概念性的,并非一个精确数字。
问题大小(problem size):问题中的元素与它们的交叉复杂性。他很大程度上取决于估测者的知识与看问题的角度。
项目大小(project size):项目组人员数量。但需注意,这个测度与“问题大小”是不同的,不可混淆。
系统要紧性(system criticality):系统出错时会造成的影响,如饮料机(本来要咖啡,结果出来可乐) 和飞机(可能机毁人亡)的系统要紧性显然不同。
精确性(precision):表述一个问题时精确到什么程度,如到类图(class diagram)还是到源码。
准确性(accuracy):表述一个问题时的正确程度,如GUI,后期的描述一般要比初期的准确。
相关性(relevance):对某一个问题是否加以考虑,如讨论GUI时可以不考虑domain model。
宽容性(tolerance):当实际与制定的规章偏移时,能容许多大的偏移。
可视性(visibility):“外人”是否能容易地看出项目组是不是在遵循所规定的方法,如IS9001便很强调可视性。
比例尺(scale):描述一样东西时允许多少组成元素同时出现。如UML中的package使我们能用不同的比例尺来看待使用情形(use case)和类(class)。
稳定性(stability):改变的可能性。如项目初期的变化最大(两眼茫然),中期变化较小(大势已定), 后期相对稳定(小修小补)。
设计原则
把这些结构与概念要素综合起来,可以为设计一套方法提供一个系统的思路。从这些要素和对个人和团队的分析出发,作者根据自己的经验,提出了七大设计原则:
1.面对面的交流是费用最低、速度最快的信息交换方式。
如果可能,项目组成员应该坐在一起,这样交流起来方便,使开发工作能有效进行。这句话反过来说,如果项目组很大,则这种面对面交流变得困难,交流费用上升,交流质量下降,从而会增加软件开发的困难。所以如果生产率和资金是关键因素的话,那么应该尽可能使用人数少(因此能坐在一起)的团队。
2.方法超重时代价昂贵。
前面提到“方法重量”是方法控制的结构要素与正规性的乘积。所以,当控制要素数量增加(典型的如分析、规划、设计、图表等文档这样的工作产品),正规性提高时(典型的如频繁的开会、报告),那么开发进程将受到很大影响。但是如果重量太轻,也许生产率一时上去了,但质量却下来了,结果要花更多的时间来排错。所以,对这个“度”的设置需要小心。
3.大的团队需要重一些的方法。
团队大起来以后,特别是坐位一分散,成员之间的直接交流便减少,如果没有一套有效的协调与交流的方式,工作易于陷入混乱,影响开发效率与质量。但如果过重,就会导致原则2所说的后果。所以还是有一个“轻重”度权衡的问题。
4.系统越要紧/重要,正规性应越高。
如上所述,正规性提高将导致费用上升。但另一方面,正规性提高的确有助于少犯错误。而这一点对重要性很高的系统是必须的(如航天飞机和核电厂项目),所以费用比一般系统要高也是在情理之中,可以接受的了。
5.增加反馈与交流可以减少中间产品。
这里的“中间产品”是指在一个组内部使用的工作产品,作者把它们称之为“允诺性便签”(promissory notes),主要是指那些描述计划中的(所以允诺要完成的)的活动的文字材料,如分析、设计、测试计划等。作者认为有两种方式可以减少中间产品。一是尽快拿出工作系统(尽管只有部分功能)。这样能极大地促进用户、系统分析人员、设计师和测试人员之间的交流与反馈,使得有些中间产品成为没有必要了。二是减少项目组人员,使得大家能坐在一起,面对面交流,有些中间文字东西也没必要再写了。
6.纪律、技能、理解与过程、形式、文档的对立。
这个原则来源于Jim Highsmith的三句话[19]。纪律(discipline)是指一个人(主动)选择要求的工作方式,而过程(process)是指人(被动)听命而行;技能(skill)含有创造性的能力之意,而形式化或手续化(formality)则是要求按步就班;理解(understanding)是指知识,包括那些隐藏的知识,如在项目中谁知道什么、那些讨论成为设计的一部分等,而文档(documentation)则只是理解(知识)的一部分。探索性的活动需要强调纪律、技能和理解,而软件开发很大程度上正是一种探索性的活动。
7.从非瓶颈活动中求效率。
每个项目一般都有一个瓶颈所在。如果项目进度因为瓶颈受阻,那么提高项目的总体效率的通常做法是调更多的精兵强将人员去支援瓶颈处的工作。其实还有一种做法,便是对非瓶颈处(特别是瓶颈的“上游”)的人员的工作进行调整,让他们在把结果提交给瓶颈之前多花些时间把他们的工作尽可能的稳定下来,从而减少瓶颈处的“重做”(rework)负荷(软件开发中总是有“重做”)。这是一个以效率换稳定的策略。
在设计方法时,应充分考虑这些要素与原则。一个重要的推论是“不同的项目应该有不同的一套方法”,作者提供了一个思路, 用一个三维坐标系统来表示不同的方法。项目组人数作为x坐标,系统要紧性作为y坐标,系统优先因素作为z坐标。x坐标取值为1-6人,20人,40人,100人,200人和500人;y坐标取值C(loss of comfort), D(loss of Discretionary money),E(loss of Essential money)和L(loss of Life)。这样xy不同的组合就形成了不同的坐标格,表示一个项目的基本特征。例如,“C6”表示一个项目有6人,系统出错时会引起一些不方便。而“D20”则表示一个有20人的项目,如果系统出错会导致损失一些金钱。对每一个xy坐标格,z实际上说明了项目的一些其他特征。作者用这个思路来设计了他的水晶方法系列(Crystal methodology family),“D6”类称之为 Crystal Clear,“D20”类为Crystal Yellow,“D40”类为Crystal Orange。在此框架下,XP可归入C4至E14。
对于项目的具体运作,作者还从实践经验中归纳出一些“甜蜜之处”(sweet spots)[20],并认为如果采用的一套方法靠近这些甜蜜之处,那么开发的效率可以提高。
二到八人坐在一起。
专家用户在场。
一月递增周期。
全自动回归测试(单元或/和功能测试)。
有经验的开发人员[21]。
构造与生长
一套方法应该是动态的、自适应的,也就是说,一套方法要在适应开发环境中构造和生长。作者把一个软件项目比拟为一个生态系统。系统中的各组成部分如人员个性、坐位、工作语言等都在相互作用、相互影响之中。当然,一个良好而稳定的系统的形成与发展主要取决于项目组成员的交互作用[22]。如果大家能理解个人、团队和方法的特征,那么他们就能更好地选择(或设计出)一个适合于自己这个项目的初始方法并不断地发展之,而推动发展的一个关键之处在于经常性的检查与调整。这是一个随时间而进行的过程,作者提出的具体步骤为:
现在。随时可做的(不一定要手上有项目),主要是增加对目前所在的公司的开发方法的了解。具体方式是(最好几个人)去找人一对一地谈话,收集如下信息:
项目名,受访者在项目中的角色;
项目数据(如起止日期,最多时的人数,应用领域,使用的技术);
项目历史;
做错的/不要再重复的;
做得好的/可保留的;
优先因素;
其他。
对这些信息进行分析,找出不同项目的共同之处。
项目开始时。要做的是设计出一个初始方法,这可以分两步进行:
由两人对目前的项目进行分析,提出草案。具体步骤为:在人数、系统要紧性、优先因素的三维坐标中 找到这个项目的位置;找出这个(待提出)方法的概念要素,如正规性、文档的范围与详细程度、递增周期长度等; 选择一个相近的现成方法,如XP、RUP等;
召开团组全体或代表会议(半天到一天),充分讨论候选方法,并加以修改、“定稿”,成为项目的初始方法。
第一个递增周期的中间。需要一个1-3小时的会议,讨论目前的方法是否工作,有无根本性的错误,能否在第一个周期结束时拿出一个哪怕是很小的、但是测试过的、可运行的工作系统。要达到此目的,必要时需对工作系统的功能作一些调整。
每个递增周期之后。应该有一个专题检讨会(relection workshop),短至2-4小时,长可2-3天。经过一个周期之后,可以全面地对所用的方法的各组成单元进行评价。要讨论的两个主要问题是“学到了什么”和“什么可以做的更好”,据此对方法进行一些修改,作为下个周期的方法。
(第二个以后的)每个递增周期的中点。可以召集一个会议或个别谈话。这个检讨的目的主要是尝试新的想法和做法。因为经过了两三个成功的周期之后,项目组成员们有足够的经验来作新的“冒险”[23],即使不成功,也有后路,不会影响大局。但作者认为如果周期为三周或更短,则这个中点检讨可以不做。
多余的话
我去年(2001)七月左右第一次读到这本书时的草稿(draft version 2b1)时,第一感觉就是耳目一新。对书中所列举的对个人和团体的分析都有一些似曾相识之感(相信干过几年软件开发的同行都会有同感),但从未这样集中、全面而详细地读过。读第一遍产生的“冲击波”消退后,我开始重读并作了一些笔记,以求更好地理解并掌握作者的主要思路,但在阅读中却觉得材料有些零乱和重复。这本书去年底正式出版以后,和version 2b1对照着又读了一遍,发现基本材料(我想有90%)没变,但次序和结构有些变化。很明显,作者在尽力把这些材料有机地组织起来并表述出来。
总的说来,我觉得这本书提供了一个新的角度来看待软件开发活动和新的思路来设计开发方法。书中提供的材料大部分来自作者丰富的实践经验,对软件开发实践有很高的参考价值,值得软件项目参与者,包括出资者、管理者与开发者反复研读。我认为美中不足的是,作者试图建立来统率这些材料的框架并非严谨完美,从结构上说,这本书给我的感觉更象是一本结构化的技术散文集,而非严格意义上的学术著作。不过,从另一方面说,这也许是一个优点,让读者能从这些丰富的材料中,根据自己的知识和经验来构造出自己的“理论”框架。
在这篇介绍文章中,我试图根据我的理解来勾勒出的作者的主要思路,使读者诸君对这本书有个大概的印象。文章基本依据书的顺序,为方便读者阅读原文,再简要说明如下:
“Introduction: Unknowable and Incommunicable”:引论,主要说明人要正确地认识事物和准确交流是件非常 困难的,甚至是不可能的。本文未作介绍。
“Chapter 1: A Cooperative Game of Invention and Communication”:在本文的“软件开发是什么”中介绍。
“Chapter 2: Individuals”:在本文的“人啊,人”中介绍。
“Chapter 3: Communicating, Cooperating Teams”:在本文的“团队的力量”中介绍。
“Chapter 4: Methodologies”:在本文的“法无定法”中的“要素”与“设计原则”中介绍。
“Chapter 5: Agile and Self-adapting”:在本文的“法无定法”中的“构造与生长”中介绍。
“Chapter 6: The Crystal Methodologies”:是作者对其水晶方法系列的简介。本文未作介绍。
这本书和Jim Highsmith的Agile Software Development Ecosystems 是计划中的“Agile Software Development Series”(系列丛书)的两本基础书。作者称这套丛书的核心思想是:
不同的项目需要不同的一套方法。
注重技能、交流和团队的项目要比注重过程的项目有效。
这套丛书可分为三大类:
个人技术,如作者的“Writing Effective Use Cases”。
群体技术,如作者的“Surviving Object-Oriented Projects”。
方法实例,如作者的“Crystal Clear”。
从这里可以看出,作者关于软件开发的思路是技能、交流与团队为纲,方法过程为目,“纲举目张”。
鸣谢
感谢agilechina.org的诸位同伙对写作本文的鼓励以及对初稿提出的意见和建议。
注释:
注释部分有些是正注,有些则为“胡批”,博看官一笑,不必当真。
1. Tony Hoare 是计算机科学的奠基者之一。1999年从牛津大学退休。此公老骥伏枥,志在一统。最近几年从事的研究之一便是计算机科学的统一理论。
2. Bertrand Meyer 是现代软件工程的先驱之一,他的著作 Object Oriented Software Construction 被视为OO技术的经典。“契约设计”(Design by Contract)是他对软件开发技术的重要贡献(Meyer的一篇关于“契约设计”的 介绍短文,参考译文见 http://members.tripod.com/jian_hu/meyer/contract.html)。 他最近有一篇文章 Software Engineering in the Academy(参考译文见 http://members.tripod.com/jian_hu/meyer/teaching.html), IEEE Computer 2001年5月 是谈院校的软件工程教学的,也可从中较全面地了解他对软件工程的看法。
3. 本人曾经有一位同事就是人们头脑中艺术家的典型形象:长发垂背、胡子拉碴、不修边幅,整天龟缩在一个阴暗的房间里,瞪着鬼火一样一闪一闪的屏幕。
4. 有趣的是,(19)60年代末70年代初,也是结构化程序开始盛行之时。1968年 Edsger W. Dijkstra 著名的“Go To Statement Considered Harmful”, Communications of the ACM, Vol. 11, No. 3, 1968,打响了对“GoTo党乱动派”的第一枪。
5. 俗语说:人上一百,形形色色。或曰:林子大了,什么鸟都有。其实,林子不大,鸟的种类也未必单一。
6. 作者书中的 iterative 的含义和现在常用的意思不太一样。书中给的定义是:a scheduling and staging strategy that allows rework of ieces of the system,所以,译成“反复”似乎恰当一些。而incremental在书中的定义为:a scheduling and staging strategy in which peices of the system are developed at different rates or times and integrated as they are developed,此处译为“递增”,但其义似乎更接近于 Martin Fowler 的 The New Methodology 中的 iterative。
7. 毛主席早就说过:加强纪律性,革命无不胜。
8. 书中作者引了 Lave 和 Wenger 的 Situated Learning中的一段:“The world carries its own structure, so that specificity always implies generality”。特殊性总是蕴涵着普遍性,这简直就是我们从中学到大学的政治课里面学的经典原理之一。
9. 广义上说,这是一个复用(reuse)问题。
10. 这似乎有些玄得象练气功或参禅了,但准确地说可能是进入了忘我而想物(程序)的境界。
11. 郑重声明:这里的“肢体接触”与议会全武行无关。
12. “四人帮”的“Design Patterns: Elements of Reusable Object-Oriented Software” 引发了这几年的经久不衰的pattern热潮,Grady Booch 更认为这是超越Object的三个迹象之一(另两个是多视角描述软件系统架构和Aspect-Orientd Programming)。“四人帮”之名也许来自中国文革的王张江姚四人帮。有趣地是,pattern “四人帮”希望 他们和正宗“四人帮”推动文化大革命一样,能带来一个“设计(小)革命”,当然不愿象正宗“四人帮”那样因为他们的“反革命”思想而末日来临。而更为有趣的是,中国曾在1980年底审判文革“四人帮”,而计算机领域在1999年也有一次“审判pattern四人帮”,控告他们“对计算机科学犯下的罪行”,详见 http://www.c2.com/cgi/wiki?ShowTrialOfTheGangOfFour。
13. 书上的小标题是“Teams as Communities”。这里“team”应是指项目组,偏重于“物理”上的一堆人,而“community”更有“精神”上的同信(心)协力之意。这层意思也许老词“集体”,或新词“团队” 都可以表达出来吧。
14. 目标是系统开发。这个目标可能不是革命的,但一般来说不会是反革命的。
15. 这句话本人深表赞同,尽管有些“狗坐箢篼--不受抬举”之嫌。
16. 老山战士当年喊出的“理解万岁”应该是放之四海而皆准的。
17. 四川新都宝光寺有联曰:“世外人法无定法然后知非法法也,天下事了犹未了何妨以不了了之。”对我等靠敲键盘养家糊口的俗人来说,却是“做开发虽然法无定法却需有法法也,建系统总是了犹未了还得慎了了之”。
18. 曾在网上看见过一首顺口溜:一等男人外面有个家,二等男人外面有朵花,三等男人舞厅随便抓,四等男人下班就回家。
19. Jim Highsmith says:“Don't confusedo
cumentation with understanding;
Process is not discipline;
Don't confuse formality with skill。”
20. 当然,这里的“sweet spots”与圣经中的“流着奶与蜜”的地方无关。
21. 对XP的批评之一便是说XP是“hire the best, fire the rest”。
22. 金观涛在1980年代在“整体的哲学”一书中提出的组织的产生与生长的理论也许可以借鉴,即一个组织能稳定存在是因为它的子系统之间的功能是耦合的,而组织的生长是组织从一个稳态相另一个稳态的演进。
23. 邓小平的教导:“胆子再大一点,步子再快一点”此时可用。
--------------------------------------------------------------------------------
修改记录
2002年3月:完成全文,并作部分小修改。
2002年2月:前半部分发表于agilechina.org。
胡健
Email: jian4_hu2@hotmail.com
Web: http://members.tripod.com/jian_hu