持续交付2.0
“10X”,就是“十倍速”,是Google内部流行的一种隐喻,用以说明那些具有挑战的事情必须用非常手段来解决,而不是常规性的改进。
Google X部门是谷歌内部的创新产品部门,众所周时的谷歌眼镜和自动驾驶就是这个部门的工作。该部门的负责人阿斯特罗.泰勒用下面的方式解释这一法则:
“10X is easier than 10 percent.
如果你只是想自己的汽车达到50英里的时速,可能只要对它稍加改造即可。然而,如果想让它只有一加仑汽油跑上500英里,就要对它进行重新设计了。”
那么,这一法则与工程效能有什么关系呢?下面让我们用LinkedIn的案例来了解一下什么是“非常之目标必配之以非常手段”。
02
—
建立有挑战的目标
在2015年,领英公司还不到3000名工程师。那时,公司原计划每个月发布一个版本,版本计划是开发时间为三个星期,集成测试时间为一周,然后就发布,每个人都能轻松顺利地按时完成工作,如下图所示。
然而,这只是一个“理想”而已,现实却是另外一个样子。每当拉出Release Candidate分支的前两天,所有人都在加班,匆忙提交半成品的代码,以便交给测试人员开始测试。而代码质量不好,就有很多Bug等待修复。最后一分钟还可能提交一个关键功能。没有测试完成,只能延迟发布。如下图所示,在这种情况下,每个角色都不开心。
开发人员不开心,因为:
公司希望改变这一状况。于是,在启动“航海家”项目的同时,全面改变这种非常糟糕的软件交付状态。
这个“航海家”项目是重写Android和iOS客户端,以及移动端的Web网站,这个项目几乎是全新的,包括新的代码库,新的前端API服务和新的产品设计。
产品目标是:
每周发布;
快速迭代;
更容易做试验(experiments)
整个公司都聚焦于移动端。因为移动端对公司业务来说,越来越重要,必须做的更好,下图就是目标。
对,你没有看错!一周发布一次!
03
—
10X,需要更激进的做法
面对这一目标,工程团队的回答如下:
发布时间点应该是一个产品决策
每次最新的构建都可以发送给所有团队成员试用
工程团队需要思维改变
于是,就有了下面的这个口号:
为什么要定在3小时呢?因为,如果想在三小时内完成,团队就
没有时间做手工测试
没有时间测试所有内容
更容易强调匠艺(craftsmanship)
更容易在每个工作日的八小时内发布三个版本
部署流水线就变成了下面这个样子:
深色的部分就是要在三小时内完成的工作。
按照原来的做事方式,上面的计划根本行不通,所以必须做出重大的改变!
04
—
静态分析(Static Analysis)
Java Checkstyle
Android Lint
与后端接入层的API服务制定编译时契约
使用Linkedin 自己开源的REST框架 Rest.li
通过静态扫描来保证即使修改了API,生产环境上也不会发生向前兼容性问题
客户端的model 类是自动代码生成,以确保其正确性
使用IntelliJ的CLI 自动对代码进行格式化
05
—
代码构建(Building the code)
项目刚启动时还不错
2015年下半年,功能越多,代码就越多,构建就越慢了
2016年初,绝大部分代码仍旧放在两个Gradle Module下
06
—
APK拆分
频繁发布,就意味着需要会员App的频繁更新,我们就需要考虑会员数据的保留,以及更新包的大小。
发布版本对App进行了APK的拆分。为不同的屏幕密度和CPU架构组合构建单独的APK。每次提交总共会产生30多个APK。
这么多的APK,构建版本一定非常慢。的确是这样的。30多个APK在持续集成平台上的构建时间约为35分钟,花掉了我们三小时预算的20%。这是不能忍受的。
于是,我们每次构建都使用两台机器。其中一台机器用于构建Debug版本,并运行自动化测试。而另一台机器用于构建Release版本(30多个APK)。
构建时间的长短最终受限于最长时间的那个任务,就是构建Release版本。为了能够更快一些,我们每次构建增加到了六台机器,以后可能会增加更多。
Android Gradle Plugin 3.0在速度方面有很大的优化,在没有代码变更的情况下,速度提升大约40%。而我们已经将代码模块化,所以,速度应该能够提升更多。
我们的测试分为三层。第一层是单元测试。这没什么好说的,框架成熟,开发人员写就好了。第二层是Layout测试。你可以看做是对Views的单元测试,就是使用Dummy数据在一个Dummy Activity上加载一个Layout。使用Espresso ViewAssertions对overlaps, RTL layout等进行验证。 第三层是场景测试(Scenario tests)。主要用于验证关键业务工作流是否能正常工作。通常是涉及App多个不同屏幕交互的工作流。应用程序从设备上的夹具服务器(fixtures Server)获取模拟数据。并不是一个面面俱到的测试用例集。
我们根本不衡量类、方法和行的覆盖率。我们的目标并不是每行代码都被覆盖,我们希望的是高价值、低维护成本的测试。针对每个特性,找到对业务影响最大的操作流,并通过场景测试覆盖这个操作流的Happy Path。团队会就什么样的操作流必须被测试覆盖,并会衡量这类测试有多少个会运行。
例如,可以成功地在LinkedIn 的信息流上发布一个帖子(Post)——这就是一个场景测试。如果这个场景失败了,会对业务有很大的影响。当分享一个超过1万字的帖子里,应该提示正确的错误信息——这就会做为一个场景测试。因为,如果这个功能不能正常工作,世界也不会停止运转。而且,这类问题可以被单元测试覆盖到(由团队自己来决定好了)。
目前,每次构建运行的自动化测试用例数为6500个。一共会运行两次,一次是在提交代码之前,一次是在提交代码之后。而且,如果有测试失败,会自动回滚(Auto-Reverted)。最初的时候,每个CI服务器上只运行一个模拟器,每次构建需要6个CI服务器。现在,我们自定义了基于Gradle的测试工具,用来优化和切分测试集。现在使用一台CI服务器,运行16个模拟器。并且,我们还自定义了 HTML+JUnit的测试报表。会包含每个测试的日志数据,以及那些失败测试的截屏图片。
测试环境的稳定性对自动化测试来说是非常关键的。因此,我们自己开发了脚本,用于创建和启动模拟器。同时,也会安排专人做为环境守护工作。另外,为了测试的稳定,我们还要求每个Instrumentation指令只运行一个测试,与Android Test Orchestrator类似。每个测试开始前都会清理所有的App数据。如果因为模拟器问题而失败,会自动恢复或重试。针对测试用例的稳定性,我们要求,如果没有代码变更,只要测试成功一次,那么无论以后运行多少次都必须成功。否则就标记为“不稳定测试(Flaky Test)”。而不稳定的自动化测试还不如没有测试。
13
—
测试:主干守护者
我们指定了主干守护者。其主要工作是:发现和移除不稳定的自动化测试。即:根据最近一次成功构建,持续不断地运行其所对应的所有自动化测试。只要有一个测试失败,就将该测试用例标记为不稳定。并在Jira上自动创建一个卡片,附加上日志和截屏,并将其指定给该测试的维护人。每天发送一份日报给管理团队,标明每个团队有多少测试用例被标记为“不稳定测试”。如果不稳定测试的占比超过10%,那么在修复它们之前,自动禁止该团队提交代码。想要让某个被标记为不稳定的测试重新恢复运行,必须先修改一些代码,要么是找到并修复不稳定的原因,要么是加入更多的日志,以便下次运行失败的时候,可以得到更多的信息。
14
—
分发:Alpha版本
Alpha版本就是最新一次成功构建的版本。员工可以在App上一键安装这个最新版本,通常产品经理和那些想尽早看到最新功能的人会使用这个版本。最开始的时候,我们使用Google Play提供的Alpha 通道。每三个小时自动上传一次真正的3X3版本。但是,想看到最新代码功能的人仍旧嫌这种方式太慢。
15
—
分发:Beta版本
对于Beta版本,我们使用Google Play 的Beta通道。即开放的会员制,即使出现了严重的问题,也不会对业务有实质性的影响。我们每周发布三个版本(周一、周三和周五)。公开的Beta用户群(可以)通过Google Play给我们提交反馈。在Beta发布的四小时内,最严重的问题会通过我们的自动化测试报告出来。
16
—
分发:正式版本
每个星期三发布一次正式版本。基本上是最新且没有严重问题的那个Beta版本。如果最新的三个Beta版本都存在问题而无法发布,就跳过这次发布,并进行一次事后分析。另外,我们也利用Google Play的阶段性发布,即:一天之内逐步放量。并监控版本采纳率和崩溃率。所以,现在的发布计划如下图所示。
我们使用了LinkedIn已有的A/B测试框架,通过功能开关(Feature Flags)来控制新功能对具备哪些具体特征的会员用户开放,而且也可以用来监控新功能的性能指标。并且支持动态配置。全部由服务器端控制,所以,不需要发布新版本,就可以控制那些引发崩溃或者问题的代码。
有人会认为,我们一定存在手工测试阶段。事实上,它并不存在。我们会定期做推送通知和Deeplink的手工测试,但这并不会阻碍我们的版本发布。团队会针对新功能进行手工的Bug Bash(它是一种集体体验产品功能并发现潜在缺陷和改进的集体活动)。但同样也不会阻碍我们的版本发布。它也不是手工回归测试,只是为了确保新功能没有问题。
19
—
小结
在LinkedIn,从提交到发布的时间(C2P time)是VP这个级别非常关注的一个事情。在LinkedIn能做到这种程度,也用了差不多两年半的时间。领导团队对这件事情的Buy-in是至关重要的。在企业中,这种3X3是一种思维上的转变,自上而下的推动会使它相对容易一些。从最简单的事情开始做起,比如任何人都可以运行静态扫描,或者在持续集成嗠器上建立自动化测试的执行等。
如果你仍旧觉得无从下手,可以参考《持续交付2.0》一书的内容。它不但讲解了各方面的挑战,给出了一些解决方案,同时在最后三章,详细讲述了三个不同类型的软件团队(百人产品团队、微服务团队和大版本中的小团队)做出巨大改变的历程与步骤,希望对你有所帮助。
重磅推荐
《持续交付2.0》
硅谷顶级互联网公司的产品研发方法。
在未来十年里,
快速提升工程生产力,打造有战斗力的团队,
应对激烈的市场竞争,
这一本书就够了~
《持续交付2.0:业务引领的DevOps精要》
扫码购买
京东 77.5元
本书“重新定义”了持续交付,增补了组织管理和架构两个维度,辅助以真实案例,对诸多持续交付的原则和实践加以解读,并对持续交付过程中的取舍原则加以论述。
持续交付2.0是实现组织战略目标的组织能力,并引入双环模型理论,以及基础工作原则、组织原则和架构原则;
通过多个互联网公司案例的解读,阐述如何根据组织的当前状况,应用原则,并对最佳实践进行取舍,快速达到组织能力目标。
关于作者
乔梁
持续交付2.0 创始人
专注于软件企业组织管理
DevOps顶级大神
著有《持续交付2.0》
译有《持续交付》《软件沉思录》
关注公众号查看其他原创作品