构建是软件架构静态边界划分的描述,同时也连接了相关平台的单元测试、代码质量分析、集成测试、产物优化等一些列最佳实践。

转眼间,已经在开发者工具里断断续续坚持了 4 年。曾独立为携程开发 API,UI 测试框架,参与构建平台的维护(Java、DotNet、H5等),并独立重写了移动端构建脚本。也独立维护过 H5、RN 的发布系统,参与 Crash 上报,Device Farm 建设。在蚂蚁继续参与伙伴工程平台的研发及移动端构建平台的维护与重写。平时关注各种持续交付,DevOps 相关实践,深感做好移动端构建平台之难。

什么是好的构建平台

大家都知道构建就是将源码和配置经过一系列处理变为目标容器可执行包的过程。构建平台只需能调度构建就可以了。但构建平台能否与构建真正的融合却并不简单。参考 DX 从用户的角度看,由易到难:

构建平台,为什么移动端更难做好 - 图1

1. 功能

  1. Web 界面,可以配置代码仓库,触发构建,完成打包

  2. 看到每次构建记录的日志信息

  3. 可选的执行单元测试、代码扫描、UI 测试等

  4. 版本及构建产物管理

  5. 可以自助扩展构建

2. 稳定

  1. 开发者本地和平台构建一致

  2. 代码和配置不变,构建产物不变

  3. 平台是高可用的

3. 简单

  1. Web 界面中少量的配置和输入,便可持续触发构建

  2. 提供本地 Cli 或构建插件快速触发平台构建

  3. 可以和 IDE 或本地构建工具融合

4. 直观

  1. 引入业界最好的构建工具和其它辅助工具

  2. 提供构建 Profiling,从 Web 界面洞悉整个构建过程,定位问题和瓶颈

  3. 本地构建过程也可以可选的同步云端

  4. 细粒度的构建缓存提供卓越的性能体验

  5. 单元测试,代码质量 Metric 友好展示

因此打造好的构建平台体验它应该包括以下要素:

  1. 快速稳定的构件/Image 仓库,如 Artifactory、Docker Registry、CocoaPods Specs Repo

  2. 稳定可扩展的调度平台,如整合 Jenkins、Drone、Concourse

  3. 简单好用的构建配置 DSL,如 Gitlab ci.yml、Jenkins Pipeline.yml

  4. 运维体系,如 k8s 或 Ansible、Chef、Salt

  5. 直观的 Web 交互界面

  6. 本地开发构建工具的合理引入或增强

  7. 对端中立的架构感知和现代开发实践体系

这些要素要求我们知识储备要杂还要相对的专,要有运维技能、后端开发、前端体验,还要对相应端的架构,构建标准、当代开发实践体系,平台生态有较深入的理解。搜寻移动构建平台的一些宣讲,大都止于功能和稳定性,或吹嘘性能,但对它的正确性和直观性却聊之甚少。

为何前端和服务端相对容易

前端

前端工程化一路飞跃,构建工具 Grunt、Gulp,模块打包 Webpack 等首次出现已在 2012 年后,并随着 Node 的发展,融合了服务端。看似悠久的语言,ES6 之后,工程化却站在了 Java、DotNet、Python 等肩上,并以更快的速度迭代。Docker 容器技术降低了运维的门槛,前端对命令行的接受程度更高,自带的技术时尚感,和用户体验积累,一个优秀的全栈工程师,便可以做出一个优秀的前端构建平台,简直就是全栈知识体系的自然表达。

后端

以 Java 为例,自 2000 年 Ant 的诞生,提供了 XML 构建描述,并为跨 IDE 自动化构建奠定基础。04 年,Maven,Ivy 的出现,让依赖管理变得简单,降低了构建配置难度,促进了构建标准化。07 年 Gradle 的出现,更好的平衡了构建的灵活性和一致性,经过2个大版本的迭代后,性能也随之大幅的提升。

同时 Java 世界里充满了各种标准化,构建产物单一(jar、war、osgi zip)。各种成熟的测试工具 JUnit、Spock、Mockito,Jmeter、Selenium 等。代码分析工具 FindBugs、CheckStyle、PMD、Proguard、Sonar Scan 等。

成熟和标准化,意味着稳定性。一个优秀的后端就可以完成构建平台的建设。

移动端的挑战

1. 历史包袱

通常移动端的构建平台会派生自后端,代码混在一起,并用 Java 的构建知识去抽象 Android、iOS 的构建。移动端构建平台建设初期投入低,以能跑为目标,且是一个人包揽所有工作,往往是需求业务堆积,缺乏思考,没有长远规划,且对平台构建者的发展不利。历史包袱还体现在移动端的构建数据沉淀是有流程依赖性的,且它的上下游系统,通常也历史悠久。历史包袱至少要 1 年以上的艰苦努力,才能陆续甩掉。相比前端和后端的构建平台,这已经是大头。

2. 复杂的构建流程

移动端架构相对来讲没有后端那样成熟,往往一些动态修复方案调整,业务上需要去兼容。还有一些自定义的构建插件会侵入原生构建流程,导致维护性降低。移动端碎片化严重,构建工具升级也会带来维护成本。对于多 Bundle 架构,还要将依赖管理上升到 Web UI 层面,给本地和平台的交互,一致性也带来挑战。移动端本身的工程化实践起步也过晚。再加上让后端去熟悉,没有实际开发经验。

3. 运维

Docker 相应降低了维护环境的成本,而 Mac 还没有成熟的 Docker 化方案。通常对于不到 100 台的机器,依然需要寻找传统化的运维方案。关键是,初期大家惯性地走自己折腾的道路,引入更多的问题。

4. 可持续性

我经历过整个构建团队的集体离职,和构建平台多个人的相继维护。可持续性主要体现在参与构建平台的建设者,很难获得技术上的成长和满足感,也很难沉下心去深入了解构建领域知识,觉得这些虚头巴脑,没有技术含量。

理想的团队

可见好的移动端构建平台是至少一个后端、一个中等水平的运维,还有 2 个端优秀开发者的相遇。经历过一段磨合之后,构建出可用的构建平台。对于构建平台我一直希望的是没有人专职去做,是各个端在业务开发中去积累和发现,发少量时间的一个副产品。把精力放在探索每个端的开发实践中,顺便孵化出一些好用的工具,我心里一直把这样的开发者称为开发者体验工程师。

参考