持续发布那些事儿

2018-03-15 10:50:54 浏览数 (1)

什么是持续发布

持续发布这个说法,一般情况下确实是和敏捷开发联系在一起。敏捷开发的scrum模式的一个重要概念就是持续发布。

按照理论上的说法:scrum的每一个sprint结束时(或者更激进的说法,每天结束时)开发团队都应该提供一个可以发布给用户的产品。所差别的,仅仅是每日产品的具体feature不同,quality应该是稳定的。

不过当然,这仅仅是一个理论上的说法。就笔者所见所闻而言,还不知道哪一家企业或者机构真的能够做到如此。

有一些互联网企业,确实是每天,甚至每几个小时直接就把刚改过的代码上线。不过那些代码的质量就不好说了。虽然时间上近似,但是这种基于“将所有测试任务交给用户”想法的赶工式的发布,显然不是我们所说的持续发布。

从实践的角度来说,持续发布如果能做到每个sprint结束可以对内部用户提供一个用于内测的版本,每天的checkin不要包含不完整的feature代码(也就是说一个feature在完全实现之前不要checkin),也就可以认为是在进行持续发布了。

但是在这里,会有个问题,如果feature的粒度过大,特别是分配个不同的人并行开发,则可能会导致代码不能够及时的合入。此处涉及到敏捷开发的另一个概念——最小feature原则。我们说的feature,是一个“自洽”的最小代码单位。一个比较合理的尺寸,是以1人/天为宜。

为什么要持续发布?

为什么会有敏捷方法、持续发布这样提法出现呢?应该说互联网行业是主要驱动力之一。传统的瀑布式软件模型,基本是以月为单位来计量开发日程的,一个软件周期在1年或者更长也都是很正常。但是互联网软件的更新是按天、按小时计的,今天的提出来的feature,今天,最多明天就要上线,否则就要少赚钱,或者被竞争对手超过!

除了时间要求差别巨大以外,传统软件讲究需求分析,结构设计,先把要做什么搞清楚,然后仔细设计架构和具体实现,然后才付诸编码,而互联网软件则提出了一个概念——精益(lean)。精益的核心思想是试错。每增加一个feature,就让它立刻去面对用户,通过用户的反馈来确定这个feature是否值得存在,应该向哪个方向修改。一个软件不是像以前那样,先列出120个功能点,然后全部开发测试完毕在交给用户使用而是,在开发了最初的几个最核心的功能点后,就直接扔给用户去用,然后根据用户的反应或删或改。

这样自然就会要求一个软件被不断的发不出去,而不是最后发布一次。持续发布也就被提了出来。

如何持续发布

用笔者曾经参与过的一个大数据分析平台开发项目作为例子,来说明一下持续发布:这个平台是一个从0开始的项目,一开始就follow scrum流程,最初一个sprint是3周,后来改为2周。开始阶段,大概前8-10个sprint还是比较混乱的。到了10个sprint左右,一些基本功能,包括前后端都已经具备了,同时自动化测试框架也已经搭建,从这个时候开始,逐渐向理想的持续发布状态前进。虽然最终直到1.0, 1.1 发布开发团队也没能达到理想的持续发布状态,但是基本上已经达到了每天checkincode之后都会在内部测试平台编译部署,部署好的测试版本是内部用户可以直接访问试用的。

在产品开发稳定期,基本上每天的流程是这种:每个sprint开始的时候PM把这个sprint要做的feature都列出来,每天早上,dev先挑选自己当天要做的feature,然后就去做相应的开发工作。开发流程遵循TDD,dev在提供featurecode的同时,必须同步提供unit test case的code。到了下午,大家checkin 各自的code,在checkin的时候,代码是被scan过的,如果新添加的method没有相应的unit test case,则会被拒绝checkin。codecheckin之后,自动编译、部署并运行所有automation testcases,如果有failed test,则会发出警告。如果test coverage低于要求的阈值,也会被警告。如果所有都满足条件,则会正式部署到内部产品环境,内部用户就可以直接使用了。

用什么技术实现持续发布

一般而言,持续发布环境所需的几个主要组成部分包括:版本管理工具、code review工具、测试框架、编译部署工具和测试运行环境,这次加起来,统称持续集成(CI)系统。

具体到一个企业如何搭建一套CI系统,则有两种截然不同的风格:开源软件大组合 vs 自己造轮子。

例如:公司A采用git jekins testng。git是code repositry,用户代码的版本管理。testng是基础测试框架,我们基于它进行了二次开发,所有自动化测试用例都是testng驱动的。jekins则属于编译部署工具,codecheckin到git repositry之后,jekins就会自动触发自动编译环境编译,然后自动部署到测试环境,然后再启动自动化测试,得到testreport之后根据不同结果发送邮件。同样的流程,公司B自主开发所有的构件。

这两种风格的优劣也十分明显:前者可以在短期内以少量人员的投入迅速建立起CI系统,但却不太容易对自身的特殊需求进行定制;后者需要投入大量人力物力和时间,但却对所有工具掌控绝对的控制权。具体如何选择,则要看企业的实力和需求。

持续集成对于软件开发流程影响

当然,并不是所有软件都需要每天发布,也不是所有软件都可能每天发布。很多类型的软件,例如金融、电信等,大量的专业测试是必不可少的,客观上不具备持续发布的可能。

不过以目前的态势来开,大多数类型的软件向着更频繁更迅速发布的这个方向上走的趋势是很明显的。那么在实际工作中借鉴持续发布的思想,用来构建适合自己的“持续发布”就成了必要。那么怎么才能更快、更高、更强呢?怎么才能用更少的人工在更短的时间干出更多的活儿来呢?

对于软件行业而言,有一个已经被众多企业验证有效的方法:自动化。把能自动化的部分都自动化起来。

软件产品的三要素:开发、测试、运维。现阶段,开发还没有成熟的自动化技术,不过在测试和运维领域,成熟的可实践技术已经很多了。把编译、部署、监控、测试这些可以自动化的部分都自动化起来。

测试相对于运维而言,更“单纯”。尤其是很多不涉及到图形界面的后端软件,自动化测试甚至可能覆盖全部功能。

例如前述提到的大数据分析平台,产品有单元测试,和端到端的自动化测试用例。因为产品整体是个webservice,所以对后端做全自动化测试也比较简单。到开发的后期极端,后端的测试基本上已经脱离了手动。不过前端因为是图形界面,所以还是采用了手动测试。

后端的单元测试用例由开发人员负责,端到端测试用例则归测试人员编写,编写好的自动化测试用例的运行由CI系统来承担。这样做最大的好处是回归测试的方便和全面,避免了因为fix bug或者临时feature修改导致的系统崩溃情况。

但是话说回来,对于前后端都有的产品而言,要求手动测试和自动化测试同步完成,通常是一个不合理的要求。机器可以彻夜不停运转,人却不行。

从实践出发,可以将持续发布人为分为“小版本”和“大版本”。这里说的大小版本并不是指真正意义上发布出来的软件的版本。而是说,当一个sprint 持续三周时,可以每个sprint发布一个“小版本”,每2-3个sprint发布一个“大版本”。小版本仅保证自动化测试完成,大版本才保证手动和自动都完成。如果内部用户要使用,只能使用大版本,小版本仅供团队内测。这样会使得部分feature不能以最快速度让用户适用,但是同时也允许团队提供相对质量较高的内部产品。以此来达到自动/手动测试的平衡。

0 人点赞