本章主要知识点
❑ 常见的软件过程模型有哪几种?各自有什么优缺点?
❑ 敏捷过程的价值和准则是什么?Scrum和Kanban过程各有什么特点?
❑ 什么是DevOps?什么是持续集成和持续部署?
随着软件开发复杂度和规模的不断增加,仅仅依靠个人的技能、依靠编程和测试已远远不能满足需要。在过去几十年中,人们已逐渐认识到,软件过程是软件产品成本、进度和质量的主要决定因素,是建造高质量软件需要完成的任务框架。本章将详细介绍软件过程的概念、常见的软件过程模型、敏捷过程和DevOps,以及软件过程的选择、裁剪、评估和改进。
每个人都知道主动积极的优质软件工程师的重要性,但是如果不理解软件过程,或者软件过程不是在最佳实践下进行,即使是技术精英也无法达到最佳的工作状态。过程是将人、技术、管理结合在一起的凝聚力,是产品成本、进度和质量的主要决定因素。
1984年10月,第一届国际软件过程会议召开,会议提出“软件过程”这个新概念,这标志着软件工程进入了软件过程时期。所谓软件过程(software process),也称为软件生存周期过程,是指软件生存周期中软件定义、开发和维护的一系列相关过程,它定义什么时候做什么、如何做、由谁来做、产生什么制品(artifact)。一个过程由多个彼此相关的活动组成,活动可细分为任务,任务把输入制品加工成输出制品。活动通过人工或自动的手段来执行,可以是顺序的、迭代的(重复的)、并行的、嵌套的,或者是有条件地引发的。通过软件过程,可以规范软件开发与维护的流程,不断地引入软件开发与维护的最佳实践,持续地进行改进,使得软件项目的成功是可以重复的,确保明天的实践比今天更好。
ISO/IEC 12207《系统和软件工程:软件生存周期过程》标准(System and Software Engineering-Software Life Cycle Processes)将软件过程进行了系统的分类,并定义了每个软件过程的活动,以指导所有参与软件项目的人员(供应商、集成商、开发人员、操作人员、维护人员、管理人员、用户以及支持人员)在软件开发、运作、维护中更好地协同工作。ISO/IEC 12207认为,软件是系统的一部分,软件需求从系统需求和设计中导出,开发后的软件最终集成到系统中,软件过程和系统过程紧密相关。软件生存周期过程分为四大过程组,如图2-1所示。
图2-1 ISO/IEC 12207软件生存周期过程
协议过程组定义了软件系统的需方和供方在获取或提供满足需求的软件产品或服务时所需要进行的活动,它包括获取过程和供应过程。其中获取过程是为需方而定义的,该过程从确定需要获取的系统、软件产品或软件服务开始,制定和发布标书,选择供方和管理获取过程,直到验收系统、软件产品或软件服务。供应过程是为供方而定义的,该过程决定编制投标书来答复需方的招标书;与需方签订一项合同,来提供系统、软件产品或软件服务;确定为管理和保证项目所需的规程和资源,从编制项目计划,实施计划,直到系统、软件产品或软件服务交付给需方。
组织项目使能过程组提供所需的组织级资源和基础设施以支持项目,并确保达成组织的目标和所签订的协议。它包括6个过程:生存周期模型管理过程、基础设施管理过程、项目组合管理过程、人力资源管理过程、质量管理过程和知识管理过程。
技术管理过程组的项目过程负责计划、执行、评估和控制项目的进度,并支持各种特定的管理目标,包括项目计划过程、项目评估与控制过程、决策管理过程、风险管理过程、配置管理过程、信息管理过程、度量过程和质量保障过程。
技术过程组关注贯穿软件生存周期的技术活动,用以定义系统的需求,将需求转换成一个有效的产品,使用这个产品,提供所需的服务,并保持这些服务直至它被淘汰。这些过程涵盖了软件或系统开发中的业务分析、需求定义、架构定义、设计定义、系统分析、实现、集成、验证、移交、确认、运维、退役等各个方面。
ISO/IEC 12207提供了一个全面的过程框架,为制定组织或项目特定的软件过程提供指南。
软件过程模型,又称为软件生存周期模型,是软件过程的结构框架,它在一定抽象层次上刻画了一类软件过程的共同结构和属性。不同的软件过程模型阐述不同的软件开发思想、步骤以及最佳实践。常见的软件过程模型包括瀑布模型、增量模型和演化模型。
1970年Royce提出了著名的线性顺序模型,又称瀑布模型(waterfall model)。正如它的名字一样,瀑布模型将软件过程中的各项活动规定为依固定顺序连接的若干阶段工作,形如瀑布流水,最终得到软件产品。这些顺序执行的阶段通常为:需求、设计、实现、测试、交付、运行和维护,如图2-2所示。每个阶段的结束处都设有评审,只有通过评审才能进入后一阶段。前一阶段的中间产品是后一阶段工作的基础。
瀑布模型的优点在于:①它在支持开发结构化软件、控制软件开发复杂度、促进软件开发工程化方面起了显著作用;②它为软件开发维护提供了一种当时较为有效的管理模式,通过开发计划制订、项目估算、阶段评审和文档控制有效地对软件过程进行指导,从而对软件质量起到一定程度的保障作用。但是,瀑布模型的最大问题在于没有在实践中进行验证。一个没有通过验证的模型在大量的实践中会暴露出它的种种不足和问题:
图2-2 瀑布模型
1)不能应对不确定性。用户常常难以清楚地给出所有需求,而瀑布模型却要求如此,它不能接受在许多项目的开始阶段自然存在的不确定性,以及开发过程中的需求变更。
2)错误发现太迟。软件的运行版本一直要等到项目开发晚期才能得到,很多错误直到运行程序时才被发现,造成大量的返工。
3)开发进度缓慢。由于模型的线性顺序,开发者常常被不必要地耽搁,某些项目组成员不得不等待组内其他成员先完成其依赖的任务。
瀑布模型太理想化、太单纯,已不再适合当前充满各种风险的软件开发项目。但我们应该认识到,“线性”是人们最容易掌握并能熟练应用的思想方法。当人们碰到一个复杂的“非线性”问题时,总是会千方百计地将其分解或转化为一系列简单的线性问题,然后逐个解决。线性是一种简洁,简洁就是美。当我们领会了线性的精神,就不要再呆板地套用瀑布模型的外表,而应该用活它。例如增量模型和演化模型实质上就是多次重复的线性模型。也许,当软件工程和开发技术足够成熟时,线性模型可能会再次回归到业界实践中。
增量模型(incremental model),又称有计划的产品改进模型,它从一组给定的需求开始,通过构造一系列可执行版本来实施开发活动。第一个版本实现一部分需求,下一个版本实现更多的需求,以此类推,直到系统完成。每个版本都要执行必要的活动和任务,如,需求分析和架构设计仅需要执行一次,而软件详细设计、软件编码和测试、软件集成和软件验收在每个版本构造过程中都会执行。增量模型的例子如图2-3所示。
和瀑布模型相比,增量模型具有以下显著的特点:
1)多个版本可以并行开发。在开发每个版本时,开发过程中顺序地或部分平行地进行各项活动和任务。当相继版本在部分并发开发时,开发过程中的活动和任务可以在各版本间平行地被采用。
2)每个版本都是可运行的产品。每一个线性序列产生软件的一个可发布的“增量”,这必须是可运行的产品。
3)需求在开发早期是明确的。大部分需求在项目早期就被定义,在此基础上进行整体架构的设计,然后将功能有计划地分为若干增量来逐步实现。
图2-3 增量模型
当开发人员、资源或资金不足以在设定期限内实现一个完全的版本时,增量开发尤为有用。早期的增量可以由较少的人员实现,如果核心产品很受欢迎,可以增加新的人手实现下一个增量。同时,增量能够有计划地管理技术风险,并且能提前把产品推向市场。但增量并没有缓解瀑布模型中的需求风险和架构风险。相反,一旦需求不明确、架构没有把握或变更频繁,其返工风险会更大,极可能涉及多个并行开发的版本。
就像所有复杂系统一样,软件要经过一段时间的演化。业务和产品需求在软件开发过程中常常发生改变,想要一次迭代就开发出最终产品是不可能的;同时,紧迫的市场期限使得难以一下子完成一个完善的软件产品。因此,只要核心需求能够被很好地理解,我们就可以进行渐进式开发,其余需求可以在后续的迭代中进一步定义和实现。这种过程模型称为演化模型(evolutionary model),它能很好地适应随时间演化的产品的开发。
演化模型是迭代的过程模型,它的特征是渐进地开发各个可执行版本,逐步完善软件产品,如图2-4所示。每个版本在开发时,开发过程中顺序地或部分重叠平行地进行各项活动和任务。演化模型通过以下手段缓解了软件开发所遇到的进度风险、需求风险、架构风险、技术风险、集成风险和质量风险等。
1)优先级高的需求在前面的迭代实现,迭代式交付产品。当进度来不及时,宁可放弃优先级低的需求,绝不牺牲质量。
2)支持迭代间和迭代内的并行开发,加快开发进度。需求在开发早期常常不能被完全了解和确定,演化模型在一部分需求被定义后就开始开发了,然后在每个相继的版本中逐步完善。
3)在软件的开发过程中,需求总会变化,但需求变化和需求“蠕变”会导致项目延期交付、工期延误、客户不满意、开发人员受挫。通过向用户演示迭代所产生的部分系统功能,我们可以尽早地收集用户对系统的反馈,及时改正对用户需求的理解偏差,从而保证开发出来的系统能够真正地解决客户的问题。
4)当我们对项目的技术方案不确定时,演化模型通过早期迭代进行技术探索,建立架构或技术原型,通过原型的测试与反馈来评估和选择合适的技术方案,为后续的迭代化开发提供稳定的基础。
5)在每个迭代中都安排集成和测试,使得系统集成和系统测试提前并持续执行,及早发现代码缺陷。
演化模型是目前采用最广泛的模型,统一软件过程(UP)和许多敏捷过程(如XP、Scrum)都采用了这种模型。原型模型则是迭代次数为2的演化模型,它在第一个迭代中通过界面原型来识别和澄清软件需求,然后在第二个迭代中根据明确的需求进行开发。但是,演化模型也有一个明显的缺点——复杂。它比瀑布模型要复杂很多,其难点是迭代的规划和控制,当然,这也是其成功的关键。本节以下内容将详细阐述迭代化开发原则,并以统一过程为例来解释演化模型。
图2-4 演化模型
2.2.3.1 迭代化开发原则
迭代是处理不确定的复杂问题的有效手段。演化模型采用迭代来应对复杂软件开发中的不确定性,将一个软件生命周期划分为若干个迭代,前一个迭代将为下一个迭代积累经验。
● 迭代化开发原则一:要求每次迭代都产生一个可执行的软件版本。每次迭代本身都包括计划、建模、需求、分析和设计、实现、测试、评估等活动。每个迭代开始于计划和需求,结束于一个小型发布,其内部就像一个小的瀑布模型,即瀑布模型可以看作迭代化开发的一个特例,整个开发流程只有一次迭代。唯一和瀑布模型不同的是,其计划、需求、设计、实现、测试等活动允许(或鼓励)部分并行。
● 迭代化开发原则二:要求有计划的迭代。采用瀑布模型进行开发也有迭代,例如第一个迭代是对所有的功能进行需求分析、设计、实现和测试,在测试时发现需求有缺陷,然后返工至需求,再进行设计、实现和测试,形成第二个迭代,在测试时又发现缺陷,再返工……但这种迭代是无计划的、失控的。我们无法事先预计会有多少次迭代,每个迭代做什么,项目什么时候会结束。迭代化开发要求在做项目计划时就确定迭代的个数,以及每个迭代的起止时间和任务。一个软件项目通常由3~9个迭代组成,项目的风险越高,迭代就越多。迭代的安排和计划是由风险驱动的。
汽车4S店业务管理系统的迭代安排
我们首先分析汽车4S店业务管理系统的风险,发现最大的三个风险如下:
1)第一大风险:需求风险。ABC汽车集团公司提不出具体需求,同时由于激烈的市场竞争,在开发过程中需求将会发生变化。
2)第二大风险:技术风险。采用什么架构,是否要采用Web service技术?SJTU项目组没有相关经验。
3)第三大风险:进度风险。整个项目的开发进度非常紧。按当前掌握的需求,需要9个月才能完成,但ABC公司为了配合一款新车上市,要求7个月后系统就上线。
根据上述风险分析,我们进行了如下的迭代安排:
1)第一个迭代,解决需求风险,开发需求界面原型,并和ABC公司召开需求联合评审会,获得用户反馈。
2)第二个迭代,解决技术风险和架构风险,开发架构原型,并通过测试确保所选的技术和架构是合理的。
3)第三个迭代~第六个迭代,解决进度风险。我们将用户需求排出优先级,将优先级高的需求放在第三个迭代完成,构建系统的第一个版本,并在第四个迭代进行第一次移交,包括移交时的系统打包、用户手册准备、验收测试和部署上线。第五个迭代开发优先级中的需求,构建系统的第二个版本,并在第六个迭代进行第二次移交。每个迭代一个月。
在新车上线时,前四个迭代已经完成。虽然系统的功能没有全部完成,但系统最重要的功能已经移交和上线,而且质量很好,用户可以开始使用。余下的次要功能在第9个月底全部完成,不影响ABC公司的业务。
事实上,迭代的周期有长有短,同一个软件项目中多个迭代的周期也常常不尽相同。典型情况下,一个迭代一般是2~6周,这受软件项目的规模和复杂性、开发组织的规范、稳定性和成熟度,以及软件开发的自动化程度等因素的影响。
2.2.3.2 统一软件过程
每一种软件过程模型都有具体的过程实例,其中统一软件过程(UP) [1] 是目前广泛接受的演化过程之一。UP是Rational软件公司(2003年被IBM收购)开发的一个风险驱动的、基于UML和构件式架构的迭代、演化开发过程,它是从几千个软件项目的实践经验中总结出来的,对于实际项目具有很强的指导意义。
UP的整体框架如图2-5所示。它展示了两个维度:水平方向是随着时间逐渐延展的项目生命周期,展示了过程以阶段、迭代和里程碑所表述的动态特性;垂直方向是以规范为逻辑划分的活动,通过过程元素,如流程、活动、制品、角色等展示了过程的静态特性。
图2-5 UP框架
UP把软件过程分为先启(inception)、精化(elaboration)、构建(construction)和产品化(transition)四个阶段。每个阶段又可分为多个迭代,其中迭代的数量和风险相关,风险越大则迭代个数越多。每个阶段结束是一个业务决策里程碑(大里程碑),每个迭代结束是一个技术里程碑(小里程碑)。
先启阶段的目的是在所有项目干系人之间就项目目标达成共识。该阶段对新项目尤其重要,新项目的重要业务风险和需求风险问题必须在项目继续进行之前得到解决。对于扩展现有系统的项目来说,先启阶段较短。先启阶段的结束是软件生存周期的目标里程碑。
精化阶段的目的是建立软件架构的基线,解决技术风险,以便为软件的详细设计和实现提供一个稳定的基础。架构是基于对大多数重要需求(对系统架构有很大影响的需求)的考虑和风险评估建立起来的。架构的稳定性则通过一个或多个架构原型进行评估和验证。精化阶段的结束是软件生存周期的架构里程碑。
构建阶段的目的是基于已建立基线的架构完成系统开发。从某种意义上来说它是一个“制造”过程——由于需求风险和技术风险已经通过前两个阶段受到控制,其重点在于管理资源和控制操作,以便优化成本、进度和质量,又快又好地实现软件的功能。从这种意义上说,从先启和精化阶段到构建和产品化阶段,管理上的思维定式经历了从知识产权开发到可部署产品开发的转变。构建阶段的结束是软件初始能力的里程碑。
产品化阶段的重点是交付最终用户可以使用的软件。它可跨越几个迭代,包括测试处于发布准备中的产品和基于用户反馈进行较小的调整。在产品化阶段,用户的反馈应主要侧重于调整产品、配置、安装和可用性问题,而所有软件架构上的问题应该在项目早期阶段就已得到解决。产品化阶段的结束是软件产品发布的里程碑。
20世纪90年代后期,随着技术的发展和经济的全球化,软件开发也出现了新的特点,即在需求和技术不断变化的过程中实现快速的软件开发。在这个背景下,软件行业借鉴了制造业“敏捷制造”的思想,逐渐形成了敏捷(agile)软件开发这一新型软件开发模式。在2001年,以Kent Beck、Martin Flower、Alistair Cockburn等为首的一些软件工程专家成立了“敏捷联盟”(http://www.agilealliance.com),并提出了著名的敏捷宣言,这标志着敏捷软件开发的思想逐步走向成熟。
和传统过程不同的是,敏捷过程强调以人为本,快速响应需求和变化,把注意力集中到项目的主要目标——可用软件上,在保证质量的前提下,适度文档、适度度量。敏捷过程基于适应而非预测,它弱化了针对未来需求的设计而注重当前系统的简化,依赖重构来适应需求的变化,通过快速、短迭代的开发,不断产出和演化可运行软件。敏捷过程以人为导向,把人的因素放在第一位。它认为,软件开发中的绝大部分是需要创造力的设计工作,因此,在管理理念上应注重领导和协作,而非命令和控制,充分发挥软件人员的能动性和创造力。敏捷过程特别强调软件开发中相关人员间的信息交流,认为面对面的交流的成本要远远低于文档交流的成本,应减少不必要的文档,提高应变能力。
从本质上讲,敏捷过程是为克服传统软件过程中认识和实践的弱点开发而成的,它可以带来多方面的好处,但并不适用于所有的软件开发项目。它也并不完全对立于传统软件工程实践,而是保留了传统软件工程实践的基本框架活动:客户沟通、策划、建模、构建、测试、交付、迭代等,但将其缩减到一个推动项目组进行构建和交付的最小任务集。
敏捷过程的框架分为四个层次:动机、价值、原则和实践,如图2-6所示。
(1)动机
互联网的迅猛发展和经济全球化向软件开发提出了新的挑战:快速的市场进入时间、快速变化的需求、快速发展的技术。在这个背景下,许多软件工程师都试图改变传统软件过程的复杂性,自下而上地提出了敏捷过程。
(2)价值
《敏捷宣言》中包含了四条著名的敏捷价值观,所有敏捷过程都必须同意这个价值观才能加入敏捷联盟中。
图2-6 敏捷过程的四个层次
● 注重个人和交互胜于过程和工具。
● 注重可用的软件胜于事无巨细的文档。
● 注重客户协作胜于合同谈判。
● 注重随机应变胜于循规蹈矩(恪守计划)。
敏捷开发认为关注左边的内容更能适应市场需求,提升客户满意度。
(3)原则
从四条敏捷价值观出发,敏捷联盟提出了十二条基本原则:
● 最优先的目标是通过尽早地、持续地交付高价值的软件来满足客户需要。
● 欢迎需求变化,甚至在开发后期也是如此。敏捷过程通过驾驭变化来帮助客户取得竞争优势。
● 经常交付可用软件,间隔从两周到两个月不等,优先采用较短的时间尺度。
● 整个项目自始至终,业务人员和开发人员都必须每天在一起工作。
● 以积极主动的人员为核心建立项目团队,给予他们所需的环境和支持,并且信任他们能够胜任工作。
● 在开发团队内外传递信息最有效率和效果的方法是面对面的交流。
● 可用的软件是最主要的项目进展指标。
● 敏捷过程提倡可持续的开发。项目发起人、开发者和用户都应该始终保持稳定的工作步调。
● 持续关注技术上的精益求精和优良的设计以增强敏捷性。
● 简约——使必要的工作最小化的艺术——是成功的关键。
● 最优的架构、需求和设计浮现于自组织的团队。
● 团队定期不断地对如何更加有效地开展工作进行反思,并相应地调整、校正自身的行为。
这些敏捷原则是用来判断一个组织是否做到了敏捷的主要依据。
(4)实践
敏捷到底应该如何做?如何将敏捷价值观和原则落到实处?这是大多数人最关心的问题。人们已研究总结出大量成熟的敏捷实践,在此基础上提出了一系列具体的敏捷过程,如Scrum、Kanban、XP、AgileUP、AM(Agile Modeling)、Lean、FDD、Crystal等。接下来将介绍最有代表性的敏捷过程——Scrum和Kanban。
Scrum是目前最流行的软件过程,它关注敏捷的软件项目管理,由Ken Schwaber和Jeff Sutherland于1993年提出,已在全球许多公司中应用,适用于需求难以预测的复杂商务应用产品的开发。Scrum一词来源于橄榄球运动,意为两队并列争球。敏捷软件开发就像是橄榄球的争球过程,是迅速的、有适应性的、自组织的。
Scrum认为软件开发过程更多是经验性过程(empirical process),而不是确定性过程(defined process)。确定性过程是可明确描述的、可预测的,因而可重复执行并能产生预期的结果,并能通过科学理论对其进行最优化。经验性过程与之相反,应作为一个黑箱(black box)来处理,通过对黑箱的输入输出不断进行度量,在此基础上,结合经验判断对黑箱进行调控,使其不越出设定的边界,从而产生满意的输出。Scrum方法将传统软件开发中的分析、设计、实现视为一个黑箱,认为应加强黑箱内部的混沌性,使项目组工作在混沌的边缘,充分发挥人的创造力。若将经验性过程按确定性过程来处理(如瀑布模型),必将使过程缺乏适应力。
Scrum的核心准则是自我管理和迭代开发。
(1)自我管理
Scrum团队的目标是提高灵活性和生产能力。为此,他们自组织、跨职能,并且以迭代方式工作。每个Scrum团队都有三个角色:①Scrum主管(Scrum Master),负责确保成员都能理解并遵循过程,通过指导和引导让Scrum团队更高效地工作,生产出高质量的产品;②产品负责人(Product Owner),定义和维护产品需求,负责最大化Scrum团队的工作价值;③团队(Team),负责具体工作。团队的理想规模是5~9人,团队成员具备开发所需的各种技能,负责在每个Sprint(冲刺迭代)结束之前将产品负责人的需求转化为潜在可发布的产品模块。
Scrum过程中没有中心控制者,强调发挥个人的创造力和能动性,鼓励团队成员进行自我管理,使用自己认为最好的方法和工具进行开发。Scrum主管的职责不是检查和监督团队成员的日常工作,而是消除团队开发的外部障碍,指导团队成员工作,对内部成员进行培训。Scrum通过鼓励同场地办公、口头交流和遵守共同规范创建自组织团队。
(2)迭代开发
Scrum是一种演化型的迭代开发过程,如图2-7所示。Scrum的核心是Sprint,即贯穿于开发工作中的短期迭代。一个Sprint周期通常为1~4周,它是一个固定时间盒,在项目进行过程中不允许延长或缩短。每个Sprint都会提交一个经测试可发布的软件产品增量版本。Sprint由Sprint计划会、开发工作、Sprint评审会和Sprint反思会组成。
图2-7 Scrum过程
Scrum采用四个主要的文档:产品待办事项列表(product backlog)、Sprint待办事项列表(Sprint backlog)、发布燃尽图(release burndown chart)和Sprint燃尽图(Sprint burndown chart)。产品待办事项列表是囊括了开发产品可能需要的所有事项的优先排列表。Sprint待办事项列表包含在一个Sprint内将产品待办事项列表转化成最终可交付产品增量的所有任务。发布燃尽图衡量在一个发布计划的时间段内剩余的产品待办事项列表。Sprint燃尽图衡量在一个Sprint时间段内剩余的Sprint待办事项列表条目。
Scrum采用任务板来可视化软件开发的进展,它可以是一个大白板,也可以使用软件,如图2-8所示 [2] 。任务板上展现了当前Sprint的所有任务,每项任务用一张“即时贴”来代表,上面记录着任务的名称、优先级、接受任务的开发者姓名、预计的完成时间等信息。任务板上有3列:待处理的任务(To Do),即Sprint中要着手的待办事项或用户故事(user story);进行中的任务(Doing),即团队成员已经认领的、正在处理的任务;已完成的任务(Done),即团队成员已经完成的、被关闭的任务。在Sprint过程中我们要不断地更新任务板。
图2-8 Scrum任务板示例
Scrum主管通过每日立会(standup meeting)来保证项目组成员了解其他所有人的工作进度。Scrum每日立会是每天早上进行的15min的会议,大家必须站立开会,例如站在任务板前。每个团队成员要回答以下三个问题:昨天你做了什么?今天打算做什么?有没有问题影响你达成目标?团队成员通常需要与Scrum主管沟通解决这些问题,这些沟通不是会议讨论内容,因此每日立会只是提出问题,会后再个别沟通具体问题的解决方案,以确保每日立会的时长控制在15min以内。
Scrum能快速适应需求变化,提高开发进度和质量,在工业界取得了很大成功。Standish Group的2018年chaos报告中的调查结果表明,Scrum的项目成功率达到58%,而传统的瀑布模型的项目成功率仅有18%。
Kanban,又称为看板,源自精益制造,从丰田公司的实践中演化出来,其核心在于工作的全方位可视化以及基于工作的实时沟通。通过看板墙(Kanban board)中各工作项的直观展示,让团队成员清晰了解各项工作的状态及进展,并识别瓶颈。
看板墙和Scrum任务板很类似,可以是物理板或电子板。不同的是,在看板墙中,根据团队的规模、结构和目标的不同,团队可以设置自己个性化的工作流。图2-9是一个典型的看板墙,它的每个迭代由待办事项(Backlog)、选择(Selected)、开发/处理中(Develop/Ongoing)、开发/已完成(Develop/Done)、部署(Deploy)和发布(Live!)等步骤组成。我们也可以把开发进一步细分为设计、编码和测试。看板墙的作用是把整个开发流程可视化。团队在看板墙的各栏目中贴上卡片来代表开发过程中的各个工作项,让团队工作流可视化呈现。
图2-9 看板墙示例
看板墙上的每张卡片代表一个工作项,它记录了有关该工作项的相关信息,使整个团队能够全面了解负责该工作项的人员、正在完成的工作的简要描述、估计该工作需要多长时间等。电子板上的卡片通常还会包含功能截图和其他对经办人有价值的技术细节。看板卡片允许团队成员在任何时间点都能了解每个工作项的状态以及相关细节。
栏目顶部的数字代表该步骤的最大工作项容量。Kanban通过限制进行中的工作项的数量,防止过度生产,并动态地揭示开发过程中的瓶颈。进行中的工作项(work in progress, WIP)称为在制品。团队通过将在制品与团队能力的匹配来达到软件的“及时”(just in time, JIT)开发。
Kanban和Scrum都是基于快速迭代的敏捷过程,采用自组织团队。和Scrum不同的是,Kanban的最大特点是限制正在进行的工作项的数量,以及看板墙上可视化的工作流。此外,Kanban的迭代没有规定的固定时长,没有规定的角色。两个过程可以相互融合,例如微软提出的Scrum-ban。
在传统的软件组织中,开发与运维之间常常存在隔阂,这使得软件产品无法迅速地交付给市场。隔阂产生的根本原因是:开发人员和运维人员认识的方法,以及各自所处的角色,都存在根本性的差别。开发团队要求不断满足新的客户需求,并快速实现新的功能。而运维最关心的是“稳定”,任何差错都有可能对生产环境中的用户造成直接影响。因此,开发运维一体化(DevOps)应运而生,它将敏捷过程从开发延伸至运维,形成了贯穿软件开发和软件运维的一系列实践 。
DevOps是敏捷过程在完整的软件生命周期上的延伸,从文化、自动化、标准化、架构以及工具支持等方面,打破开发与运维之间的壁垒,在保证高质量的前提下,缩短产品交付的周期。DevOps始于计划,覆盖编码、构建、测试、发布或交付、部署、运营和监控等阶段,如图2-10所示。这是个“无穷环”,因为DevOps的根本理念是“持续”,也就是“没有终点”。“无穷环”也象征着软件开发与运维过程中短周期、高质量的交付和快速的反馈。
自动化是DevOps的基石,通过DevOps工具链可使软件构建、发布和部署更加快捷、频繁和可靠。工具链通常以持续集成工具为中心,将项目管理和问题跟踪、版本管理、构建、测试、发布、部署、监控等工具作为一个个集成单元,进行编排与调度,构建开发与运维的自动化工作流,支持DevOps的全生命周期。
图2-10 DevOps的生命周期
为了应用和优化DevOps过程,Kim等提出了DevOps的“三步工作法”基础原则 [3] 。
● 第一步,流动原则,聚焦于价值流的快速流动。为了在竞争中取得优势,DevOps的目标是在缩短代码从变更到生产环境上线所需时间的同时提高服务的质量和可靠性,建立从开发到运维之间快速的、平滑的、能向客户交付价值的工作流。为了实现上述目标,本原则借鉴精益思想,实现工作内容的可视化,减小工作批次大小和等待间隔,内建质量以防止缺陷向下游传递,从而增强价值流动性。
● 第二步,反馈原则,关注于持续快速的反馈机制。本原则使得开发运维的每个活动都可快速、持续性地获得工作反馈,及时发现并修复问题,从开发源头控制质量,为下游活动做优化。
● 第三步,持续学习与实验原则,旨在创建有创意、有高度信任感的企业文化。本原则鼓励每个人敢于发现问题、承担问题、解决问题;从成功和失败中不断学习,开展科学的实验,进行持续改进;在团队中分享知识和经验,建立学习型、共享型文化。
DevOps的根本理念是“持续”,最核心的技术实践是持续集成、持续交付和持续部署。
● 持续集成(continuous integration)是指开发人员频繁地(一天多次)将更新的代码合并或者提交到主干源码仓库中。在这个合并或者提交的过程中,都伴随着执行一系列质量保证活动(如代码规范检查、单元测试、安全扫描等)来确保代码的质量。持续集成的主要目标是让正在开发的软件始终处于可工作状态,同时更快地发现、定位和修复错误,提高软件质量。
● 持续交付(continuous delivery)是指在持续集成的基础上,将集成后的代码自动安装到更贴近真实运行环境的“类生产环境/预生产环境”中。持续交付可以看作持续集成的下一步。持续交付的主要目标是让正在开发的软件始终处于可部署状态,同时实现快速交付,能够应对业务需求。
● 持续部署(continuous deployment)是指在持续交付的基础上,将交付后的代码自动部署到生产环境中。持续部署的主要目标是加快从代码提交到部署的速度,并能快速地收集真实用户的反馈。
在持续集成、持续交付和持续部署的整个过程中,代码以及相关的制品不断向生产环境的方向流转,在工具链的支持下实现价值的快速流动。
软件的项目/任务管理工具、版本管理工具、构建工具、代码静态分析工具、自动测试工具、部署工具、监控工具等形成了一个DevOps工具链,在整个软件生命周期中支持开发与运维团队的高效协同。
DevOps工具链通常采用持续集成工具作为流程引擎,将DevOps的各种工具进行集成,构建一个可重复和可靠的自动化系统,实现价值快速持续的交付。典型的持续集成工具包括开源Jenkins、Atlassian的Bamboo、腾讯的Coding平台、华为云软件开发平台DevCloud、阿里巴巴的云效流水线等。
整个流程通常分为以下几个主要阶段:
1)计划阶段。采用项目/任务管理工具进行计划、问题跟踪和协作。典型的工具如Jira和Pivotal Tracker等。
2)编码阶段。采用IDE进行编程,完成的代码只有通过代码静态分析工具或代码评审等质量门禁,才能进入代码库。典型的版本控制系统有Git和SVN等,代码静态分析工具有SpotBugs、PMD、CheckStyle和SonarQube等。
3)构建阶段。使用构建工具管理项目依赖,进行编译和链接,生成目标代码。典型的C/C++构建工具有CMake和Bazel, Java构建工具有Maven和Gradle等。
4)测试阶段。通过部署工具将目标代码部署到测试环境,采用自动测试工具运行测试用例。典型的自动测试工具包括JUnit、CppUnit、PyUnit等单元测试工具,Postman和SoapUI等API测试工具,Selenium等功能测试工具,以及JMeter和LoadRunner等性能测试工具。
5)发布阶段。通过部署工具将通过测试的目标代码部署到生产环境,进行软件发布。典型的部署工具有Capistrano和CodeDeploy。开发人员也可以通过编写脚本实现自定义的自动部署。
6)运营阶段。采用监控工具对运行的软件进行自动监控,监控内容包括指标、日志和分布式追踪。如果在运营时发现缺陷或新需求,则将变更请求以新任务的形式登入项目/任务管理工具中。典型的监控工具有Prometheus、Grafana、ELK、Jaeger等。
经过几十年的演化,软件过程发展出了众多流派,包括黑客开发、敏捷开发、风险驱动的开发、计划驱动的开发、严格的微里程碑的开发等。每种过程都有其价值,集成了多项最佳实践,适用于特定类别软件的开发。不存在一种过程对所有项目都是最好的选择。因此,选择适合自己组织或项目的过程,是实施软件过程的首要任务。软件过程的选择应综合考虑以下多种因素,进行敏捷和规范的平衡。
1)产品/项目自身的特点:开发特定项目、通用产品还是产品线?需求是否明确?需求变化是否频繁?开发周期是否很短?产品升级换代是否很快?项目规模是否很大?项目干系人是否很广?开发团队是集中的,还是分散的?对可靠性和性能等质量要求是否很高?开发嵌入式系统、信息系统、多媒体系统还是其他?一般来说,“重”量级的软件过程适合需求相对稳定、项目规模较大、开发周期较长、质量攸关、产品/项目较广的情形,而以敏捷开发为代表的“轻”量级过程比较适合需求变化快、项目规模小、开发周期短、项目干系人少的项目。
2)团队的实际情况和企业文化:以敏捷开发为主的软件过程对团队成员的要求非常高,无论是专业技能、沟通技巧还是职业精神。此外敏捷开发强调自组织团队,这要求软件组织对开发团队充分信任、充分授权、积极支持,这需要组织文化的强力支持。
3)客户的影响:通常客户不会直接介入开发团队对过程的选择。但是大型客户对供应商可能有强制的过程标准。另外,客户会对过程提出一些要求,例如,提供种类繁多的文档,进行定期的阶段评审等。
选择后的软件过程还需要经过裁剪和融合才能真正满足项目的实际需要。通常会从以下几个方面对软件过程进行裁剪。
1)流程归并与裁剪:并不是每个项目都需要采用软件过程中的所有流程、阶段、活动,开发人员可以根据项目的实际情况对流程进行归并和裁剪。例如UP中有业务建模流程,那么产品的原型阶段可能需要包括这个流程;而产品的升级版本可以简化业务建模流程,直接从需求开始。
2)角色的筛选与定制:软件过程是适用于各种项目开发的通用框架,其角色定义力求完整、分工明确。而在实际项目中,由于项目规模、资源的限制,一些角色可以根据需要合并,其职责和行为规范可以根据实际情况重新定义。
3)文档的裁剪和定制:软件过程通常会定义标准的文档模板和规范,而项目有时并不需要过多的复杂文档,因此项目经理可以制订文档计划,对实际项目所产生的文档数量与规范进行裁剪和定制。
软件过程的选择和裁剪还有一个重要内容,即融合。融合的意思是不仅仅采用一种软件过程,而是在项目过程中融合其他的软件过程。例如微软在项目开发过程中采用了Scrum和Kanban的融合方法,从而创造了一种全新的敏捷开发方法——Scrum-ban。
所定义的软件过程是否适合本组织或本项目?过程绩效如何?软件过程能力成熟度为几级?哪些实践域做得很好,哪些又有不足呢?为了评估一个软件工程的好坏,研究人员提出了软件过程评估的参考模型和方法,例如CMM/CMMI 、ISO/IEC 20000 、ISO/IEC 15504、GJB 5000等。其中最有影响力的是美国卡内基-梅隆大学软件工程研究所(CMU/SEI)提出的CMM/CMMI,在美国、中国、印度等国家普遍采用。欧洲则更多地采用国际标准ISO/IEC 15504。近年来,软件的运营和维护管理也逐渐引起大家的注意,于是国际标准化组织在ITIL的基础上推出了ISO/IEC 20000,用于评估软件运维过程的能力。GJB 5000标准则是我国军用软件的能力成熟度评估的国家标准。
2.5.2.1 CMM/CMMI
为了保证软件产品的质量,20世纪80年代中期,美国联邦政府提出了对软件承包商的软件开发能力进行评估的要求。为了满足这个要求,CMU/SEI于1987年研究发布了过程能力成熟度模型(Capability Maturity Model, CMM),2002年发布了CMMI(Capability Maturity Model Integration),当前CMMI的最新版本为3.0。CMMI是一个标准簇,它包括开发、服务、供应商管理、安保、安全、数据管理和虚拟交付等八个领域。
CMMI将软件组织的能力成熟度分为以下五个等级,如图2-11所示。
图2-11 CMMI的能力成熟度等级
1)初始级(initial)。软件过程是无序的,有时甚至是混乱的,对过程几乎没有定义,成功取决于个人努力。管理是反应式的。
2)已管理级(managed)。建立了基本的项目级软件过程来跟踪费用、进度和功能特性,制定了必要的过程纪律,能重复早先类似应用项目取得的成功经验。
3)已定义级(defined)。软件技术和管理都形成了组织级的标准软件过程,所有项目均使用经批准、剪裁的标准软件过程来开发和维护软件,软件产品的生产在整个软件过程中是可观察的。
4)定量管理级(quantitatively managed)。分析对软件过程和产品质量的详细度量数据,对软件过程和产品都有定量的理解与控制。管理和决策都有客观依据,能够定量预测性能。
5)持续优化级(optimizing)。实现了过程的量化反馈,采纳先进的新思想、新技术促使过程持续不断地改进。
CMMI提供了各个实践域和成熟度等级的标准,但未提供具体的过程。各组织应根据自己的业务目标和特点与标准来制定自己的过程体系。
2.5.2.2 ISO/IEC 20000
在注重IT系统开发的同时,系统的运营和维护也成为关注的焦点。每年都有大量因系统运行故障而导致业务严重中断或出错的事件发生,造成了巨大的经济效益和社会效益的损失。为了提高IT运维服务管理过程的成熟度,2005年以ITIL为基础的英国国家标准BS 15000被国际标准化组织接受,成为IT服务管理ISO/IEC 20000国际标准,用于评估和认证IT运维服务管理过程的能力。ISO/IEC 20000提出了一整套规范的IT服务运营、实施和改进的过程管理、人员管理以及技术管理体系。它强调以客户为中心的、基于过程的IT服务管理,通过整合业务与IT服务,提高IT服务的提供和支持能力。
ISO/IEC 20000包含两个部分,其中ISO/IEC 20000-1是IT服务管理体系的要求,包括6大过程组(即服务组合,关系和协议,供需,服务设计、建立和转换,解决和实现,服务保障)及过程组所覆盖的21个服务管理流程。ISO/IEC 20000-2是IT服务管理体系应用指南,为体系的实施提供参照说明。
2.5.2.3 评估方法
CMMI、ISO/IEC 20000、ISO 15504、GJB 5000等标准不仅提出了过程评估的参考模型,同时还提供了过程评估的方法,以系统地指导评估的实施,现以CMMI的评估方法为例进行阐述。
CMMI的评估方法强调实践的价值和目的及过程改进的效果,它定义了四种评估方法。
1)基准对比评估(benchmark appraisal):一种正式评估方法,目的是获得评估等级,评估过程需执行所有的评估步骤,要求全面覆盖评估中所使用的模型。根据被评估的CMMI的不同级别,评估组通常为4~9人,由主任评估师领导,评估时间为5~10天。评估方式为文件审查和人员访谈,评估输出物为最终评估报告。所给出的成熟度等级结果的有效期为3年。
2)维持性评估(sustainment appraisal):是针对已经通过基准评估的组织进行续证需求的评估。如果没有大的组织架构的变动,维持性评估将实质性地缩减审查过程成熟度的持续性的范围。1/3的实践域要深入分析,其他可以概要分析。如果是高成熟度的评估,则包含高成熟度实践的实践域须深入分析。评估时对上一次评估发现的弱项(实践)要进行考察。最多可以连续做3次维持性评估。评估组最少为2人,包含1名主任评估师。有效期为2年。
3)评价性评估(evaluation appraisal):一种非正式评估方法,通常在正式评估前进行,以衡量组织是否达到了CMMI的实践要求。评价性评估可以由组织在任何范围内使用,集中于需要关注的实践域,可以只收集更少的信息。评估组的负责人既可以是主任评估师,也可以由组织内部有经验的成员担当。
4)行动计划复评(action plan reappraisal):是针对第一次基准评估失败的组织,改进软件过程后,再一次进行评估的方法。该方法必须在上次评估结束后4个月内完成,且需要得到CMMI研究院认可。
通过软件过程评估,组织能清晰地了解开发现状,分析不足,总结成功经验和失败教训,引入软件开发最佳实践,进行软件过程的改进。CMU/SEI在推出CMM/CMMI模型的同时,基于戴明博士的PDCA(Plan-Do-Check-Act)循环提出了软件过程改进模型——IDEAL,如图2-12所示。
图2-12 IDEAL软件过程改进模型
IDEAL定义了初始化(Initiating)、诊断(Diagnosing)、建立(Establishing)、行动(Acting)和扩充(Leveraging)五个阶段。其中初始阶段是组织层上下同心、拟定目标和愿望的阶段,这是对未来有一个共同思考的过程;诊断阶段采用评估的工作,对组织现状进行分析,发现存在的缺点和问题,并根据组织战略要求,确定需要进一步改进的方向;建立阶段制定相应的规则、模板和过程,作为改进实施的基础;行动阶段则是一个不断试点、总结、推广的过程,在这个过程中组织的所有人员都积极参与,在提高技能、绩效的同时,也在提高组织对过程改进的信心;扩充阶段进行总结、再学习和提高。
软件过程的改进需要循序渐进,不能一蹴而就;需要持续改进,不能停滞不前;需要联系实际,不能照本宣科;需要适应变革,不能一成不变。
1.什么是软件过程?根据ISO/IEC 12207标准,软件过程可分为哪些过程组?
2.瀑布模型、增量模型和演化模型各有哪些优缺点?
3.迭代化开发的原则是什么?
4.请简要列出敏捷开发的价值观和原则。
5.Scrum过程的两大核心准则是什么?请简述之。
6.请简要解释Kanban中WIP的含义和作用。
7.什么是DevOps?它有什么作用?
8.持续集成、持续交付和持续部署的差别是什么?
9.CMMI模型将软件组织的能力成熟度分为五个等级,请简述之。
10.请简述软件过程的改进模型IDEAL。
[1] 参见Jacobson, I.,Booch, G.和Rumbaugh, J.著的 The Unified Software Development Process 一书。
[2] 参见Henrik Kniberg所著的 Scrum and XP from the Trenches 一书。
[3] 具体可参见G. Kim、J. Humble、J.Debois、J. Willis和N. Forsgren著 The DevOps Handbook : How to CreateWorld-Class Agility , Reliability and Security in Technology Organizations 。