NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

从探索到落地,手淘引入 Swift “历险记”

  • 2020-02-20
  • 本文字数:4031 字

    阅读完需:约 13 分钟

从探索到落地,手淘引入 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,通过文件扫描分析得到结论。


  1. 国内使用 Swift 的 APP 约占比 22%,美区使用 Swift 的 APP 约占比 78%,其中美区剩余没有使用 Swift 的 APP 大部分来自中国地区本地化的产品,如抖音,快手等,可以得出一个结论,国内还是小众的 Swift,在国外已经是现状。

  2. Github/Stack Over Flow 社区等 Objective-C 开源库和问题提问已经基本停滞,未来我们在落地新技术,Objective-C 可能已经是最坏的打算,加之 WWDC 17 年以来,苹果不再提供 Objective-C 的示例,组内同学也多次遇见 Objective-C Bug 去社区提问,毫无热度的情况。

  3. 苹果在 WWDC19 年发布了 4 个 Pure Swift 框架,无法简单的被 Objective-C 混编。


未来我们极有可能因为苹果的强制推进风格和社区文化的落后产生技术踏空,无法迅速响应业务,甚至无法招聘到会使用 Objective-C 的工程师。



Swift 研发效率

Swift 从诞生之初就是一门先进的语言,主要有三个特性。


  1. Safe Swift 从语法层面避免了很多未定义的行为,空值访问,值类型,对工程的稳定性有非常正面的好处,曾经面试一个候选人,简单重写为 Swift 让项目的崩溃率降低 30%。

  2. Fast,Swift 的语言设计让更多的方法调度通过静态调度完成,语言运行时效率优于 Objective - C。

  3. Expressive, 富有表现力的语法特性,让代码量清晰已理解,减少的代码量约有 30%-50%不等,简洁的代码也让一些 Bug 无处藏身,也让工程师能更高效的支撑业务发展,大大提升了研发效率。



下图是一个业务模块重写后的代码量对比:


其他不利因素

Swift 虽然在 5.0 版本完成了 ABI 稳定,但是在低版本操作系统中 (iOS 12.2 以下) 仍旧会有一些不够完美的地方。


  1. 在低于 iOS12.2 以下的操作系统会带来约有 3MB 的包大小问题,但幸运的是苹果放开了蜂窝数据网络下 200M 的下载大小。在 iOS13 上甚至可以超过 200MB。

  2. 在低于 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 的核心实现,这里就不再赘述。


  1. 新晋网红SwiftUI——淘宝带你初体验

  2. 系列文章深度解读|SwiftUI 背后那些事儿

  3. 历时五天用 SwiftUI 做了一款 APP,阿里工程师如何做的?

  4. Swift 在 GAIA 平台云端一体化的探索

SwiftUI 的未来

随着前面的调研,使用分析等,虽然 SwiftUI 在初期使用 UIKit/APPKit 在性能上略显不足于 Flutter,但是 SwiftUI 的 DSL 和其他特性比 Flutter 简介不少,相信苹果在未来的版本种会持续优化,现在的技术储备让我们可以轻松应对未来 SwiftUI 的落地。

业务模块重写

手淘在多年的历史迭代中,或多或少遗留了一些历史包袱,如 Cocoapods 不规范使用,头文件管理不规范,工程模版老旧。为了发现是否存在工程问题会导致 Swift 无法落地业务,我们尝试编写一个代码量适中的 SDK,来验证 Swift 的研发效率等提升。完成 SDK 初步重写后,我们发现了现有工程中遗留了大量的问题,导致现有的项目完全无法使用 Swift。


主要存在以下问题:


  1. 头文件不规范无法混编;

  2. 不支持 Module 无法被 Swift 导入;

  3. 工具链老旧支持 Swift 源码开发调试;

  4. 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.0Xcode 11 + pod 1.7.5
Swift 5.1无法支持Swift环境落地多个业务,且向前兼容
DarkModeXcode10 无法使用DarkModeAPI支撑业务适配 DarkMode 已上线
打包时间最短时间8min左右5 分 30s
打包时间平均时间 (Debug)14.58 min
打包时间平均时间 (Release)14.29.7 min
源码环境构建 (初次 pod install)3分钟1分钟
源码环境(增量构建)1分钟20s

Swift 二进制不兼容研究

