You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

144 lines
12 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 31 | 了解移动App的持续交付生命周期
你好我是王潇俊。今天我和你分享的主题是了解移动App的持续交付生命周期。
我已经和你分享完的前30个主题里介绍的都是偏向后端持续交付体系的内容。在服务端持续交付的基础上我会再用两篇文章和你聊聊移动App的持续交付。
与后端服务相比移动App的出现和工程方面的发展时间都较短所以大部分持续交付的流程和方法都借鉴了后端服务的持续交付。但是移动App因为其自身的一些特点比如版本更新要依赖用户更新客户端的行为等所以移动App的持续交付也呈现了一些独有的特点。
同时移动App的持续交付也存在一些痛点。比如没有主流的分支模型甚至产生了Android开发团队使用Gerrit这样一个独特代码管理平台和分支模型的特例又比如移动App的编译速度也随着应用越来越大变得越来越慢再比如Apple Store审核慢、热修复困难等问题。
这样总体来看移动App的持续交付体系的搭建完全可以借鉴服务端的持续交付的经验。然后再针对移动App固有的特点进行改进和优化。
因此在这个系列我只会通过三篇文章和你分享移动App持续交付体系的特色内容而对于共性的内容部分你可以再次回顾一下我在前面所分享的内容。如果你感觉哪里还不太清楚的话就给我留言我们一起讨论解决吧。
作为移动App的持续交付系列的第一篇文章我会和你一起聊聊移动App交付涉及的问题、其中哪些部分与后端服务不太一样以及如何解决这些问题打造出一套持续交付体系。
## 代码及依赖管理
**首先和后端服务一样移动App的持续交付也需要先解决代码管理的问题**。
我在专栏的第四篇文章[《一切的源头,代码分支策略的选择》](https://time.geekbang.org/column/article/10858)中和你分享了各种代码分支策略比如Git Flow、GitHub Flow 和 GitLab Flow这三种最常用的特性分支开发模型的思路、形式以及作用。
对于移动App来说业界流行的做法是采用“分支开发主干发布”的方式并且采用交付快车的方式进行持续的版本发布。
关于这种代码管理方式我会在下一篇文章《细谈移动App的持续交付流水线pipline》中进行详细介绍。
**其次移动App的开发已经走向了组件化所以也需要处理好依赖管理的问题**。
移动端的技术栈往往要比统一技术栈的后端服务更复杂,所以在考虑依赖管理时,我们需要多方位地为多种技术栈做好准备。比如:
针对 Android系统业界通常使用Gradle处理依赖管理的问题。Gradle是一个与Maven类似的项目构建工具。与Maven相比它最大的优点在于使用了以Groovy为基础的DSL代替了Maven基于XML实现的配置脚本使得构建脚本更简洁和直观。
针对iOS系统我们则会使用CocoaPods进行依赖管理。它可以将原先庞大的iOS项目拆分成多个子项目并以二进制文件的形式进行库管理从而实现对iOS的依赖管理。另外这种管理依赖的方式还可以提高iOS的构建速度。
除了以上两个技术栈外移动App还会涉及到H5、Hybrid等静态资源的构建、发布和管理。那么同样的我们也就需要Nexus、npm等构建和依赖管理工具的辅助。
可以说移动App的技术仍旧在快速发展中与后端服务比较成熟和统一的状态相比我们还要花费更多的精力去适配和学习新的构建和依赖管理工具。
## 项目信息管理
项目信息管理主要包括版本信息管理和功能信息管理这两大方面。
**对于移动App的持续交付来说我们特别需要维护版本的相关信息并对每个版本进行管理**。
对后端服务来说,它只要做到向前兼容,就可以一直以最新版本的形式进行发布;而且,它的发布相对自主,控制权比较大。
但对移动App来说情况则完全不同了一方面它很难保证面面俱到的向前兼容性另一方面它的发布控制权也没那么自主要受到应用商店、渠道市场和用户自主更新等多方面因素的影响。
所以在移动App的持续交付中我们需要管理好每个版本的相关信息。
另外为了提高移动App的构建和研发效率我们会把整个项目拆分多个子项目而主要的拆分依据就是功能模块。也就是说除了从技术角度来看移动App的持续交付会存在依赖管理的内容外从项目角度来看也常常会存在功能依赖和功能集成的需要。所以**为了项目的协调和沟通,我们需要重点管理每个功能的信息。**
可见做好项目信息管理在移动App的持续交付中尤为重要而在后端服务的持续交付中却没那么受重视了这也是移动App的持续交付体系与服务端的一大不同点。以携程或美团点评为例它们都各自研发了MCD或MCI平台以求更好地管理项目信息。
## 静态代码检查
静态代码检查的内容,就和后端服务比较相似了。为了提高移动端代码的质量,业界也陆续提供了不少的静态代码检查方案。比如:
* Clang Static Analyzer被Xcode集成但其缺乏代码风格的检查可配置性也比较差
* OCLint其检查规则更多也更易于被定制
* Infer是Facebook提供的一款静态检查工具具有大规模代码扫描效率高、支持增量检查等特点。
我们也可以很方便地把这些静态检查工具集成到移动App的持续交付当中去。基本做法你可以参考我在第25篇文章[《代码静态检查实践》](https://time.geekbang.org/column/article/14407)最后分享的Sonar代码静态检查的实例的内容。
## 构建管理
移动App构建管理的大体流程我们可以借鉴后端服务的做法通过代码变更触发自动的持续集成。集成过程基本遵循拉取代码、静态检查、编译构建、自动化测试以及打包分发的标准过程。
移动App和后端服务的持续交付体系在构建管理上的不同点主要体现在以下三个方面
1. **你需要准备 Android 和 iOS 两套构建环境**而且iOS的构建环境还需要一套独立的管理方案。因为iOS的构建环境你不能直接使用 Linux 虚拟机处理而是要采用Apple公司的专用设备。
2. **在整个构建过程中,你还要考虑证书的管理**,不同的版本或使用场景需要使用不同的证书。如果证书比较多的话,还会涉及到管理的逻辑问题,很多组织都会选择自行开发证书管理服务。
3. **为了解决组件依赖的问题,你需要特别准备独立的中央组件仓库,并用缓存等机制加快依赖组件下载的速度**。其实,这一点会和后端服务比较相像。
## 发布管理
移动App的发布管理和后端服务相比相差就比较大了。
**首先移动App无法做到强制更新决定权在终端用户**。移动App的发布你所能控制的只是将新版本发布到市场而已而最终是否更新新版本使得新版本的功能起效则完全取决于用户。这与后端服务强制更新的做法完全不同。
**其次移动App在正式发布到市场前会进行时间比较长的内测或公测**。这些测试会使用类似Fabric Beta 或者 TestFlight 这样的 Beta 测试平台,使部分用户优先使用,完成灰度测试;或者在公司内部搭建一个虚拟市场,利用内部资源优先完成内测。而且,这个测试周期往往都比较长,其中也会迭代多个版本。
**最后移动App的分发渠道比较多样**。还可能会利用一些特殊的渠道进行发布。为了应对不同的渠道的需求,比如标准渠道版本,控制部分内容,一些字样的显示等等。在完成基本的构建和打包之后,还需要做一些额外的配置替换、增删改查的动作。比如,更新渠道配置和说明等。
以上这些因素就决定了移动App与后端服务的发布管理完全不同。关于移动App的发布我会在下一篇文章《细谈移动App的持续交付流水线pipeline》中进行详细介绍。
## 运营管理
移动App发布之后还有一件比较重要的事项那就是对每个版本的运营管理。
这里讲的运营主要是指,追踪、分析和调优这个版本发布的表现和反馈。我们运营时,主要关注的内容包括:奔溃报告、区域分析、用户分析、系统资源消耗、流量消耗、响应时长、包体大小、系统监控,以及预警等。
通常,我们也会对比版本之间的这些运营指标,以判断应用是变好了,还是变坏了。
## 热修复
后端服务修复Bug的方式一般是发现Bug后可以立刻再开发一个新版本然后通过正常的完整发布进行修复。
而移动App的发布需要用户安装才能起效这就决定了它不能采用后端服务修复Bug的方式。因为这会要求用户在很短的时间内重新安装客户端这样的用户体验相当糟糕。
但是我们也无法避免Bug。所以对移动App来说我们就要通过特定的热修复技术做到在用户不重新安装客户端的前提下就可以修复Bug。这也就是我所说的热修复。
关于热修复,比如**Android系统**,主要的方式就是以下两步:
1. 下发补丁内含修复好的class到用户手机
2. App通过类加载器调用补丁中的类。
其实现原理主要是利用了Android的类加载机制即从DexPathList对象的Element数组中获取对应的类进行加载而获取的方式则是遍历。也就是说我们只需要把修复的类放置在这个Element数组的第一位就可以保证加载到新的类了而此时有Bug的类其实还是存在的只是不会被加载到而已。
当然技术发展到今天我们已经无需重复造轮子了完全可以利用一些大厂开放的方案和平台完成热修复。比如百川的hHotFix、美团Robust、手机QQ空间、微信Tinker都是很好的方案。
**iOS系统方面**Apple公司一直对热修复抓的比较严。但是从iOS7之后iOS系统引入了JavaScriptCore这样就可以在Objective-C和JavaScript之间传递值或对象了从而使得创建混合对象成为了可能。因此业界产生了一些成熟的热修复方案。比如
1. [Rollout.io](http://Rollout.io)、JSPatch、DynamicCocoa
这三个方案只针对iOS的热更新。目前Rollout.io和JSPatch已经实现了平台化脚本语言用的都是JavaScript。Rollout.io除了支持OC的热更新外还支持Swift。
DynamiCocoa源自滴滴目前还没开源所以我也没怎么体验过。但是它号称可以通过OC编码自动转换成JavaScript脚本这对编码来说好处多多。
2. React Native、Weex
这两个方案都是跨平台的热更新方案。其中React Native是由Facebook开发的 Weex是由阿里开发的。就我个人的体验来说Weex从语法上更贴近编程思路而且还实现了平台化使用起来更加便捷。
3. Wax 、Hybrid
这两个方案比较特殊。其中Wax采用的脚本语言是Lua而不是JavaScript所以比较适用于游戏而Hybrid主要面向H5Hybrid App已经被证明不是好的方案所以用户越来越少了。
## 总结
今天我主要和你分享了移动App的持续交付生命周期的几个主要部分包括代码及依赖管理、项目信息管理、静态代码检查、构建管理、发布管理、运营管理以及热修复。
然后我分享了相比于后端服务移动App的持续交付体系有哪些不同的地方。比如项目信息管理、运营管理和热修复在移动App的交付过程中被提到了更重要的位置而其他几个主要过程代码、构建、发布这三部分都因为移动App开发的特性与后端服务相比有所区别这些区别也是我要在下一篇文章中和你重点分享的内容。
## 思考题
对于移动App的交付来说版本和信息管理非常重要。你所在的公司是如何管理这些信息的有哪些可以优化的可能吗
感谢你的收听,欢迎你给我留言。