敏捷宣言阐述了一种价值观和指导原则,“敏捷”不是一种开发流程和方法,在中文中,“敏捷”是形容词,不是名词。敏捷开发方法是指“敏捷的开发方法”,而不是指“敏捷这种开发方法”,因此我们可以说Be agile,而不能说Do agile。凡是符合敏捷价值观和原则的开发方法都可以说是敏捷开发方法,例如Scrum、XP、RUP(Rational Unified Process)、Crystal、DSDM等,目前比较流行的是Scrum和XP的组合。迭代、拥抱变化、以人为本是敏捷方法的核心思想,与计划驱动、文档驱动的开发实践不同,敏捷强调灵活应对变化和自适应的计划(敏捷并不是不做项目计划,而是分散到每一个迭代中,更频繁的做计划)。

敏捷开发方法是由一些敏捷开发实践所组成的,其中Scrum主要有6个实践,XP主要有14个实践,RUP主要有6个实践。下面介绍一些主要的敏捷实践,略去了其原始来自于哪个敏捷方法。

1.   自我组织和自我管理的团队(Self-organizing Team

这是Scrum开发方法的核心实践之一:团队被赋予足够的权力和资源,由团队自己决定自己的工作方式。团队没有经理,只有一个Scrum Master,类似于流程教练,对团队遇到的问题进行指导。每一个工作日,在同样的时间和地点,团队成员围成一圈举行一个15分钟的短会。Scrum Master充当了防火墙的角色,确保团队不会因为其他外部的工作请求而中断现有工作。Scrum这个词来源于英式橄榄球(两队并列争球称为Scrum),在比赛中每个队员都应该时刻保持对场上全局的判断,然后集体行动,奋力实现同一目标——胜利。球队比赛的时候,教练和投资方只能在场外,场上的局势由球队集体把握。(我们现在的管理方式还是命令式管理)

Scrum中团队的组织是基于特性的,是跨功能模块和角色的编队(需求、设计、开发、测试、组件等,特性关联到的模块和角色都有参与),每组5~9个人,对于大的团队,相关的特性可以归到一个特性域。之所以这样编队,是为了使工作聚焦客户和真正的价值,因为特性是基于客户的角度来定义的,客户看不到内部的模块、组件、平台、数据库、前台、后台等。(我们研发人员出差解决问题,经验不丰富的员工就会不经意的说:我是负责客户端的,这个问题是服务器端的问题,得找另外部门解决,这就是按功能模块编队导致的结果)

2.   迭代(或者短周期交付)

所有敏捷方法都强调了短周期交付,采用迭代生命周期模型快速交付可以工作的软件。在Scrum中每个迭代称为一个Sprint(英语为快跑、冲刺的意思),Scrum是30天一个迭代周期,而XP更短,2周到4周。现代IID方法都强烈推荐固定时间箱(time-boxing)的迭代,当然也有固定范围的迭代(scope-boxing)。每次迭代都是一个mini项目,包含了需求、设计、编码、测试等大多数规程(discipline)工作,但在不同阶段,不同规程的工作重点是不同的。迭代不是小瀑布的迭加,所有工作都是并行开展的。如图1是RUP(Rational的迭代开发方法)中的迭代生命周期模型图。RUP将软件生命周期分成4个阶段,分别是初始阶段(Inception)、细化阶段(Elaboration)、构造阶段(Construction)和交付阶段(Transition),每个阶段都由若干迭代组成;另外RUP将规程(Discipline)分成9个工作流,分别是商业建模(Business Modeling)、需求(Requirements)、分析和设计(Analysis & Design)、实现(Implementation)、测试(Test)、部署(Deployment)、配置和变更管理(Configuration & Change Management)、项目管理(Project Management)、环境(Environment)。从图中看出,每个迭代中包含了各类规程的工作,只不过不同阶段,工作重点不一样。如前期的迭代中,需求分析的比重大一些,而开发/实现的比重就要小一些。

 微信图片_20250808093040

图1 RUP迭代生命周期模型

3.   持续集成(Continuous Integration

持续集成是一种软件开发实践,即团队的成员经常集成他们的工作,通常每个成员每天至少集成一次——这导致每天发生多次集成。每次集成都通过自动化的构建(包括测试)来验证,从而尽快地检测出集成错误。许多团队发现这个过程会大大减少集成问题,让团队能够更快地开发内聚的软件。持续集成不是“每日构建”,而是针对每次变更都要进行一次构建。构建包括编译、测试、代码审查和部署软件等工作。一旦构建失败,持续集成工具会通过声音、图像等形式进行告警,团队应该将构建失败的问题作为最高优先级的问题进行处理。通过“早集成、常集成”的策略,缩短缺陷引入和缺陷发现之间的时间,提高开发效率,降低开发风险。

4.   结对编程(Pair Programming

两个人共同坐在同一台计算机前进行编码,一人编码,一人审核,随时交换角色。结对可以根据一定的规则进行调整,如每个迭代更换一次,甚至每天更换一次。这种方式加强了代码审核,降低了缺陷引入的概率,并使经验在团队中快速传播,从而提高了整个团队的工作效率。结对编程实践来源于XP极限编程,极限的含义就是如果你认为某个实践是好的,那么就将他做到极致。结对编程就是如果你认为Review是好的,就将Review做到极致。

5.   测试驱动开发(TDDTest-Driven Development

是测试先行开发(Test-First Development)的子实践,是XP的关键实践之一。TDD要求对于大多数代码都要编写单元测试,并且开发过程是测试驱动的,也就是测试用例是先于代码开发出来,是从测试到编码的开发过程,而不是从编码到测试的开发过程。其本质是将瀑布开发模式下详细设计、编码和单元测试三个阶段融为一体。测试只是简单的通过和失败,没有必要人为检查具体的测试结果,如2000个单元测试用例都通过了吗?TDD的好处在于:目标明确避免过度设计;发现更多的Bug,质量更好;测试网保护,开发更有信心;形成良性循环,测试越多,质量越好,质量越好,压力变小,压力变小,就越愿意做更多测试。而传统的开发方法,在时间和进度压力下,往往削剪测试时间,把问题留到后面解决。TDD改变了编码人员的习惯和思维模式,使得编码人员更容易编写可测试的代码、松耦合的代码。

6.   频繁重构(Refactoring

重构是一种对软件内部结构的改善,目的是在不改变软件可见行为的情况下,使其更易理解,修改成本更低。Martin Fowler在《重构改善既有代码的设计》(重构的开创性著做)中写到:Any fool can write code that a computer can understand,Good programmers write code that humans can understand。频繁重构的实践是“持续设计改进(Continuous Design Improvement)”的实践,目的是产生最小的、简单的、易于理解的代码。频繁重构是对敏捷开发原则9的支撑:不断地关注优秀的技能和好的设计可以增强敏捷的能力。

7.   用户故事(User Story

为做好项目计划,我们需要知道客户的需求。传统的方法详细的描述客户的需求,而敏捷方法认为这是一种浪费。我们只需要知道需求是需要细化的,并且知道如何细化需求就可以了。需求是会发生变化的,过早的定义详细的需求会导致变更和浪费。“用户故事”就是一种从用户的角度出发,通过特征来描述需求的方法,用户故事不同于用例(Case),它不是为了细化需求,而是作为一个沟通的提示。

8.   集体所有权(Collective Ownership

结对编程中的两个人一起check out代码,编码和check in。这样就没有程序员个人对任何具体的代码和技术负责,大家一起对GUI负责,对中间件负责,对数据库负责。敏捷实践鼓励一人多能,不受专业的限制,如果想做其他模块,只要申请就可以了。敏捷实践并不是拒绝专家的诞生,如果你喜欢GUI,就多做一些这方面的工作,但必须也要参与开发后台或者数据库的模块。敏捷实践是基于特性组建团队的,而不是功能模块。一个特性涉及到的所有模块,团队成员都必须有能力修改。

限于篇幅,其他敏捷实践如简单设计(Simple Design)、可持续的开发速度(Sustainable Pace)、系统隐喻(Metaphor)、完整团队(Whole Team)、开放办公空间(Open Workspace)、回顾会议(Retrospective Meeting)等不再详细阐述。

需要说明的是:这些实践之间是有关联关系的,不能断章取义,只取一个。我们需要理解其核心的价值观和内涵,然后根据实际情况选择(Adopt)部分实践、根据实际情况进行适配(Adapt)。