Swift 是一门相对静态的语言,不同于 Objective-C 大部分通过 msg_send 动态调度,静态语言需要访问到其他依赖 SDK 的数据结构的静态布局信息,且手淘的研发方式是二进制依赖交付,容易造成下层 SDK 升级未通知上层 SDK 升级重新编译,带来的二进制不兼容问题很有可能留到线上在爆发,Swift 5.1 同时带来的 Library evoluation 功能帮助我们避免二进制不兼容问题发生。


以下是一份会打破二进制不兼容的 API 变动列表:


ChangeNormal struct@frozen struct
Adding fieldsAllowedAffects ABI
Reordering fieldsAllowedAffects ABI
Removing ABI-public fieldsAffects ABIAffects ABI
Removing non-ABI-public fieldsAllowedAffects ABI
Changing the type of an ABI-public fieldAffects ABIAffects ABI
Changing the type of a non-ABI-public fieldAllowedAffects ABI
Changing a stored instance property to computedAllowedAffects ABI
Changing a computed instance property to storedAllowedAffects ABI
Changing the access of a non-ABI-public fieldAllowedAllowed
Marking an internal field as @usableFromInlineAllowedAllowed
Changing an internal ABI-public field to be publicAllowedAllowed

业务完成

完成以上基本工作后,我们把之前重写的 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


2020-02-20 10:003855

评论

发布
暂无评论
发现更多内容

模块一的命题作业

月影之臣

架构实战营

数字货币合约交易系统开发内容(源码)

数字货币合约交易APP系统开发介绍(案例)

现成秒合约交易APP系统开发模板

架构营模块一作业

GTiger

架构实战营

模块一

迪马

理解 std::declval 和 decltype

hedzr

算法 元编程 C++11 c++17 纯虚函数

pygame 二次 hello world 项目感知

梦想橡皮擦

10月月更

持续测试、持续集成、持续交付、持续部署和DevOps

FunTester

持续集成 持续交付 持续测试 FunTester 持续构建

官方线索|#1024小鹏汽车科技日#如约而至!关于未来出行,你有什么想象?

搬砖人

1024我在现场

Vue进阶(幺肆叁):如何用绝对定位(position:absolute)完美定位布局及其注意事项

No Silver Bullet

Vue 绝对定位 10月月更

ZooKeeper分布式配置——看这篇就够了

牧小农

zookeeper 分布式配置

数字货币期权交易软件系统开发内容(源码搭建)

永续合约软件系统开发源码搭建

Shopee ClickHouse 冷热数据分离存储架构与实践

Shopee技术团队

数据库 后端 Clickhouse 存储 S3

架构3期模块一作业

渐行渐远

架构实战营

代码质量管理:SonarQube + Jenkins Pipeline配置

看山

DevOps 10月月更

【LeetCode】加一Java题解

Albert

算法 LeetCode 10月月更

👊 【Spring技术特性】采用protostuff和kryo高性能序列化框架实现RestTemplate的序列化组件

洛神灬殇

spring 序列化协议 序列化机制 10月月更

ARouter 在多 module 项目中实战

逆锋起笔

android arouter 路由框架 阿里arouter

OpenMLDB: 一文了解窗口倾斜优化技术细节

第四范式开发者社区

机器学习 数据库 开源技术 OpenMLDB

Java 面试八股文之数据库篇(三)

Dobbykim

对自己深度学习方向的论文有idea,可是工程实践能力跟不上,实验搞不定怎么办?

Giant

自然语言处理 机器学习 深度学习 算法 论文

永续合约APP系统开发简介(搭建)

有了这个告警系统,DBA提前预警不是难题

华为云开发者联盟

数据库 监控 GaussDB(DWS) 智能监控 告警系统

Go 中如何写注释

baiyutang

golang 10月月更

【Flutter 专题】23 图解自定义 Dialog 对话框

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 10月月更

期货合约系统APP开发简介(搭建)

技术分析| WebRTC开源服务器商业化过程中遇到的问题及挑战

anyRTC开发者

开源 音视频 WebRTC 服务器 实时通信

百度商业托管页系统高可用建设方法和实践

百度Geek说

架构 高可用

从零到熟悉,带你掌握Python len() 函数的使用

华为云开发者联盟

Python 数据结构 函数 内置函数 len()

从探索到落地,手淘引入 Swift “历险记”_架构_姜沂(倾寒)_InfoQ精选文章