从探索到落地,手淘引入 Swift “历险记”
背景
手淘 iOS APP 在 2019 年经过了约一年的时间,完成了 Swift 语言从调研到基础设施建设再到顺利落地业务。
手淘作为一个航母级别的 APP, 组织结构,工程结构,都是普通 APP 难以企及的,在手淘中实践犹如在沼泽地艰难探索,期间和集团内众多 Swift 爱好者,中间件负责人,一起努力探索出一条较为明朗的 Swift 落地指南。
时间轴
Swift 预研
Swift 语言在 2018 年就已经宣布 ABI 稳定是最重要的目标,虽然早在 Swift 4.x 时代, 语法就已基本不变,但受限于手淘是一个航母级 APP, 工程交付以二进制组件化为主,ABI 未稳定的 Swift 只能固定 Swift Toolchain 的版本,加之会有将近 3MB 的包大小压力,彼时都不适合引入 Swift。苹果与 2019 年 3 月 25 日发布了 Swift 5.0 版本,宣布了 ABI 稳定,彼时又让团队的 Swift 燃起了信心,架构组作为新技术的把控团队,决定在百忙之余让团队成员各自分担一些对 Swift 的调研工作。
在工作之余,我们完成了调研工作,从中得到两个比较重要的结论。
Swift 流行度
我们通过爬虫分析国内外 APP Store 排行榜 Top1000 的 APP,通过文件扫描分析得到结论。
- 国内使用 Swift 的 APP 约占比 22%,美区使用 Swift 的 APP 约占比 78%,其中美区剩余没有使用 Swift 的 APP 大部分来自中国地区本地化的产品,如抖音,快手等,可以得出一个结论,国内还是小众的 Swift,在国外已经是现状。
- Github/Stack Over Flow 社区等 Objective-C 开源库和问题提问已经基本停滞,未来我们在落地新技术,Objective-C 可能已经是最坏的打算,加之 WWDC 17 年以来,苹果不再提供 Objective-C 的示例,组内同学也多次遇见 Objective-C Bug 去社区提问,毫无热度的情况。
- 苹果在 WWDC19 年发布了 4 个 Pure Swift 框架,无法简单的被 Objective-C 混编。
未来我们极有可能因为苹果的强制推进风格和社区文化的落后产生技术踏空,无法迅速响应业务,甚至无法招聘到会使用 Objective-C 的工程师。
Swift 研发效率
Swift 从诞生之初就是一门先进的语言,主要有三个特性。
- Safe Swift 从语法层面避免了很多未定义的行为,空值访问,值类型,对工程的稳定性有非常正面的好处,曾经面试一个候选人,简单重写为 Swift 让项目的崩溃率降低 30%。
- Fast,Swift 的语言设计让更多的方法调度通过静态调度完成,语言运行时效率优于 Objective - C。
- Expressive, 富有表现力的语法特性,让代码量清晰已理解,减少的代码量约有 30%-50% 不等,简洁的代码也让一些 Bug 无处藏身,也让工程师能更高效的支撑业务发展,大大提升了研发效率。
下图是一个业务模块重写后的代码量对比:
其他不利因素
Swift 虽然在 5.0 版本完成了 ABI 稳定,但是在低版本操作系统中 (iOS 12.2 以下) 仍旧会有一些不够完美的地方。
- 在低于 iOS12.2 以下的操作系统会带来约有 3MB 的包大小问题,但幸运的是苹果放开了蜂窝数据网络下 200M 的下载大小。在 iOS13 上甚至可以超过 200MB。
- 在低于 iOS12.2 以下的操作系统会有 100-200ms 不等的启动耗时增加,但在团队同学的努力下上线了二进制重排,启动性能大幅度上升,具体分析请看 手淘架构组最新实践 | iOS 基于静态库插桩的⼆进制重排启动优化。
集团横向组织成立
在充分的说明了 Swift 的优势和未来的情况下,我们决定不再停留与各种了解,准备下决心落地 Swift,毕竟所有的 iOSer 都知道,Swift 是未来,但是喊了这么多年的口号,总需要有组织的向前推进,只有自己做了并且落地了才有未来。
在基础会议上讨论了一些 关于 Swift 落地的计划和核心任务。如 Swift 基础建设,基础库适配,Xcode 升级, 以及新框架 SwiftUI, Combine, 容器化架构等。
并逐步拆解任务,落地下去。
SwiftUI & GAIA FaaS
在了解 Swift 的同时恰逢 WWDC19, 苹果与 WWDC 推出了跨 Apple 平台下一代声明式的 UI 布局框架 “SwiftUI”。作者第一时间了解了 SwiftUI 的方方面面的特性,简洁清晰的 DSL, 表现力十足的数据流管理,能减少传统 Cocoa 命令式编程 80% 的代码,对研发效率有极大提升。
以下是一个简单的代码展示。
同时我们日常工作中一直有值班看数据大盘的诉求,有时甚至需要在外出的时候查看,之前我们不得不携带工作电脑,迫切需要一款移动值班的 APP,刚好出来的 SwiftUI 新技术可以帮助我们快速落地原型。
但此时没有后端支持,我们想到了 GAIA 平台, GAIA 平台是一款 FaaS 平台的风格,且 Swift 是一门跨平台语言,早在很早 IBM 就曾有 Serverless 服务,于是我们使用 Swift 遵守 GAIA 规范实现了一套 FaaS 服务,作为我们的数据大盘后端支撑。
之前已经编写了多篇文章分析了 SwiftUI 和 FaaS 的核心实现,这里就不再赘述。
- 新晋网红 SwiftUI——淘宝带你初体验
- 系列文章深度解读 |SwiftUI 背后那些事儿
- 历时五天用 SwiftUI 做了一款 APP,阿里工程师如何做的?
- Swift 在 GAIA 平台云端一体化的探索
SwiftUI 的未来
随着前面的调研,使用分析等,虽然 SwiftUI 在初期使用 UIKit/APPKit 在性能上略显不足于 Flutter,但是 SwiftUI 的 DSL 和其他特性比 Flutter 简介不少,相信苹果在未来的版本种会持续优化,现在的技术储备让我们可以轻松应对未来 SwiftUI 的落地。
业务模块重写
手淘在多年的历史迭代中,或多或少遗留了一些历史包袱,如 Cocoapods 不规范使用,头文件管理不规范,工程模版老旧。为了发现是否存在工程问题会导致 Swift 无法落地业务,我们尝试编写一个代码量适中的 SDK,来验证 Swift 的研发效率等提升。完成 SDK 初步重写后,我们发现了现有工程中遗留了大量的问题,导致现有的项目完全无法使用 Swift。
主要存在以下问题:
- 头文件不规范无法混编;
- 不支持 Module 无法被 Swift 导入;
- 工具链老旧支持 Swift 源码开发调试;
- Swift 5.0 不是 Module Stability, 对 Xcode 版本有强制限制。
适配基础库
为了解决 Swift 落地工程中的问题,我们结合集团 Swift 横向组织的力量,号召 Swift 爱好者,调研适配技术,编写适配文档,提供自动化工具,梳理出大量的 Swift 适配文档,推动中间件负责的同学,在不影响业务业务迭代的同时,顺手改掉历史包袱,满足 Swift 业务。
截至目前阶段,我们适配了约 100+ 基础库模块, 开启了强制打包卡口,长期有效的治理历史包袱,部分模块在治理历史包袱时,对自己的打包时常,和研发效率都有不小的提升。
适配 Xcode + Cocoapods
手淘的开发模式不同于其他中小型 APP,我们的开发团队复杂,交付方式主要由打包 SDK 二进制集成为主,但 Swift 5.1 才满足了 Module Stability,苹果于 9 月份才正式推出 Swift 5.1, 我们开始着手升级 Xcode11。
对于手淘这样的 APP, 每年升级 Xcode 也会带来大量的 Break Change Future,我们通过查看官方文档,提供适配方案,推动业务方修改了大量 Bug 适应了大量 Futuer,我们与 11 月初完成了 Xcode11 的适配工作。
同时由于 Cocoapods 1.5.x 才支持 Swift 静态库,我们将 Cocoapods 升级到了 1.7.5, 升级还带来不少 SDK 打包效率巨大的提升。
- | Xcode 10 + pod 1.2.0 | Xcode 11 + pod 1.7.5 |
---|---|---|
Swift 5.1 | 无法支持 Swift 环境 | 落地多个业务,且向前兼容 |
DarkMode | Xcode10 无法使用 DarkModeAPI | 支撑业务适配 DarkMode 已上线 |
打包时间最短时间 | 8min 左右 | 5 分 30s |
打包时间平均时间 (Debug) | 14.5 | 8 min |
打包时间平均时间 (Release) | 14.2 | 9.7 min |
源码环境构建 (初次 pod install) | 3 分钟 | 1 分钟 |
源码环境(增量构建) | 1 分钟 | 20s |
Swift 二进制不兼容研究
Swift 是一门相对静态的语言,不同于 Objective-C 大部分通过 msg_send 动态调度,静态语言需要访问到其他依赖 SDK 的数据结构的静态布局信息,且手淘的研发方式是二进制依赖交付,容易造成下层 SDK 升级未通知上层 SDK 升级重新编译,带来的二进制不兼容问题很有可能留到线上在爆发,Swift 5.1 同时带来的 Library evoluation 功能帮助我们避免二进制不兼容问题发生。
以下是一份会打破二进制不兼容的 API 变动列表:
Change | Normal struct | @frozen struct |
---|---|---|
Adding fields | Allowed | Affects ABI |
Reordering fields | Allowed | Affects ABI |
Removing ABI-public fields | Affects ABI | Affects ABI |
Removing non-ABI-public fields | Allowed | Affects ABI |
Changing the type of an ABI-public field | Affects ABI | Affects ABI |
Changing the type of a non-ABI-public field | Allowed | Affects ABI |
Changing a stored instance property to computed | Allowed | Affects ABI |
Changing a computed instance property to stored | Allowed | Affects ABI |
Changing the access of a non-ABI-public field | Allowed | Allowed |
Marking an internal field as @usableFromInline | Allowed | Allowed |
Changing an internal ABI-public field to be public | Allowed | Allowed |
业务完成
完成以上基本工作后,我们把之前重写的 SDK 通过回归测试后在手淘新版本正式上线,上线后的业务调用量等同于手淘 UV,且 0 Crash, 对开发同学造成了极大的鼓舞,多位同学主动尝试使用 Swift 落地业务。
培训
在初期的业务落地中,我 Review 了大量的代码,发现各位同学写的代码还带有浓浓的 Objective-C 风格,甚至由于不习惯可选类型,引入了强制解包等语法,这些语法会在安全性造成隐患,极易 Crash,我们了解到大量的同学 “看的懂 Swift 语法,但应对不了 Swift 风格和混编环境” 为了解决这些问题,我们组织了集团一些 Swift 大牛,指定规划了一列课程帮助各位开发者轻松的过渡到 Swift 开发环境中 未来我们会考虑向业界开发者提供,敬请期待。
未来已来
手淘在完成 Swift 落地实践中产出了大量的适配文档,工具,教程,方法论,在 2019 年初我们指定的目标和方向已经基本完成,我们做到了!!!在 Swift 诞生这 6 年时间里,各位开发者一直在声称 Swift 是未来,但是在我们手淘架构组的努力下,Swift 不再是未来,而是此刻。
在接下来的计划里,我们会提供一种渐进式的 SDK 迁移方案,逐步将老旧 SDK 迁移到 Swift 中去,Swift 的高效研发效率和安全性将更易支撑业务的快速发展。
本文转载自公众号淘系技术(ID:AlibabaMTT)。
原文链接:
https://mp.weixin.qq.com/s/oHGkoGzhMs-l8TX6t0831w
(免责声明:本网站(https://c.shenzhoubb.com)
内容主要来自原创、合作媒体供稿和第三方投稿,凡在本网站出现的信息,均仅供参考。本网站将尽力确保所提供信息的准确性及可靠性,但不保证有关资料的准确性及可靠性,读者在使用前请进一步核实,并对任何自主决定的行为负责。本网站对有关资料所引致的错误、不确或遗漏,概不负任何法律责任。本网站刊载的所有内容(包括但不仅限文字、图片、LOGO、音频、视频、软件、程序等)版权归原作者所有。任何单位或个人认为本网站中的内容可能涉嫌侵犯其知识产权或存在不实内容时,请及时通知本站,予以删除。)