我在采用持续交付的组织中和开发团队工作一起工作,发现很多开发者认为的正确的敏捷团队的工作方式,在这里跑得不是很顺畅。我认为传统敏捷与持续交付的矛盾的根本在于,二者是采用不同的方式把软件变得“可以发布“(ready to release)的。
软件交付的演进
使软件变得可以发布的过程一直在不停进化,下面是一个简要的介绍:
瀑布模型
瀑布模型认为,当一个软件所有的功能都发开完毕的时候(也就是功能完整的时候),才可以发布。
敏捷:
敏捷引入的思想是,在整个开发过程中,软件都应该“可以发布”。许多敏捷的版本(在这篇文章里被称为传统敏捷)都认为,“可以发布”应该在固定周期的间隔点上完成。
持续交付:
持续交付是敏捷的一个子集,在持续交付中团队会保持软件在开发过程的所有时间内都可以发布。它和传统敏捷不同之处在于,持续交付在开发过程中不会有停下来然后创建发布版本的过程。
持续性交付不是指更短的周期
从传统的敏捷开发流程变成可持续性交付,不是指把软件发布的周期变短。每天晚上做发布版本仍然不是可持续性交付。可持续性交付是说要把”做可以发布的软件”这个动作本身从开发过程中去掉,取而代之的是保持软件在开发的过程中始终是可以发布的。
可以发布不是意味着真正的发布
有一个普遍的误解是可持续性交付就是非常频繁地发布出产品。而当一些组织把每天数次发布软件当作是持续交付的标杆时,就更加深了这一误解。可持续性交付不是一定要频繁的发布,它只是要求在开发过程中的任何一个点上,用非常少的工作,软件就能够发布(可参考Jez Humble的文章,可持续性交付VS可持续性部署)。尽管具备这一能力为更加频繁的发布敞开了大门,但是许多团队还是从持续交付的实践中,找到了压倒性的证据,来证明即便发布不是很频繁时,持续交付也是有用的。
持续交付和传统敏捷的冲突点
我前面讲过,有时候持续交付和开发团队所认为是“正确”的敏捷实践流程有一些矛盾。
冲突点: 当有工作没有完成时,软件依然是可发布的
其中一个冲突点是,一个迭代结束时,代码库中是否可以包含未完成的用户故事(user stories)或者bug修复。我在上一篇关于迭代的帖子中做了探讨。这个问题主要是源于,传统敏捷认为在迭代结束时,team停止开发,并且来做准备软件发布的一些额外工作,但是,如果团队采用持续交付,让软件可发布就没什么额外的工作需要做。
更有甚者,持续交付团队甚至认为,通过使用功能切换等技术,他们的代码即使在还有功能没有完成也可以发布成产品。这也从另外一个方面说明,团队在迭代结束时能够达到可以发布的要求,即使有未完成的用户故事。
这可能稍微有点难理解,团队肯定还是可以要求在迭代结束点上所有的工作都必须完成,但是这容易让人感觉是团队原有的正常开发的节奏被随便打断了。持续交付不是要求没有时间盒的迭代,这两种实践其实是互补的。
冲突点:snapshot(软件快照)/发布版本(release build)
许多开发团队把软件的版本分为“snapshot”版本和“release”版本。这个并不是敏捷所特有的,而是随着Maven的兴起,被深深植入了Java开发中,因为Maven把snapshot的概念放入了它的设计核心中。这种方案把开发周期划分成两个阶段,在软件开发过程中使用snapshot,当软件成为可以发布状态时才创建release版本。
很明显,这种发布周期的划分和持续交付的“软件应该总是可以发布”的理念是相冲突的。持续交付通常采用的方式是只在开始创建一次版本,然后通过不同阶段的测试验证等一系列串行工作来对版本进行改进,如果使用Maven,要用两种方式创建版本,这种方式就不行了。
其实完全可以使用Maven做持续交付,比如说,为每个版本创建一个release build。当然,这个会和Maven的“release build只以生产部署为目的,不会经常创建”的理念矛盾。而且,像Nexus和Artefactory这样的私服都有删除旧的snapshot版本的清理功能,但不允许删除release版本。所以一个活跃的持续交付团队,一天可以产生几十个版本,这样很容易就吃掉服务器上几G到几T的空间。
矛盾点: 更着重测试可部署性
标准的持续交付的实践方式是,通过基本的持续集成自动地把每个版本部署到与真实生产环境尽量贴近的模拟环境中,使用相同的发布流程和工具。这对验证每次提交的代码是否是“可以发布”是至关重要的,但是这样对持续集成的要求比现在大部分开发团队正在使用的要高很多。
举个例子,在没有要求持续发布的持续集成,可能会使用Ant或者Maven将应用发布到嵌入应用服务器然后进行自动的功能测试。开发者使用和维护都很方便,但是这很可能不是生产环境中应用发布的方式。
所以持续交付团队会自动化发布到一个更贴近真实生产的环境,包括不同的网页/app/数据层,并且使用在真正生产中使用的部署工具。当然,这种更像生产的部署阶段更加可能出错,因为它增加了复杂性,而且可能对开发者而言更难以维护和修正,因为这些工具更像是给系统管理员而不是给开发者使用的。
不过这是个机会,可以和管理运营团队一起创建一个更可靠、更易于支持的部署流程。但是实现和稳定这一流程的难度会比较大,可能会影响开发的进度。
值得采用持续交付吗?
考虑到有这么多冲突的地方,那持续交付有什么好处,值得我们从传统敏捷迁移过来呢?特别是对于那些实际上不太可能在一次迭代中有好几次发布到生产环境的团队来说,更是要问这个问题。值得这么做的原因如下:
尽早发现部署可能遇到的问题以降低风险
增加灵活性,组织可以选择在任何时候发布,并把附加的代价和风险控制到最小
把生产发布涉及的每个人拉进来(比如QA、运营等),使得整个流程更有效率。组织必须识别出流程中的困难区域,并且通过自动化、更好的协作或者改进工作方法等方式找到克服它们的方法