gitbook/持续交付36讲/docs/40007.md
2022-09-03 22:05:03 +08:00

162 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 33 | 进阶如何进一步提升移动APP的交付效率
你好我是王潇俊。今天我和你分享的主题是进阶如何进一步提升移动App的交付效率
通过我在前面分享的《了解移动App的持续交付生命周期》和《细谈移动App的交付流水线pipeline》两个主题你应该已经比较全面和细致地理解了移动客户端持续交付的整个过程。
当然搭建持续交付体系的最终目的是提升研发效率。所以仅仅能把整个流水线跑起来肯定满足不了你的胃口。那么今天我就再和你聊聊如何进一步提升移动App的交付效率。
## 提升交付效率的基本思路
同其他很多问题的解决方式一样提升移动App持续交付的效率也是要先有一个整体思路再具体落实。
理解了移动App的交付流水线后你很容易就能发现它其实与后端服务的交付流水线十分相似。
后端持续交付流水线包括了代码管理、环境管理、集成和编译管理、测试管理以及发布管理这五个核心过程。而与之相比移动App的运行形势决定了其在环境管理方面没有特别多的要求。
所以我们可以从代码管理、集成和编译管理、测试管理以及发布管理这四个方面来考虑问题。而将这四个方面直接对应到研发流程的话就是标准的开发、构建、测试、发布过程。因此移动App持续交付流水线的优化我们只要从这四个过程中寻找优化点即可。
**我们优化移动App持续交付体系的整体思路就是**:首先找到这四个核心过程中存在的问题或瓶颈,再进行针对性的优化,从而达到提升效率的目的。
接下来,我们就逐一击破这四个核心过程中的难题吧。
## 如何提升开发效率?
从开发人员的角度看提升效率最好的方法就是2个字解耦。落到技术实现上来说就是通过组件化形成合理的开发框架。
组件化是指解耦复杂系统时将多个功能模块拆分、重组的过程。对于移动App来说可以横向地按功能模块进行组件化也可以纵向地按照架构层次进行组件化。当然目前移动App的架构往往都已经比较复杂了所以通常都是两者混合的模式。
组件化带来的好处包括:
1. **方便拆分代码仓库,降低分支管理难度,提高开发并行度。**
在上一篇文章《细谈移动App的交付流水线pipeline》中我给出了一种适应发布快车模式的代码分支管理模型。试想一下如果一个巨大的App的所有代码都集中在同一个代码仓库中而所有的并行开发功能又都会形成一个个的功能分支的话它们之间相互的影响将是难以想象的。
其实任何一个代码仓库当需要管理的并行分支超过10个时都会让人头痛。所以组件化的好处就是对整个项目进行解耦把不相干的功能组件从代码仓库这个层面进行隔离以免互相影响。
2. **组件可以多版本存在,通过依赖快速选取所需版本。**
所有的组件都可以同时发布多个版本,发布的形式可以是代码包、二进制组件等等。这样做的好处是,对于组件的提供方和依赖方来说,只需要通过版本控制就能管理或者选取自己需要的组件功能,这种方式更符合编程习惯,也降低了减少沟通成本。
3. **专业分工,形成更优的组织结构。**
一旦实施组件化,各种更专业的通用组建会慢慢形成(比如网络处理、图片处理、语音处理等等),而这些更专业的组件,也会渐渐地由更专业的人或团队进行开发和维护,专业的分工使得研发效率得到进一步提升。
所以,组件化其实就是通过专业分工,提升了整个组织的开发效率。
当然,组件化并非完美无瑕,它同时也会引起一些问题,比如:
1. **组件间的依赖问题**。由于多组件、多版本的存在,加之它们之间的传递依赖,所以组件化之后的依赖管理问题不容小觑。
2. **组件间的兼容问题**。兼容性问题,是由组件间的依赖问题引发的,由此组件的发布管理也会成为瓶颈:组件间到底要不要兼容?出现了不兼容的情况,应该怎么办?
其实,组件化带来的这些负面影响,在开发人员的维度是看不到的,往往会发生在构建阶段。还好,这些问题并不是无解的。接下来,我们就一起看看构建阶段如何解决这些问题,并提高效率吧。
## 如何提升构建效率?
从目前业界流行的处理方法来看,提升构建阶段的效率,可以从扁平化依赖管理和二进制交付两个维度解决。
**第一,扁平化依赖管理**
组件的依赖问题到底有多让人头痛。我们一起来看看图1中的组件依赖示例吧。
一个App中的两个组件B和C都依赖了组件G但依赖的却是组件G的不同版本。所以这个组件G的2个版本间就发生了冲突。
由此可见,由传递依赖带来的不确定性,是我们经常会遇见并非常讨厌的组件依赖形式。因为发现和处理的成本都很高。
![](https://static001.geekbang.org/resource/image/24/87/24a6ebb48588b8a3660d0e357b2db187.png)
图1 组件依赖冲突
通常情况下一个移动App可以拆分出十几到几十个组件。大型的移动App如淘宝、美团甚至可以拆分出几百个组件。要保证这么多组件间依赖传递的准确性其难度非常大。所以为了解决这个问题业界现在普遍直接采用扁平化的依赖管理方式减少甚至去除传递依赖以此避免组件、版本冲突的问题。
![](https://static001.geekbang.org/resource/image/d7/bc/d7892bb8128b939b28117fa5e05bfbbc.png)
图2 扁平化依赖
而且这样的扁平化管理方式对于一个App版本来说更清晰、直观。
那么,实现这种扁平化的管理方式,需要具备什么前提吗。
答案,当然是需要。这个前提就是:不同组件之间,以及不同版本之间要保证可兼容。但是,你我都清楚,要想保证全部版本的完全可兼容性,其成本是巨大的。所以,在实践中,我们不会去保证所有版本的绝对兼容,而是去实现所有版本、组件间的相对兼容性。
相对兼容性是指每个组件在发布新版本时对于其所依赖的其他组件都选择组件仓库中的最新版本。这样就保证了这个组件在发布之后的兼容性。如果所有组件都可以这么做就能保证其各自都兼容。但是这个方法不是绝对的比如我们会遇到并发发布或者多个组件间引起的功能逻辑的冲突等问题所以还是需要对移动App进行集成测试。
**第二,二进制交付**
解决了组件的依赖问题之后,我们需要再考虑的问题是,如何才能提高编译速度。
传统的移动App组件集成及编译的方式如图3所示。组件先以源码的方式集成到目标项目然后对整个项目进行编译。如果组件比较多的话采用这种方式的编译时间会非常长。有时甚至要编译1个多小时。显然我们不会接受这种低效的集成与编译方式。
![](https://static001.geekbang.org/resource/image/1f/6d/1f35512e72205887d48021e0ab3e1b6d.png)
图3 组件源码集成
所以为了加快编译速度业界通常会采用二进制交付和集成的方案。如图4所示二进制交付会优先把组件编译成二进制包再形成版本并通过组件仓库进行版本管理正如图中的组件A Lib包。在真正编译时我们只要直接链接二进制包就可以了无需再进行一次编译。
![](https://static001.geekbang.org/resource/image/42/4b/42ac7ab34eacf9eaea01c8db4affa84b.png)
图4 二进制交付及集成
使用二进制包的方式可以帮我们大幅提升移动App的编译速度。而且因为有了中间交付物我们可以采用与后端服务一样的方式在本地缓存需要依赖的组件进一步加速编译过程。
**通过对开发、构建过程的优化我们已经将原来的交付效率至少提高了1倍。**
接下来我们再一起看看如何优化测试和发布流程以求移动App的持续交付体系更高效。
## 如何提升测试效率?
提高移动App测试效率的方法主要的思路有三个
1. **代码静态扫描工具**
移动App的测试同样可以使用与后端服务一样的代码静态扫描工具。但相比之下后端服务通常使用的那些工具虽然普适性强但太重且定制的门槛也很高所以针对移动App的代码静态扫描目前多数大厂都采用自研的方式定制静态代码扫描工具。另外针对移动App开源的静态代码扫描工具如Lint等已经可以满足小团队的使用了。
2. **UI自动化测试**
这部分的关注点是成本和收益比你我都清楚UI自动化测试的脚本维护成本高导致其难以被大规模使用。所以针对重要的模块和组件有计划地使用UI自动化测试是重中之重。
3. **自动Monkey测试**
Monkey是一款非常好用的探索性测试工具可以大幅提升测试效率有效解决手工测试的盲点。iOS系统的测试由于系统限制比较多所以可以在模拟器上执行Monkey的方式。
合理地利用这些测试工具和方法,就可以有效提升客户端的测试效率。
当然在测试过程中,合理地搭配监控工具,如性能监控、白屏检测等,可以起到更好的作用。
## 如何提升发布效率?
在前面两篇文章中我提到过移动App的发布流程与后端服务相比差别较大根本原因在于移动App天生具备的分批发布特性。
所以提升移动App的发布效率我们也要采用与后端服务不一样的方式。在这里我总结了提升移动App发布效率需要注意的两个问题
1. **要注意分发的精准性**。精准性指的是,分发的目标、数量、时长,以及渠道一定要合理、有效,否则就会消耗无谓的分发成本。
这里,我和你分享一个关于分发精准性的技巧。其实,说是技巧,更不如说是大家在发布过程中容易疏忽的内容。为了进行小批量的测试,通常我们都会准备一个针对性的测试用户名单。但是,你有没有想过这份名单的更新周期呢?我看到很多组织都极少更新这份名单,其实这样既对用户体验不好,也会影响测试结果。小白鼠也要时常替换的,否则就会失去实验价值。
关于这份名单的更新周期,我的建议是:结合业务实际情况,尽量避免一个用户连续多次成为小白鼠。
2. **要注意分发的稳定性**。稳定性指的是,在分发的过程中,一定要做好监控数据的收集和分析,并且要考虑好风险的处理以及必要的回滚和热修复手段。
这里我也和你分享一个关于稳定性的技巧。提高分发稳定性的一个方法就是减少分发时更新的内容并同时减少更新的时间。而对于移动App来说静态资源包的差分发布就是一个优化方案。
比如,携程在选择静态资源包的差分发布时,就经历了这样一个优化过程:从全量包发布,到文件二进制差分,再到预差分。前两个方案都是在更新时,进行差分;而预差分则是在版本发布时,就已经做好了差分计算。与前两种方案相比,预差分的目的就是减少更新时间。但预差分的缺点是,可能要对所有要发布的版本进行差分处理,这将是一个巨大的笛卡尔积。
所以,携程在经历几次尝试后,最终选择的方案是:结合全量包发布、文件二进制差分,以及预差分三种方案的特点,形成了按需差分的方案。即,先收集用户正在使用的版本,然后只做这些版本与最新版本的差分,从而减少差分处理的成本。
在我看来确保每次分发的有效性以及每次分发都能达到预期就是提高移动App发布效率的一种最有效的手段。
## 总结
在了解了移动App持续交付体系的内容后你就可以自己去动手搭建一套持续交付体系了。持续交付体系搭建起来后我们需要考虑的问题就成了如何优化这个体系的流程提升这个体系的效率。为此我从开发、构建、测试和发布这四个核心流程的角度和你分享了一些实践经验
1. 利用组件化的思想提升开发效率,但同时也会带来组件依赖及发布的问题;
2. 利用扁平化依赖管理的方法解决组件依赖和发布的问题,同时采用二进制交付的方式,进一步提高构建效率;
3. 合理利用静态代码扫描、UI自动化、自动Monkey等测试工具和方法进一步提升测试效率
4. 确保分发的精准性和稳定性,是提升发布效率的有效手段。
至此通过持续交付移动App的三篇文章再结合着以前我分享的后端服务的持续交付体系的内容你完全可以自己厘清构建移动App持续交付体系的流程了也知道了如何去优化这个流程。
希望这些内容,可以开拓你的思路,能够帮助你解决实际项目中遇到的问题。如果你还有哪些不清楚的内容,欢迎你留言和我一起讨论。
## 思考题
在今天的分享中我介绍了一种扁平化依赖管理的方法。在实际工作中你是如何管理依赖和bundle的呢
感谢你的收听,欢迎你给我留言。