第 3 章 敏捷原则

第 3 章 敏捷原则

如果我问人们想要什么,他们肯定会说想要更快的马(而不是汽车)。

——亨利 · 福特 1

1亨利 · 福特是否这么说过是有争议的,但是大家觉得这很符合他的风格。

没有什么灵丹妙药可以保证总是开发出完美的软件。敏捷团队也意识到了这一点。一些思想和基本原则可以帮助团队作出正确的选择并避免问题,或是处理那些必然会发生的问题。

我们在敏捷宣言中已经看到了四则价值观。除了这些价值观之外,每一位敏捷实践者还需要在软件项目开发团队中应用 12 条原则。敏捷宣言最初的 17 位签署者在犹他州的滑雪胜地很快就四则价值观达成了一致,但他们在宣言的 12 条附加原则上耗费的时间较长。下面是宣言签署者 Alistair Cockburn 的回忆。2

2《敏捷软件开发(原书第 2 版)》,Alistair Cockburn 著。

17 人的小组很快一致选择了这些价值观。而进一步的陈述却无法在这个会议上敲定。本节描述的这些价值观构成了当前的工作成果。

我们会越来越了解人们的看法,也会找到更准确的描述,这些陈述应该随之修改。在本书出版之后,如果现在的这个版本没有很快发生变化,我会感到惊讶的。最新版本的描述可以参见敏捷联盟(Agile Alliance)的网站(http://www.agilealliance.org/)。

Alistair 说得没错,目前网站上对原则的描述确实与他书中的描述有所区别。这些描述可能会不断地演化,但是思想和原则一直不变。

在本章中,我们会学习敏捷软件开发的 12 条原则,包括原则的内容、为什么需要这些原则以及这些原则会对项目有什么影响。通过实践中的例子,我们会学习如何将这些原则应用到真实的项目中。为了帮助理解,我们把这些原则分为四个类别:交付、沟通、执行和改进。这四个类别反映了敏捷原则中恒定的主题,也反映了敏捷开发的一般性原则。不过,这样进行分类只是学习这些原则的一种有效方式,每一个原则都是独立的。

3.1 敏捷软件开发的12条原则

(1) 最优先要做的是尽早、持续地交付有价值的软件,让客户满意。

(2) 欣然面对需求变化,即使是在开发后期。敏捷过程利用变化为客户维持竞争优势。

(3) 频繁地交付可工作的软件,从数周到数月,交付周期越短越好。

(4) 在团队内外,面对面交谈是最有效、也是最高效的沟通方式。

(5) 在整个项目过程中,业务人员和开发人员必须每天都在一起工作。

(6) 以受激励的个体为核心构建项目。为他们提供所需的环境和支持,相信他们可以把工作做好。

(7) 可工作的软件是衡量进度的首要标准。

(8) 敏捷过程倡导可持续开发。赞助商、开发人员和用户要能够共同、长期维持其步调,稳定向前。

(9) 坚持不懈地追求技术卓越和良好的设计,以此增强敏捷的能力。

(10) 简单是尽最大可能减少不必要工作的艺术,是敏捷的根本。

(11) 最好的架构、需求和设计来自自组织的团队。

(12) 团队定期反思如何提升效率,并依此调整自己的行为。3

3来源:http://agilemanifesto.org/principles.html(截至 2014 年 6 月)。

3.2 客户总是对的吗

翻回本章开头,重读一下章首的引文。亨利 · 福特想表达的真实意思是什么?他的意思是要向人们提供人们真正需要的东西,而不是提供他们要求的东西。客户有一个需求,如果你要构建符合这个需求的软件,那么必须理解这个需求,不论他是否能与你沟通。客户无法在项目初始告诉你他实际上需要的是一辆汽车而不是一匹更快的马。那么你应该如何同他打交道呢?

这就是 12 条原则的初衷:让团队构建用户真正需要的软件。这些原则的根基在于这样一个想法:我们要交付有价值的软件。但是“价值”这个词有点难以捉摸,因为每个人都会看到软件中不同的价值,不同的人对软件的需求是不同的。

现在,在你们手中就有一个很好的例子可以解释这一点。如果通过手持式电子书阅读器阅读本书,那么你就在使用能显示电子书的软件。花一分钟时间思考一下这个电子书阅读器软件的不同利益干系人(即对这个软件有需求的人)。

  • 作为读者,你希望可以在这款软件上方便地读书。你关注的是软件的功能:前后翻页、高亮段落或记录笔记、搜索文本以及跟踪上次读到的页数。

  • 作为作者,我们非常关注我们写的文字能否正确显示,列表项的“小圆点”是否正确缩进以方便阅读,读者是否可以在正文和脚注之间跳转,是否有良好的整体体验。这是享用我们的作品并从中学到东西的基础。

  • 编辑关心读者能否方便地获得图书,喜欢这本书的读者是否方便给好评并从出版社买其他图书。

  • 将本书售卖给你的书商或零售商希望读者便于浏览和购买他们卖的其他图书,并且可以快捷方便地下载电子书。

你还可以想想其他的利益干系人,以及他们各自关心的事情。上述的每一件事情都是软件带给利益干系人的价值。

市场上的第一款电子书阅读器并没有实现上述所有目标。运行在这些阅读器上的电子书软件花了很长的时间才进化成现在这幅模样。几乎可以肯定的是,随着开发团队不断地发觉传递新价值的新方法,电子书软件会越来越好。

就电子书阅读器的软件而言,我们很容易看出其价值所在,因为我们已经能看到了阅读器软件现在的状态。而在项目刚开始的时候,要看出其价值就会困难得多。为此,我们做一个简单的思维实验。考虑这个问题:假设使用瀑布式流程开发,那么这个阅读器会是什么样子的?

“按我现在说的做,而不是按我之前说的做”

假设你在首款手持式电子书阅读器的开发团队中工作。硬件团队交付了一款原型设备,带有一个 USB 接口,可以把书传进去,还有一个小键盘用来交互。现在轮到你和团队开发显示电子书给读者的软件。

遗憾的是,你所在的公司多年以来一直使用“开始前建立完整的需求”这种特别低效的瀑布式开发流程。因此,项目经理做的第一件事情就是找所有人开大会。接下来的几个星期里,你的整个团队都会泡在会议室中,一会儿与公司里的高级经理开会,一会儿与出版电子书的出版社代表开会,一会儿与想要卖书的在线零售商的高级销售人员开会,此外还要与项目经理能想到的所有其他利益干系人开会。

在多日的高强度会议和激烈讨论之后,业务分析师开始把所有信息整合在一起,制作成一份巨大的规格说明书,其中包含了从所有利益干系人那里搜集到的需求。这是一项很庞大的工作,不过现在已经有了一份大家都认为很不错的说明书。这份说明书包含了大量用户特性,足以成就最先进的手持式阅读器软件。这还包含了可以帮助出版商获得市场数据的特性,提供网络书店,方便购书,甚至还有一项创新的特性,能帮助作者在写作的时候预览和编辑自己的书,从而优化出版流程。这份说明书定义的软件的确是一款革命性的软件。然后你和你的团队坐下来预估时间,发现需要 15 个月。尽管这个时间非常长,但是大家都很兴奋,你也相信自己的团队可以交付这样的软件。

让我们看一下一年半之后发生的事情。电子书阅读器团队工作异常勤奋,投入了无数个通宵和周末,还给几段婚姻带来了压力。团队付出了巨大的努力,最终项目还是完成了,而且准确按计划交付了项目,几乎一天也不差。(是的,这看上去是不可能的!但是既然这是一个思维实验,所以就请相信确实发生了这样的事吧。)说明书中的每一项需求都实现了、测试了并且经验证已完成。整个团队非常骄傲,所有看到最终成果的利益干系人都认为这准确地实现了他们想要的功能。

最后,这款产品终于推向市场,结果惨败。没人为这款阅读器买单,利益干系人都不满意。这是怎么回事?

大家明白了一个事实:一年半前需要的软件并不是现在需要的软件。自项目开始以来,业界已经有了新的标准电子书格式。由于没有在规格说明书中体现,所以这种格式并没有得到支持。没有哪家网络零售商愿意出售这款阅读器使用的非标准格式。尽管团队开发了非常棒的网络店铺,但是零售商目前正在使用的店铺要先进得多,因此团队的作品对谁都没有吸引力。另外,你和你的团队花了那么多工夫为作者开发特殊预览功能,而竞品则让作者直接给读者通过电子邮件发送和显示 MS-Word 文档,高下立现,你们输了。

真是一团糟啊!你的团队在项目刚开始的时候制订的软件规格说明书,当时对所有公司内外的客户都很有价值。但是到了现在,一年半之前决定开发的这一款软件价值已经大大降低。有一些变数是在项目初期就可以发现的,还有很多变化在项目开始的时候是不可能预见到的。为了考虑到这些变化,团队应当在项目中的很多时间点快速地改变自己的方向。“预先指定大计划”的瀑布式开发方法限制了团队响应这些变化的灵活性。

那么我们怎样才能让项目更好地满足利益干系人和客户的需求,同时交付可工作软件?

3.3 交付项目

敏捷团队知道他们最重要的工作就是要给客户交付可工作的软件。在本书第 2 章你已经了解了他们达到这个目标的方法:以团队工作,与客户协作,并响应变化。但是团队在日常工作中应当怎么做呢?

如果团队能将交付价值当作首要目标,将变化看作是项目中的好事,并且频繁交付软件,那么这个团队与客户就可以一起工作,在开发的过程中及时调整。团队开发出来的软件不一定与刚开始计划的一样,但这是好事情,因为最终开发出来的软件就是客户最需要的软件。

3.3.1 原则1:最优先要做的是尽早、持续地交付有价值的软件,让客户满意

这条原则包含了三个独立的重要概念:尽早发布软件、持续交付价值,以及让客户满意。为了真正理解这项原则的核心,我们需要知道这三点是怎样结合起来的。

项目团队工作的环境是真实世界,在真实世界中没有什么事情是完美的。即使能够很好地收集并写下需求,团队仍然会漏掉一些需求,因为完美提取任何系统的完整需求都是不可能的事情。并不是说这不值得一试,敏捷方法的基础就是沟通和记录需求的优秀实践。问题在于客户在真正拿到可工作的软件之前,都很难想象软件到底应该如何工作。

这样说来,既然客户只有在看到了可工作的软件之后才可能给你真实有信息量的反馈,那么获得反馈的最佳方式就是尽早交付(early delivery):尽早给客户交付第一个可工作的软件版本。即便是只交付了一个可以工作的特性给客户使用,这也是一种突破。这对整个团队都是有益的,因为客户可以给出有价值的反馈,这样开发团队才能朝着正确的方向推进项目。这对客户来说也是有益的,因为拿到了软件就可以使用。也就是说,开发团队实际交付了真正的价值。尽管只是一小部分价值,但是比到最后一点价值都不交付要好,特别是在客户因为等了很长时间还没有看到软件而越来越愤怒的情况下。

尽早交付有一个缺点:最初交付给客户的软件完成度非常低。一些用户和利益干系人可能很难容忍这个。有一些用户喜欢尝鲜,但是还有一些用户对过早交付的软件兴趣低得多。很多人对于不完美的软件感到很不舒服。实际上,在很多公司里(特别是花费很多年与软件团队合作的较大型公司),软件开发团队必须认真协商向利益干系人发布软件的条款。如果开发团队与乙方之间没有很紧密的合作关系,而开发团队交付了不完整的软件,那么当用户和利益干系人发现有任何他们希望的功能缺失的时候,会给出非常可怕的处罚。

敏捷的核心价值观对此给出了答案:客户协作高于合同谈判。如果受限于固定的规格说明书,而且需求的变更面临僵化的官僚阻力,那么这样的团队别无选择,不可能让软件随着时间推移而演化。在这种条件下,团队必须启动全新的变更管理流程,这要求与客户重新进行一轮合同谈判。真正与客户协作的团队可以在开发过程中任意进行任何有必要的改变。这就是持续交付(continuous delivery)的意义所在。

敏捷方法通常采用迭代,原因就在于此。敏捷团队选择出能交付最大价值的特性和需求,并据此计划项目的迭代。团队确定哪些特性能交付价值的唯一方法就是与客户协作,并利用前一次迭代收到的反馈。从短期看,团队可以通过尽早交付价值让客户满意,从长期看,交付最终产品的时候可以实现价值最大化。

3.3.2 原则2:欣然面对需求变化,即使是在开发后期。敏捷过程利用变化为客户维持竞争优势

很多成功的敏捷实践者初识这条原则就遇到了很多困难。欣然面对变化说起来简单,但是在项目热火朝天地进行的时候,如果团队要处理需要大量工作的变化,开发人员可能会有情绪,特别是在老板不顾及工作量,要求不改变截止时间的情况下。这个坎可能很难过,特别是在团队因为项目延期而遭到抱怨的情况下。但是跨过了这个坎,收获也很大,因为欣然面对需求变化是敏捷工具箱中最有力的工具之一。

为什么项目中的变化会激起众怒?理解这一点就是理解本条原则的关键。想一下,做项目的时候发现正在开发的东西需求改变了,你会有怎样的感受?在知道需求变更之前,你以为项目进展得很好。你可能已经做了很多决策:如何规划产品结构,要开发什么产品,向客户承诺交付什么。结果现在项目外的某个人突然告诉你这个计划中有些错误,是你出错了。

“你出错了”,接受这样的指责是很难的,如果这样说的人还享受着你的服务,那就更是如此了。大部分软件工程师都是在技术自豪感的驱动下工作的:我们交付的产品我们能负责,而且能满足用户的需求。而项目中发生的变化则对这种自豪感产生了威胁,因为变化是在质疑你采用的方法,质疑你的设想。

经常出现的情况是,别人明确地告诉你怎样做之后却要求你改变方向。假设一个人要求你开发某个产品,你投入工作并完成了一半。如果这个时候,这个人跑过来对你说:“跟你讲,我经过了一番思考,我们能不能开发一个完全不一样的东西?”这会让人非常沮丧,感觉自己投入的努力没有得到尊重。现在你不得不返回去修改你以为已经完成的工作。人们很难不对此产生抗拒心理。更糟糕的是,你没有读懂客户,但还不得不冲击截止时间。

几乎所有职业开发人员都至少经历过一次这样的情况。在这样的前提下,我们怎样才能让自己欣然接受需求变化呢?

欣然面对需求变化的第一步是尝试从客户的角度看问题。尽管这一点并不总是容易做到,但是这种做法依然很有启发作用。你认为客户之前误导你了吗?当他发现你在他授意下开发的软件不对,导致你浪费了数月时间的时候,你认为他心里是怎么想的?他跑来告诉你需求有变化,这实际上是承认他自己犯了错误,让你白做了很多事情。这对他来说并不容易。难怪客户通常都会过了很长时间之后才跑过来告诉团队说要改变需求!他们知道自己带来的是坏消息,这是很让人难堪的行为。你不能按期完成任务了,他也一样。如果他有需求,而且公司花钱开发软件满足他的需求,而他的需求没有得到满足,那么这个项目就没有产生价值。而这全都是他的错,因为他在项目一开始的时候传递了错误的信息。

换句话说,两方都被要求做不可能的事情。你被要求读懂客户的心,而他被要求预测未来。如果你这么看问题的话,需求变化看上去就好接受多了。从另一方面看,如果你就是抗拒项目的变化,而且就是想严格遵照项目开始时指定的计划执行,也很简单,只要保证团队中的成员都具有心灵感应的能力和读心术就行了。

那么欣然面对需求变化意味着什么呢?它意味着以下几点。

  • 不要认为有变化就会有人“倒霉”。我们都承认,而且老板也承认,我们都是人,都会犯错。如果公司允许我们犯错并且能尽快改正,而不是期待我们一开始就把事情做完美就更好了。

  • 我们是一条绳上的蚂蚱。团队中的每一位成员,包括与你们合作的客户,都对需求和这些需求的变化负责。如果这些需求是错误的,你们的错误和客户的错误同样严重,因此抱怨变化是没有意义的。

  • 我们不把变化拖到最后。犯错误的确是令人尴尬的事情,但是我们都能意识到这一点,因此要尽早修复错误。这样,才能把损失降到最低。

  • 我们不要再把变化当成犯错。考虑到当时掌握的信息,我们已经尽力了,出了错事情才会变得更加明朗,因为开发过程中的各种决策让我们看到现在必须如何改变。

  • 我们通过变化学到东西。这是团队成长的最有效方式,也是团队学会更好地合作开发软件的最有效方式。

3.3.3 原则3:频繁交付可工作的软件,从数周到数月,交付周期越短越好

你可能会开始觉得欣然面对变化的想法有点意思,而且可能会对项目有帮助。但是你也许还会觉得这种想法看上去有点可怕。人们对这种想法有这样的反应还是挺常见的。很多在软件团队工作的人,特别是传统项目经理,在第一次听说欣然面对变化的思想的时候都感到很不可思议。这些项目经理每天都要处理各种变化,但是他们面对变化的态度和敏捷方法大不相同。敏捷实践者把对待项目变化的传统态度称作命令 - 控制(command-and-control)。

“命令 - 控制”这个词来自军事。我们在 2010 年出版的《团队之美》一书中,有一段对 Northrop Grumman(诺斯洛普 · 格鲁门公司,世界第四大军工生产厂商)的首席工程师 Neil Siegel 的采访。Neil 在采访中给出了“命令 - 控制”这个词的军事定义。

Andrew:我不太熟悉军事系统,“命令 - 控制”系统是什么?

Neil:指的是军事指挥官使用的一种信息系统。通过这个系统,指挥官之间可以互相通信并知晓当前的状况,例如所有人的位置和状态。这是指挥官了解当前情况的方法。过去的战场都不大,指挥官可以站在山头通过望远镜了解当前的状况。但是大约从 1900 年开始,战场开始变得很大,指挥官再也不可能像拿破仑那样站在山头指挥作战了。你开始需要通过技术手段“看清”整个战场。而实现这种功能的系统就称为命令 - 控制系统。

命令 - 控制式项目管理与军事上的命令 - 控制非常类似。

  • “指挥”指的是项目经理给团队分配任务的方式。尽管并不是所有成员都直接向项目经理汇报,但是项目经理可以控制所有人的任务分配。项目经理分解工作任务,安排时间计划,然后把任务分配给团队中的人力资源。

  • “控制”指的是项目经理管理变化的方式。每一个项目在开发过程中都会遇到变化:工作花的时间比预期的要长,团队成员休病假或离开项目,硬件不可用或损坏,还有其他种种以外的事情都有可能发生。项目经理不断监控这些变化的发生并把控项目:当变化发生的时候对其进行评估,更新项目计划,在进度安排和文档中引入变化带来的改变,给团队分配新的任务,管理利益干系人的期待,不要让人感到意外。

传统项目经理方案对“欣然面对变化”感到不安的原因在于,当她第一次接触到这种想法的时候,她感觉敏捷项目也会遇到传统项目的问题,团队需要响应这些变化。简单地接受变化而且欣然接受变化貌似会在项目中引入混乱。如果敏捷团队不使用命令 - 控制式项目管理,那么它们怎样才能在处理这些变化的同时仍然应对项目团队的日常问题?

欣然接受变化的同时不引入混乱的关键,在于频繁发布可工作的软件。团队通过迭代将项目分割至定期的截止时间。在每一轮迭代中,团队都要发布可工作的软件。在每一轮迭代结束的时候,团队都有一个可以展示给客户的演示,还有一个回顾会议用来回顾本轮迭代的过程以及探讨在本轮迭代中吸取的教训。然后计划下一个迭代要开发什么。可预测的进度安排和持续检查可以帮助团队尽早掌握变化,同时也创建了一个没有责备的氛围。大家在这个环境里可以讨论每一项变化,并制订解决这些变化的方案。

这就是敏捷方法吸引传统命令 - 控制式项目经理的地方。命令 - 控制式项目经理想要控制截止时间。有时间限制的迭代可以实现这一点。此外,这还化解了项目经理的一个最大难题:处理项目晚期发生的变化。传统项目经理工作中最大的困难之一就是监视变化。每日审查和迭代回顾相当于让整个团队帮助项目经理尽早发现变化,从而防止这些变化对项目造成更严重的影响。

项目经理的职责开始远离指挥和控制了。在传统的命令 - 控制方式中,他要做的事情是在团队中部署每日作战计划,以及不断地调整以确保大家都在正轨上。现在,他要与团队一起工作,确保每个人都在关注全局并且朝着同一个目标努力。在发布可工作软件的短迭代中,这些是比较容易做到的。每一位成员都有了具体的目标,而且可以更好地理解大家都在做什么。此外,每个人都会意识到自己不仅要对自己开发的部分负责,还要为整个团队在迭代结束的时候交付的产品负责。

{%}

图 3-1:团队通过迭代的方式频繁发布可工作的软件,每一次发布都添加新的特性

3.3.4 改进电子书阅读器团队的项目交付计划

这些原则可以怎样帮助陷入困境的电子书阅读器团队?回想一下这个团队遇到的问题:缺乏竞品都有的重要功能(支持业界标准的电子书格式,允许用户通过电子邮件向设备发送文档),而拥有的功能却没有什么市场(网络书店),他们开发的产品彻底失败了。

假设这个项目重新开始,我们让项目经理和利益干系人一起工作,并且让团队制订以一个月为周期的迭代。这一次项目的进展有很大的不同。

  • 在第 3 轮迭代之后,有一位开发人员报告说一种新的电子书格式已经被认定为业界标准。团队决定在第 4 轮迭代中实现一个支持这个格式的库,然后在第 5 轮迭代中把这个支持整合到阅读器的用户界面中。

  • 在 10 个月后,团队开发出了一个在原型机中加载并工作的版本,他们可以把这个版本分发给早期公测用户使用。项目经理和这些用户交谈,发现他们非常需要把 Microsoft Word 文档和报刊新闻加载到阅读器中阅读。团队决定在下一轮迭代中将电子邮件功能整合进阅读器,这样读者就可以把文章通过电子邮件发送到设备上。

  • 项目进行了一年,利益干系人告诉团队网络书店的功能实际上没有必要开发,因为所有的零售商都会使用标准的电子书格式。幸运的是,这项功能一直在积压工作表的底部,其他迭代周期都在开发更重要的功能,因此这项功能并没有耗费太多时间。

这个团队保证每一轮迭代结束的时候都能交付一份可工作的软件,因此从积压工作表中删除功能意味着他们可以赶早交付了!出版商合作伙伴已经准备好了图书,因为他们的高级经理早就获得了软件的早期版本和原型硬件,都已经试用很久了。出版商一直有参与感,因此他们也有动力尽快准备好要出版的图书,以保证在产品的第一个版本准备好的时候可以让这些书上市。

{%}

图 3-2:在每一轮迭代开始的时候,团队从积压工作表中选择出要开发的功能

通过持续发布、欣然接受变化以及在每一轮迭代结束的时候发布可工作的软件,电子书阅读器项目的第一款成品的发布大大超前于计划。低效的瀑布式流程一旦定义好需求就把开发团队和客户完全隔离开,而敏捷团队采用的方式完全不同,后者始终与客户交互。这样就可以及时响应变化,开发出更好的产品。

但是这个电子书阅读器团队还远没有达到完美。尽管通过迭代的方式交付可工作的软件,但是大家也被文档压得喘不过气来。所有人都真心感到高兴,因为开发的软件不会卖不出去、陷入困境。但是,每当发现项目确实需要修改的时候,都有一半人返回去更新规格说明书,以保证计划保持最新状态,而且自己的工作在正轨上。看上去,他们更新文档花的工夫与写代码花的工夫差不多。

团队里有人开始讨论如何减少维护这些文档所需的工作量。他们针对文档“正确的详细程度”展开了细致的讨论。但是每当他们想要砍掉一些内容的时候,总会有人指出如果不写下某项功能、需求、设计或测试用例,那么就会有人对其产生误解。如果最终的实现不正确,他们就会因此遭到谴责。于是,文档中的任何一部分看上去都是必要的,因为少了任何一部分团队都有可能开发出错误的软件。

有没有办法可以减少这项负担,同时对项目不产生伤害?还有,一个项目到底有没有“正确”的文档详细程度?

要点回顾

  • 敏捷开发宣言随附的 12 条原则让敏捷实践者对实践和方法有了具体的方向和认识。

  • 敏捷团队在项目中尽早地获得客户反馈,并且持续发布根据反馈意见改进的软件,从而让客户满意(原则1)。

  • 敏捷团队把变化看作是项目中正面且健康的发展过程,从而拥抱变化(原则 2)。

  • 通过设置时间范围的迭代来频繁交付可工作的软件,敏捷团队不断地调整项目,从而给客户带来最大价值(原则 3)

3.4 沟通和合作

软件团队自开始开发软件以来就一直在纠结“要写多少文档”的问题。很多团队多年来都在寻找解决流程、编程和交付问题的灵丹妙药。与之类似,这些团队也在寻找让文档系统或模板系统记录当前开发软件所需所有信息的神奇方法,并且让这些信息在未来自动维护。

在传统观念中,人们将软件文档看作一种必需的文档管理系统,大家都可以把已有的信息放到这个系统中,然后将自己的信息与其他所有人的信息整合在一起。如果这个系统具有可跟踪性,可以理清楚所有信息之间的所有关系,那么需要的产品、测试,以及部署和维护方式便一目了然。这里的想法是:开发人员可以从设计中的每一个部分追溯到具体的需求,测试人员可以从每一个测试用例追溯到设计、需求和覆盖范围。每当需要变化的时候,例如需要改变设计中的某个部分,团队就可以准确地看出这样的变更会对哪些代码、需求、范围和测试用例造成影响,因此可以省去很多分析的时间。软件工程师把这个过程称为影响分析(impact analysis)。大家通常都会努力维护详尽的可跟踪性矩阵,通过这些矩阵映射范围、需求、设计和测试中所有元素之间的关系。这样,项目经理就可以通过这个映射将代码、bug 报告、设计元素以及需求追溯到源头。

现在回到之前各个团队纠结的问题:到底应该写多少文档?对于敏捷团队来说,答案是够项目开发用就行。具体要写多少文档取决于团队本身的情况,例如团队自身的沟通能力以及要解决的问题等。考虑一下软件开发团队编写的所有其他类型的文档:冗长的会议记录(可以捕捉每一次会议作出的决策)、交叉引用文档(描述了每一项数据或存储)、复杂矩阵(记录每一位成员具体角色、职责和要遵循的规则)。所有类型的文档都遵循一个原则。如果某种文档不能给团队开发软件带来帮助,而且也没有必须写的原因(例如有监管的要求、投资者的要求、高级经理的要求或其他利益干系人的要求),那么敏捷团队就不写这种文档。但是如果发现编写功能性需求文档真的有帮助,那么敏捷团队就可以编写这种文档,这不影响敏捷性。所有这一切的标准就是适合,这也是敏捷给你带来的自由。

至于超出团队开发软件所需要的文档(全面的文档、可跟踪性矩阵、影响分析),消耗在这里的工作很大程度上支持了完整分析任何变更带来的影响。虽然敏捷开发对变化的管理采取了一种不同的方法(通常高效得多),但是敏捷实践者应该意识到传统的文档编写方法实际上与敏捷方法目标一致。在传统的瀑布式项目中,完整文档的全部意义就在于更好地应对变化。

具有讽刺意义的是,完整的文档往往会给管理变化带来阻碍。完美文档和可跟踪性的美梦拥有这样一种系统:团队可以通过这个系统自动地生成任何需要管理的变化带来的影响,可以准确地定位需要修改的地方。

遗憾的是,对于大部分团队来说,通过详尽文档来管理变化的真实情况不这么美妙。团队在项目开始的时候要花大量的时间努力预测未来会发生什么,并完整地记录下来。项目执行的时候,他们需要不停地维护已经写好的文档,并记录所有新开发的内容。如果对于正在开发的产品有了新的理解,他们还需要返回去修订所有受影响的文档。随着时间的推移,过时的文档会越来越多,团队需要花很大的工夫去维护这些过时的文档。

事实上,完整的文档并不完美,所以会导致不必要的变更并浪费精力。文档中任何一部分都是承担特定职责的个人从自己的角度编写的:业务分析师从一个角度写需求,架构师从另一个角度构建设计,QA 工程师从第三个角度编写测试计划。然后他们还要把这些内容整合在一起成为可跟踪性矩阵,结果发现与引入这些割裂视角的期望完全不一致。构建文档本身也成了一个要实现的目标,要求投入的精力越来越多。当变化终于发生的时候,把所有不同视角整合到一个完整文档所耗费的工作全部都需要重做。结果,团队不停地重写文档、重建可跟踪性矩阵、解决冲突。而这些时间本可以用来编写代码、测试软件、部署变化。

得有一种更有效的软件开发方法才行。

3.4.1 原则4:在团队内外,面对面交谈是最有效、也是最高效的沟通方式

敏捷实践者明白,文档只不过是另外一种沟通的形式 4。写文档交给你的时候,我的目的并不是写文档。目的是确保我脑子里的想法能与你脑子里的想法尽可能地接近。在很多情况下,文档是实现这个目标的好工具,但是文档也不是我们唯一的沟通工具。

4公平地说,传统项目经理也知道文档只不过是另外一种沟通的形式。一般的项目经理都会研究正式沟通与非正式沟通之间的区别,还会研究书面沟通与口头沟通的区别。他们还会研究沟通中的非语言信息,然后发现面对面沟通是最有效的传播思想的方式。其实在 PMP 考试中就有这些内容!

{%}

图 3-3:如果团队中的成员不沟通,他们可能会在粗粒度上保持一致,但是最后却朝着不同的目标前进。详尽的文档容易引入歧义,所以更容易产生这种情形

在软件团队中,面对面沟通方式几乎总是优于文档沟通。大家都知道亲自去与别人讨论问题是理解新想法的最有效方法。相比从一页纸或一份 Microsoft Word 文档上读到的信息,我们更善于记住在交谈中传达的信息。因此,敏捷沟通实践更关注个人与个人的沟通,而文档则用来记录那些以后需要回忆具体细节的复杂信息。

幸运的是,对于习惯复杂文档的团队来说,更高效的面对面沟通方式不难解释。这是因为大部分团队并没有尝试达到完整详细文档可跟踪性的理想情况。软件工程师现实得很。发现建立完整文档需要的工作量很大,他们最终会面对面交谈。最后,这也成为他们高效开发软件的唯一方式。由于意识到完整文档通常是不必要的,因而他们也不会因为没编写完美的完整文档而愧疚,这本就是不可能做到的事。而事实上,即使他们真的写了这些文档,这些文档在项目中也不会太有用。

团队沟通项目重要想法的最有效方法就是让大家的思考方式保持同步。这样的话,每作出一个决策,大家都可以正确应对。如果一个团队的人用同样的方式去看待世界,而且都能开放地讨论正面和负面的想法,那么大家最终会有一致的视角。如果此时发生了一个变化需要重新思考,团队成员不需要花时间互相解释。

团队沟通的终极目标是形成一种集体意识,在成员之间建立不必直说也能领悟的共同知识,因为反反复复解释同样的事情实在太过低效。如果没有集体意识,团队中不同职责的人需要付出更大的努力才能匹配视角。一个团队越能形成集体意识,越能共享同样的视角,就越容易对同样的问题形成一致的答案。这就为团队构筑了处理变化的坚实基础,可以跳过冲突,立即编写代码,而且不会因为维护文档而分心。

3.4.2 原则5:在整个项目过程中,业务人员和开发人员必须每天都在一起工作

敏捷开发团队有时候会忘记业务人员也有自己的日常工作。在这样的情况下,软件开发团队与他们所服务的业务人员自然会脱节。

为了出色地完成软件开发,开发团队需要与业务人员进行大量面对面的讨论。业务人员了解需要什么软件,因为他们在没有软件的情况下开展了同样的工作,而开发团队可以通过讨论了解这些。因此,对于同软件开发团队一同工作的业务人员来说,软件项目通常只是他们自身工作的一小部分。大部分业务人员希望软件开发团队与他们只有很少的接触。他们只想开一两个会,整理出软件需要完成的功能,就盼着不久之后开发团队带着完美的可工作的软件出现。

而软件开发团队这边则希望尽可能多地与业务人员接触。程序员需要了解软件要解决的业务问题。他们了解的方式就是与业务人员交谈,观察他们工作,分析他们的产出。需要这些信息的程序员恨不得每一个业务人员都可以全天候地解答问题。他们等待解答的时间越长,项目进展就越慢。但是业务人员并不想把自己全部时间都放在软件开发团队上,因为他们自己也有工作要做。那么到底听谁的呢?

敏捷团队有一种绕过这些问题,让业务人员和开发人员双赢的方式。他们首先都认识到,团队要给公司开发带来价值的软件。完成后的软件应该值得公司的投入。如果软件带来的价值超过了开发软件的成本,那么公司就值得在这项开发上投入资金。一个好的项目应该有足够的价值让业务人员感觉到值得投入精力。

当业务人员和开发人员同在团队中开发软件的时候,最有效的方法是让他们在项目完整周期内每天坐在一起工作。原因是,如果换一种做法,业务人员就得等到项目后期再来检查开发团队的工作并给出反馈,而项目后期修改的成本要高得多。如果能尽早处理这些变化,那么大家耗费的时间就会少得多。从整个项目的过程来看,每天与开发团队一起工作,每个业务人员的实际时间开销要少得多。

{%}

图 3-4:对于公司来说,积压工作表中的一些特性比其他特性更有价值。开发团队在决定每一轮迭代中开发什么特性的时候应该权衡价值(一项特性价值多少)及其成本(开发这项特性要投入多少)

这也是频繁发布可工作软件的开发团队应该把最有价值的特性优先开发的原因,这样的话,业务人员就可以第一时间享用到这些价值。这也是契约的一部分。这也是为什么好的敏捷团队会把业务人员看作是团队中与程序员同等重要的成员的原因。敏捷团队与传统团队存在这样巨大的差异。传统的开发团队把业务用户看作是要谈判的客户;而敏捷团队则是与客户(通常是产品所有者)合作,在项目执行的时候客户具有平等的发言权。(这就印证了“客户协作高于合同谈判”的敏捷核心价值观!)

好的产品所有者会帮助减少业务人员与开发团队在一起的时间。尽管他们仍然每天都要开会,但是产品所有者可以让这个会议关注软件价值的理解以及软件需要解决的业务问题。通过这种方式,团队可以在与业务人员面对面的沟通中验证他们已经从产品所有者那里了解到的信息。

3.4.3 原则6:以受激励的个体为核心构建项目,为他们提供环境和支持,相信他们可以把工作做好

如果公司里每一位同事都意识到团队开发的软件是有价值的,而且团队中所有人(包括产品所有者)都能理解软件是怎样为公司创造价值的,那么项目就可以以最佳状态运行。

相反,如果团队中的成员看不到软件能带来的价值,或是他们没有因为开发优秀软件而得到奖励,那么在这种环境下,项目会失败。常见的情况是,公司绩效审查机制和补偿制度不利于员工采用高效的敏捷方式开发软件,这些做法对项目无益。这背后的问题往往包括以下几点。

  • 在代码审查中,如果不断发现 bug,程序员就会获得糟糕的评价,如果没有发现 bug,程序员就会获得奖励。(这会导致程序员在代码审查中不愿意找 bug。)

  • 根据发现的 bug 数奖励测试员。(这会导致测试员挑刺并降低报告质量。这种方式给程序员和测试员之间设置了敌对关系,会阻碍测试员和程序员之间的合作。)

  • 根据业务分析员产出的文档量判定其绩效评级(而不是根据他们与团队分享的知识量评级)。

最终,所有人的绩效都应该根据团队交付的成果来评定,而不是根据每个人自己的角色来判定。当然,这并不是向领导汇报的时候不要提工作成绩不好或影响团队正常工作的程序员。人们应该根据对整个团队目标所做出的贡献进行考核。但是,考核的方式绝对不能阻碍大家做出超越自己职责边界的贡献。对于一个团队来说,好的环境会奖励下面几种人:认识到软件并没有解决的某个业务问题并将其修复的程序员,以及能够发现代码或架构中的问题并提交给团队的测试员。这样的环境可以给予每一位成员所需的支持,让项目更为成功。

详尽的文档和可跟踪性矩阵可能给团队环境和支持带来潜在问题。这些工作没有在团队中鼓励信任,反而鼓励一心自保(Cover Your Ass,CYA)的态度,在这样氛围下的团队会倾向于采用“合同谈判”的方式,而不是与客户协作的方式。

带着 CYA 态度工作的测试员会努力确保每一项需求都有测试覆盖,而不去考虑测试到底能不能对软件的质量有帮助。带着 CYA 态度工作的开发人员会严格遵循需求文档中的每一个字,而不去认真想一想自己开发的功能是不是真正能给用户带来价值。因为在这种氛围中工作,如果按照用户真正需要的方式进行开发,你可能会被指责不遵守需求规格说明书。业务分析员和产品所有者保护自己的方式就是花时间确保项目范围和需求能整齐地排列在一起。这样的话,他们往往会倾向于忽略一些无法与现有文档保持一致的讨厌需求,而不管这些需求本身的价值。

在把变化看作是坏事的环境中,软件开发团队的成员需要通过 CYA 的态度来保护自己。例如,使用详尽文档的团队很容易排斥变化,因为重新定义项目范围并修改规格说明书、设计、可跟踪性矩阵等工作需要耗费大量的精力。这容易产生内部矛盾,因为在这样的公司中,经理自然会想找一个“始作俑者”为那些因为变化而产生的额外工作负责。当这种责备不可避免时,团队中的成员会逐渐转向编写“防御性文档”以保护自己。这种氛围迫使团队中的每个人都变得 CYA。为了避免糟糕的绩效考核或惩罚,他们可以把责任撇向他们所遵循的那部分文档。

CYA 是信任的对立面。如果做项目的时候只需要编写所需的最少文档,那么公司的氛围就给了团队信任,相信团队在发生变化的时候可以做出正确的事情。在持有同甘共苦态度的敏捷团队中,如果项目失败了,那么大家都需要承担后果。这种团队中不需要 CYA。这样更容易处理变化,因为不需要维护任何不必要的文档。成员可以通过面对面的沟通解决实际问题,仅仅记录下真正必要的内容。他们可以这么做的原因就在于他们知道公司信任他们,即使项目可能耗时超出预期。

3.4.4 在电子书阅读器项目中采用更好的沟通方式

更好的沟通方式一定会让电子书阅读器项目受益。还记不记得那段会议密集的日子?业务分析师仔细地把一大堆详尽的需求整合在一起。这些需求一开始并没有形成万恶的 CYA 氛围。整个团队刚开始真的认为花时间把软件中的每一部分细节都理清楚就可以完整覆盖软件的需求,并且可以开发出最好的产品。他们在一开始的时候就已经把这部分时间用光了,所以在开发的过程中会坚守原始的需求文档,即使发现最终开发出来的产品可能并不适合市场。假使他们当时真的有能力精准地预测两年后市场的需求,那么他们应该能完美地开发出产品。很遗憾,事情发展到最后并没有像当初设想的那样。不过至少没有人被开除,因为大家都可以把矛头指向他们仔细遵循的那份规格说明书。

如果团队一开始就实施更好的沟通方式会怎么样呢?如果团队并不编写完整的需求文档,而只是记录启动项目所需的最少文档,那么产品最终会怎么样呢?

{%}

图 3-5:如果团队更多地依赖面对面的沟通,并且使用项目开发所需的最少文档,那么大家就可以更容易地保持状态同步

在整个过程中,大家都要信任其他人可以作出正确的决定。这种做法对于开发电子书格式特别有帮助,因为大家不用绑定在项目刚开始时确定的那种过时格式上,而是可以采用新格式。更好的是,当大家开始开发网络书店的时候,可能会发现这显然不是一个好的想法,废弃这个功能即可。然而,如果列在规格说明书中,这项功能就不可能去掉了。更好的沟通方式会促使项目一直符合最新的需求,从而交付更有价值的产品。

想象一下这对于电子书团队来说有什么不一样。文档负担减少,团队的这部分工作变得轻松。大家发现,更好的沟通方式和文档减负节省了大量时间。但是,如果他们这么做了,而项目仍然不在正轨上,这会是怎么回事?

因为种种原因,他们并没有真正节省这些时间。看上去他们在晚上和周末的加班比以前还多了,因为他们试图在每一轮时间受限的迭代中实现产品所有者承诺的所有功能。似乎他们越敏捷,要做的工作也越多,因为夜晚和周末加班而不能陪家人的时间也越来越多了。这可不是改进!在团队彻底崩溃之前,有没有办法可以阻止这个趋势?

要点回顾

  • 过于详尽的文档会增加需求含糊以及团队成员之间误解和沟通不畅的风险。

  • 敏捷团队最有效的沟通方式是面对面交谈,并且只依赖项目所需的最少文档(原则 4)。

  • 开发人员每天与业务用户一起工作,这样他们可以交付最大的价值(原则 5)。

  • 敏捷团队中的每一位成员都对项目有责任感,并且为项目的成功与否负责(原则 6)。

3.5 项目实施——推进项目

有了更好的沟通方式,团队成员相互信任,这是一个非常好的开端。一旦成员相处良好并认准自己在项目中的定位,他们就可以开始解决最重大的问题,在日常工作中做出实事。敏捷团队是怎样推进项目的?

3.5.1 原则7:可工作的软件是衡量进度的首要标准

好的团队合作会确保所有人(包括团队成员、经理、利益干系人以及客户)在任何时刻都了解项目的进展。问题是怎样正确地沟通项目状态——这个问题远比看上去的要复杂得多。

典型的“命令 - 控制”式项目经理会努力地通过详尽的进度安排来保证项目的进度,并通过状态汇报来更新所有项目成员的最新状态。但是状态汇报很难获得项目的真正状态。汇报本身就是一种不完美的沟通工具:也许有三个人读的是完全相同的状态汇报,但他们往往对项目进度持有完全不同的理解。此外,对于项目经理来说,状态汇报也会有极强的政治色彩。几乎所有的项目经理都有过这样的巨大压力:有时候需要在状态报告中略去一些会让经理和团队主管难堪的东西,而别人常常需要用这些信息进行决策。如果状态报告并不够好,进度该怎样汇报呢?

答案就在可工作的软件中。只要真切地看到了软件在眼前工作,那么你就“得到了”项目的进展。你可以看到软件实现了什么,以及没有实现什么。如果经理承诺了要交付的功能没有在软件中,那会很难堪,但是又不可能不去沟通这个问题,因为软件本身就足以说明问题。

{%}

图 3-6:可工作的软件可以更好地给所有人汇报项目最新进展,因为这是团队用来交流当前已经完成工作的最好方式

敏捷团队使用迭代式开发有这样一个理由:在每一轮迭代结束的时候交付可工作的软件,通过真实的产品向大家展示具体成果,团队可以让大家掌握项目进展的最新情况,而且这种方式几乎不可能会让人产生误解。

3.5.2 原则8:敏捷过程倡导可持续开发。赞助商、开发人员和用户要能够共同、长期维持其步调,稳定向前

有很多团队都和电子书阅读器团队一样,疯狂加班,追赶不切实际的截止时间。实际上,硬性的截止时间是命令 - 控制式项目经理采用的主要工具。每当截止时间快要到来的时候,大家的首要选择都是在晚上和周末加班。不切实际的截止时间是一种榨取团队每周额外工作时间的阴险手段。

从长远来看,这种做法是不可靠的。众所周知,一个团队可以拼命工作几个星期干更多的活,但是团队的工作效率一般都会在这段时间过后一落千丈。这是有道理的:人们都会感到疲劳并且失去动力。为了加班,他们推掉了很多重要的公事和私事,然而最终这些事情总是会重新找上门来的。实际上,那些严重加班的团队不会比正常工作的团队交付更多实质工作,而且往往工作质量更糟。

因此,敏捷团队信奉的是维持可持续的开发节奏(sustainable pace)。他们会针对预留的时间制订切实可完成的计划。通过迭代式的开发,这种计划的可行性很高,因为预估接下来两周、四周或六周的工作量远比预估未来一年半的工作量要简单得多。因为只承诺交付能开发的内容,所以团队不会动不动就加班到深夜或周末。5

5这是针对第 1 章讲述的关于“简化”的好例子。此刻,我们只需要告诉你,“可持续的开发节奏”指的就是给予团队足够的开发时间,让成员不需要工作到深夜,也不需要周末加班。本书之后还会进一步深入细节,讨论可持续的开发节奏会对团队的工作环境、公司文化、软件质量产生什么样的影响。

3.5.3 原则9:坚持不懈地追求技术卓越和设计优越,以此增强敏捷的能力

糟糕的预估并不是导致深夜和周末加班的唯一原因。大部分开发人员都经历过这样的事情,一个功能看上去只需要简单编写一点代码,到后面你才发现这实现起来很艰难。这种痛苦郁闷的经历让人耿耿于怀。本来接下来的三个星期可以干别的事情,结果却要用来跟踪各种 bug,给代码打补丁。

从长远来看,避免 bug 比过后修复 bug 要快得多。设计良好的代码维护起来也要简单得多,因为其开发方式易于扩展。

过去二十几年,软件设计领域发生了一次变革。面向对象设计和分析、设计模式、解耦及面向服务的架构等软件设计领域的创新带来了很多模式和工具,让开发人员可以在每一个项目中开发技术优异的软件。

但是这并不意味着敏捷团队在每一个软件项目开始的时候要花大量时间进行大规模的设计。敏捷开发人员会培养起非常好的编程习惯,从而帮助自己编写设计良好的代码。他们不停地寻找设计和代码的问题,一旦发现问题,立即将其修复。在项目的开发过程中,只需要在当下多花那么一点点时间编写可靠的代码并及时修复问题,那么留下的这份代码库在未来就会非常好维护。

3.5.4 改善电子书阅读器团队的工作环境

前面提到的电子书团队成员和家人一定会很喜欢可持续的开发节奏。此外,项目本身也可以进展得更好。这个团队注定从项目一开始就要忍受加班,因为不可能有任何工具制订一年半之后依然精准的计划。

更惨的是,团队的软件设计和架构设计依据都是项目伊始时制订的详尽规格说明书,所以最后出来的代码非常复杂,难以扩展。结果,项目过程中很多小修改都需要打大补丁,代码库中留下了大量的意大利面条式代码。如果团队采用迭代式开发方法,不断交付可工作的软件,那么大家就可以对每一轮迭代制订计划,从而保持一个可持续的开发节奏。通过更简单、更适时的方法设计出来的架构更灵活更可扩展。如果团队使用了更好的设计、架构和编码实践,那么就可以开发出更易维护和扩展的代码。

想象一下,假设采用了这些新的原则,现在电子书阅读器团队就会像一台运转良好的软件生产机器。他们定期地迭代并发布可工作的软件,同时不断地调整方向以确保总是在开发最有价值的软件。他们之间沟通良好,只编写需要的文档。他们用的是很棒的设计实践,开发出了可维护的代码库。而且他们并没有为了做到这些而加班工作。这个团队已经迈入敏捷了!

但是这时下一个项目的阴影已经升起。新的项目经理刚刚给他能找到的所有人发送了大型会议通知。参会者接到消息,相关人等开始订会议室,人们热火朝天地讨论所有需要记录文档的需求。我们刚形成的敏捷团队又开始“心口痛”了。

他们知道马上要发生什么了。大量的需求规范、计划和甘特图会在初期涌现。他们怎样才能保证下一个项目不会掉进前一个项目的坑?他们好不容易才爬出来的。

要点回顾

  • 沟通项目进度最有效的方法就是把可工作的软件交付到用户手中(原则 7)。

  • 保持团队最高生产效率的方法就是:保持可持续的开发节奏,不要逞强,不要匆忙赶工,避免加班(原则 8)。

  • 设计良好并很好实现的软件可以最快交付,因为这种软件修改起来很容易(原则 9)。

3.6 项目和团队的持续改进

KISS(Keep It Simple, Stupid,保持简单)是一项不仅应用于软件开发,也应用于其他所有工程实践中的最基本的设计原则。敏捷团队在项目规划、软件开发以及团队运营的过程中都会遵守这项原则。

3.6.1 原则10:简单是尽最大可能减少不必要工作的艺术,是敏捷的根本

在已有项目中添加代码会让项目变得更复杂,如果还继续添加更多依赖这些代码的代码,项目会变得尤为复杂。系统、对象和服务间的依赖使得变化成为一件困难的事情,因为有了依赖关系,变化导致系统另一部分发生变化的可能性会提升,后面还有可能导致第三个变化。每一个变化都会形成多米诺骨牌效应。采用迭代式开发以及在项目初期将文档量控制到最小,可以帮助你的团队避免交付不必要的软件。

然而,很多开发人员第一次听到诸如“采用迭代式开发”和“以所需的最少计划启动项目”这一类说法时会有一点不适应。他们觉得,如果没有大量的设计和架构决策及其文档化,那么编写项目代码会显得太早,因为如果现在就开始编写代码,那么以后设计变化的时候他们就要删除现在写的这些代码。

这种反应是可以理解的。在软件开发领域之外的其他工程项目中,这种做法并不合情理。比如说,新接触敏捷开发的程序员很有可能会抛出这样的反对意见:“如果让承包商来帮我翻新房屋,我希望可以事先看到完整的蓝图。我不希望他简单跟我聊聊就开始砸我家的墙。”

房屋翻新项目确实不能这样。因为要做的事情是改变一栋房屋,最具破坏性的操作就是拿大锤子砸墙。但是软件与房屋以及其他物理实体之间是有差异的。在软件项目中,最有破坏性的事情就是编写代码,然后编写更多依赖这些代码的新代码,再然后再编写更多进一步依赖的最新代码。代码的连锁变化会产生可怕的多米诺效应,最终出现一大堆无法维护的意大利面条式代码。

把待定的工作最大化可以避免这种困境,而最好的实现方式就是开发没有太多依赖和不必要代码的系统。而要实现这个目标最有效的方式就是与你的客户以及利益干系人在一起工作,确保只开发最有用且最有价值的软件。如果某一项特性没有价值,那么对于公司来说,更节省成本的方法就是根本不要开发这项特性。为维护这些代码而产生的成本往往比这项特性给公司带来的实际价值要高。编写代码的时候,如果团队可以基于一些只实现单一功能的小型自包含的单元(例如类、模块和服务等)进行设计,那么这个团队就可以避免多米诺骨牌效应。6

6本章在这里又简化了,没有深入进去。我们之后会更详细地讨论团队怎样在项目初期不做大量设计的情况下开发优秀的代码,讨论这种做法对项目的影响,以及如何包容项目未来的变化。

3.6.2 原则11:最好的架构、需求和设计来自自组织的团队

有大量事前设计的团队非常容易做出过于复杂的设计。想来这并不令人意外。让我们再看一下第 2 章展示的瀑布式流程的示意图,其中有一个完整的阶段是专门用来做需求的,还有一个阶段用来做设计和架构。在设计和架构阶段尽全力就必定意味着要构建可以做到的最棒的架构。对于采用这种方式工作的团队来说,如果提出的需求较少而且设计太简单,那么从直觉上会给人一种偷工减料的感觉。要是他们拿出一份巨大的需求文档和一个复杂的设计,那还会有人质疑吗?当然不会。在流程中有整块整块的阶段让他们做这些事情,意味着人们明确地要求他们这么做。

自组织的团队(self-organizing team)并没有明确的需求和设计环节。自组织团队会用合作的方式对项目进行规划(而不是依赖某个“负责”计划的人),而且会持续地作为一个团队改进计划。采用这种工作方式的团队通常会把项目分解为多个用户故事或其他类型的小块,从能够给公司带来最大价值的块着手,然后再考虑详细的需求、设计和架构。

这种做法使得传统软件架构师的工作更为困难,但是产生的结果却更令人满意。传统的软件架构师坐在一间办公室里抽象地思考要解决的问题。尽管现在很多架构师明显不是这么工作的,但是或多或少与团队日常工作脱节的架构师并不少见。

在敏捷团队中,所有人都对架构负有责任。尽管高级软件架构师和设计师仍然很重要,但是他不再孤立工作。实际上,如果团队从最重要的分块开始逐块构建软件,那么架构师的工作会更有挑战性(而且也更有意思)。敏捷团队不会在一开始就创建一个覆盖所有需求的大设计,而是采用增量式的设计,这就要求设计的系统不仅完整,而且还在项目变化的时候方便团队修改。

3.6.3 原则12:团队定期反思如何提升效率,并依此调整

如果不能持续地改进构建软件的方式,那么团队就不算敏捷。敏捷团队会不断地检查并调整,成员会检查自己项目运转的方式,并通过检查的结果对未来进行改进。而且,他们不只是在项目结束的时候这么做。他们会每天开会寻找需要改变的地方,如果有道理,就会改变当前的工作方式 7。你需要适应的一点是:对于你自己以及你团队中的其他同事,你必须非常诚实,让大家知道哪些事情可行,哪些不可行。对于刚刚迈上敏捷开发道路的团队来说,这一点尤其重要。增强团队实力的唯一方法就是经常回顾自己已经做的事情,然后评估作为一个团队这些事情做得怎么样,最后提出能改进的计划。

7这里又是一个简化。目前,我们只需要了解敏捷团队会自查和改进即可。第 4 章我们会学习 Scrum 团队如何具体做这件事情,以及这件事情和自组织的团队有什么关系。

这是有道理的,而且几乎所有人都同意这件事情有意义。回顾过去,清点哪些事情做对了,哪些事情做错了,这确实是很多团队真心想做的事情,但是很少落实。原因之一就是,这一开始并不让人感到舒服。这需要揪出具体的问题和错误,而很少有人会对公然指出其他人的错误感到自在。随着时间的推移,团队中的成员会对这件事情感到越来越自然。最终,大家会认为这是提意见而不是挑刺。

很多团队不反省的另一个原因是没时间。即使找到了时间,人们也常常觉得投入下一个项目比思考已经完成的事情要更重要。如果在开始每一个项目的时候,给每一轮迭代以及每一个项目的收尾阶段预留了开会时间,总结并评估已经完成的事情,而且制订出改进计划,那么团队更有可能真正地坐在一起讨论他们已经完成的事情。这样可以从经验中吸取教训,提高效率。

要点回顾

  • 敏捷团队避免开发不必要的特性以及过于复杂的软件,保证给出的解决方案尽可能简单(原则 10)。

  • 自组织的团队对项目的所有方面都负有共同的责任:从产品构思到项目管理到项目的设计和实现(原则 11)。

  • 敏捷团队在每一轮迭代结束的时候和项目结束的时候会花时间总结过去,讨论总结经验,提高开发软件的能力(原则 12)

3.7 敏捷项目:整合所有原则

敏捷开发在软件工程的历史上是独一无二的。敏捷开发与多年来“银弹”方法的浪潮不同,后者承诺通过神奇实践、高级软件工具,以及昂贵的咨询费用解决软件团队中的问题。

收获“聊胜于无”结果的团队和通过敏捷开发享受到更多好处的团队有一个区别:后者意识到不能像点菜一样选择敏捷实践。组合使用这些实践的关键在于团队的思维方式,敏捷价值观和原则是思维背后的动力。

敏捷的独特之处在于从价值观和原则出发。敏捷团队不仅要诚实地回顾开发软件的方式,还要回顾成员交流的方式,以及与公司其他同事交流的方式。首先要理解原则,然后再采用方法,要完整理解其工作原理,还要在过程中不断地评估和改进。敏捷团队可以真正找到改进项目运行的方法,增强敏捷性,开发并交付更好的软件。

常见问题

我是一名“明星”开发人员,我只想让其他人都不要打扰我,这样我就可以开发出伟大的软件!我为什么还要考虑任务板或燃尽图这样的东西?

 所有优秀开发人员都遇到过这种沮丧的事情:本来开发了一段很棒的代码,结果某个根本不知道怎么编程的家伙要求做出一个修改,你就不得不把这段代码弄乱然后打上补丁。对于非常在乎程序设计技艺的人来说,如果一些非开发人员故意等项目做到一半才想明白到底需要什么,那么进行的技术妥协(而不是一开始就编写正确的代码)就是不必要而令人沮丧的。

 这也是很多伟大开发人员被敏捷团队吸引的原因。没错,敏捷开发要求你关心计划,习惯使用诸如任务板和燃尽图之类的计划工具。敏捷方法构筑的根基在于这些与计划相关的实践,而且这些实践是专门挑选出来的,已经简化到了最极致,并且足够满足高效计划和运行项目的需求。计划项目的最大好处就是可以在规划期过问棘手问题,防止收尾时进行变更。因为高效的敏捷团队从项目一开始就在不停地与用户沟通,所以可以做到这一点。很多优秀的开发人员都会赞同在一开始做计划的时候问用户一些棘手的问题,而这些问题如果不问的话可能会在项目后期引发变化。避免最后才出现的需求变更,避免打乱已经编写好的代码打补丁,这也是敏捷开发很好的卖点。

 敏捷计划还意味着与团队其他成员沟通,这种沟通可以真正帮助伟大的开发人员进步。“明星”开发人员从不停止学习,但是在命令 - 控制式的团队中,明星开发人员与团队的其他成员隔离开了,他们的大部分学习都是自我主导的。而在自组织的团队中,开发人员之间会进行大量的沟通,这种沟通指的并不是被迫参加无穷无尽的无用状态汇报会。团队成员自己决定为使项目正常运转而沟通的内容。这样不仅可以做出更好的项目,还意味着你可以向坐在身边的开发人员取长补短。比如说,坐在身边的同事要在工作中采用一种你之前没有见过的新设计模式,那么在项目结束的时候,你就会了解到这个新设计模式好不好。如果好,你就可以把这个新技术添加到自己的工具箱中。这种学习过程是自动发生的,你不需要费额外的力气,因为整个团队都在高效地沟通。这也是接纳敏捷的开发人员往往发现自己技术更强的原因之一,他们感觉自己的编程技艺在不断地进步。

我是一名项目经理,我现在还不清楚我可以怎样融入一个敏捷团队。我在这里面的职责应该是怎样的?

 如果你是一名项目经理,那么你的职责可能属于以下三种传统的项目管理职责之一。

  • 一名杂事缠身的计划者:需要预估并指定项目进度,还要指导团队的日常工作。

  • 一名产品专家,可能承担了业务分析师的职责,需要确定需求、与团队沟通需求并确保团队开发出满足需求的软件。

  • 与高级经理以及与公司高层管理人员一起工作的主管,需要向他们汇报公司在项目上的投资正在产生价值。

 在第 4 章中,你会进一步学习一项最常见的敏捷技术:Scrum,还会学习 Scrum 团队中的各种职责。如果你是一名会深入团队细节的实干型项目经理,那么你就很适合去做 Scrum 主管。Scrum 主管的工作是帮助团队制订计划,并且在整个项目的过程中帮助团队成员排除影响进度的困难,让团队最终能交付软件。换一个角度,如果你的工作是理解公司的需求并负责向团队沟通需求,那么你更有可能成为产品所有者。在这种情况下,你要负责管理积压工作表,决定进入每一轮迭代的特性,并且在整个项目的过程中负责回答团队提出的细节问题,确保团队可以保持在正轨上,开发出正确的软件。

 如果你是一名负责管理的项目经理,那么你带领的团队很有可能不敏捷,不过也没关系。你反而会要承担一名敏捷战士的最重要职责,在你的团队和经理中推行敏捷实践和敏捷价值观。如果有一些分解为多轮迭代的特性积压工作表,并且掌握了本轮迭代相关细节,你会发现你恰好掌握了向高层管理人员和高级经理汇报所需的具体信息。越清楚进展以及目标完成程度,你就越了解项目的真实进度。但是为了真正做到这一点,你还需要熟悉敏捷团队的工作方式和交流方式,让团队和领导层之间沟通顺畅。

稍等一下。如果整个团队在一起做计划,那么这是不是说没有人负责这件事情?这看上去很不实际。决策是怎样作出的呢?

 这取决于要做什么决策。解决冲突的方法应该是不变的。考虑一下你现在所在的团队,或回想一下你之前所在的团队。谁在负责?谁负责解决团队成员不能解决的争辩和分歧?谁考核你的绩效?公司的层次结构有很多种,而敏捷团队可以在任何层次结构下工作。然而,敏捷团队更擅长自己解决冲突,因为关注沟通,而且其目标比其他类型的团队更容易达到一致。

 如果你问的是哪些特性会进入软件,或者通过哪些方法来开发这些特性,那么这些事情是敏捷团队中特定角色负责决策的。在 Scrum 团队中,产品所有者负责决定软件中需要实现哪些特性。然而,团队只需要接受那些依据真实信息估算可以塞进一轮迭代的特性。第 4 章会进一步讨论如何计划。对于敏捷团队来说,计划是属于整个团队的,因为这种团队是自组织的。

 但是,计划属于整个团队并不意味着团队群龙无首,负责人还是有的。如果你们刚刚开始步入敏捷,你一年后的老大很可能就是你现在的老大,区别在于,你的老大会对敏捷足够信任,从而让团队拥有项目决策权,而且会支持团队的决定,而不会事事插手或猜疑。这也是敏捷在真实世界中可以行得通的唯一方式。

现在就可以做的事

下面是你现在就可以自己或与团队一起尝试做的事情。

  • 如果你现在正在开发一个项目,那么在开始编写代码之前首先与团队坐在一起,花 15 分钟讨论一下你们正在开发的特性。你能不能发现对于同一项特性的分歧?

  • 列出你现在正在开发的特性。尝试通过价值和开发难度的维度组织这些特性。

  • 花几分钟列出你和你的团队会创建和使用的所有文档。看看能不能找出一些团队开发代码实际上并不需要的文档?

  • 下一次加班到很晚的时候,思考一下加班的原因是什么。能不能想出一些做法,让你和你的团队避免加班?截止时间是不是太勉强了?是不是在最后一刻加进了额外的工作?首先要明白加班是有问题的,然后花时间去了解导致加班的原因是什么,这是解决问题的第一个步骤。

更多学习资源

下面是与本章讨论的思想相关的深入学习资源。

  • 《敏捷软件开发(原书第 2 版)》,Alistair Cockburn 著:进一步了解敏捷开发宣言的价值观和原则,以及宣言创建的过程。

  • 《敏捷项目管理(第 2 版)》,Jim Highsmith 著:进一步了解敏捷项目管理的价值观、迭代和其他方面。

  • Succeeding with Agile,Mike Cohn 著:进一步了解团队在步入敏捷时会遇到的困难以及克服这些困难的方法。

  • 《如何构建敏捷项目管理团队:ScrumMaster、敏捷教练与项目经理的实用指南》,Lyssa Adkins 著:进一步了解如何避免命令 - 控制式思维方式。

教练技巧

下面是帮助团队理解本章思想的敏捷教练技巧。

  • 帮助团队意识到超长时间的工作并不能带来更多的代码。实际上这样开发的代码量会更少,而且质量也会受影响。

  • 与团队成员单独坐在一起讨论工作。哪些事情激励了成员?哪些事情让他们感到沮丧?他们作出决策的依据是什么?

  • 让每一位团队成员选出对自已影响最大的三条敏捷原则,既可以是正面影响也可以是负面影响。人们会很惊讶地发现在团队中的其他同事选了不同的原则。这有助于帮助大家找到共同点。

  • 以大家共有的原则作为起点,找到最适合团队思维方式的一组实践。

目录