GMTC2018《从简到繁:Instagram+iOS团队如何随着产品一同成长》 李晨
2020-02-27 170浏览
- 1.成⻓长的烦恼: INSTAGRAM IOS 团队如何随着产品成⻓长 李李晨 @ Instagram
- 2.成⻓长的烦恼 • Instagram⽉月活和产品线迅速发展 - 从14年年开始,每7个⽉月增加1亿⽉月活 - 已突破10亿⽉月活 - 信息流,私信,Stories,IGTV • 成⻓长的烦恼 - 复杂的列列表 - ⼤大量量实验相互⼲干扰 - 编译时间越来越⻓长 • iOS⼯工程团队如何迎接挑战 2
- 3.演讲内容 1 复杂列列表的解决⽅方案:IGListKit + MVVM 2 ⼤大规模对照试验 3 加快编译速度:Buck + Focus + Focus Project 3
- 4.⻓长列列表:UICollectionView • UICollectionView: - ⾼高度可定制 - 业务逻辑和UI代码分离 • 听上去很美好 4
- 5.图⽚片信息流:基础代码 5
- 6.图⽚片信息流:添加点赞数 6
- 7.图⽚片信息流:添加点赞数 7
- 8.⽤用户增⻓长组:添加关注组件 8
- 9.⽤用户增⻓长组:添加关注组件 9
- 10.⻓长列列表:分散的逻辑 • UICollectionView: - ⾼高度可定制 - 业务逻辑和UI代码分离 • 理理想很美好 • 现实很残酷 - ⼏几⼗十个⼯工程师在同样⼏几个函数上反复添加逻辑 - 业务逻辑和设计需求耦合 - 代码可读性、可维护性下降 - 添加⼀一个新UI需要修改多个团队的代码 - 臃肿的ViewController代码 10
- 11.⻓长列列表:寻找成⻓长性好的框架 • 寻找⼀一个框架 - 减少团队间的代码耦合 - 让业务逻辑和设计需求分离开来 ⽤用户增⻓长团队 信息流团队 11
- 12.⻓长列列表:IGLISTKIT • 起源于列列表设计 • 增加⼀一层SectionController,分拆业务逻辑 • ⿎鼓励代码重⽤用 • ⾼高效列列表刷新机制 •https://github.com/Instagram/IGListKit12
- 13.⻓长列列表:IGLISTKIT+MVVM FeedItemModel UserModel DataModel - 原始数据 - 来⾃自缓存或服务器器 - 可能有冗余信息 FeedItemViewModel FeedItem SectionController UserHeaderCell PhotoCell 信息流团队 UserRecommendation ViewModel ViewModel - 设计需求 尺⼨寸、颜⾊色、字号 - 只包含必要信息 UserRecommendation SectionController UserRecommendation Cell SectionController - 业务逻辑 - 将ViewModel中的设计 需求和数据传递给Cell Cell - 展示数据 ⽤用户增⻓长团队 13
- 14.⻓长列列表:IGLISTKIT优化后 ⽤用户增⻓长团队 信息流团队 Data Model --> View Model 14
- 15.⻓长列列表:SECTIONCONTROLLER • 由具体⼀一个团队来维护,和其它团队代码解耦 • 专注于业务逻辑 • 设计需求已经在ViewModel和Cell当中,和业务逻 辑充分解耦 15
- 16.演讲内容 1 复杂列列表的解决⽅方案:IGListKit + MVVM 2 ⼤大规模对照试验 3 加快编译速度:Buck + Focus + Focus Project 16
- 17.对照实验:快速迭代的核⼼心⼯工具 • 通过随机抽样实验,来选择出相对较好的产品⽅方案 • 核⼼心优势:⽆无需理理解和争论复杂的⽤用户⾏行行为逻辑,直接告知结果 • Instagram等社交类产品⾯面临着复杂的⽤用户⼼心理理,需要⼀一个客观有效的⼯工具来指导产品决策;对照实验就是社交类产品 快速迭代的核⼼心⼯工具 • 良好的副产品:⽤用于发现代码中的bug • 缺点:⽤用户规模要求⾼高,实验到决策时间较⻓长 17
- 18.对照试验:案例例 添加关注组件: - 对⽤用户留留存有帮助吗?有多少帮助? - 对信息流展示量量有负⾯面影响吗?有多⼤大影响? 对照组: - 控制组:不不显示关注组件 - 实验组:显示关注组件
- 19.对照试验:案例例 ⽤用户来到⻚页⾯面时做曝光记录: if (_experimentsManager.logAndGetResult(“关注组件”)) { // 显示关注组件 } 查看结果:(7天后) - 实验组的⽤用户留留存率提升1% - 实验组的⽤用户信息流展示量量下降0.2%
- 20.对照试验:确保实验⽅方案连续性 • ⽬目标:⽤用户在同⼀一次App使⽤用体验中,其所处的实验组应当是⼀一致的 避免:启动App时处于控制组,过了了⼏几秒钟处于实验组 • 难点:App启动的⼀一瞬间,很多实验就要开始运⾏行行了了;⽤用户所处的实验组信息是通过服务器器端控制和改变的,⼏几秒钟后 才获得最新的实验⽅方案 20
- 21.对照试验:确保实验⽅方案连续性 • 解决⽅方案:启动App以后,⼀一直使⽤用之前的实验⽅方案;最新的实验⽅方案在下⼀一次App启动时才开始使⽤用 • // ⽤用户启动App时 _experimentsManager.applyOldPlanFromClientCache(); _experimentsFetcher.fetchNewPlan{ (experiments) // 保存实验⽅方案,供下次使⽤用 DiskCache.cacheExperiments(experiments); }; // ⽤用户关闭App时 if (_diskCache.experimentsChanged()) { // 强制关闭App,确保下次启动为冷启动 } 21
- 22.⼤大规模对照试验:实验的相互⼲干扰 • ⼀一个⻚页⾯面进⾏行行多个试验时,容易易出现这种实验叠加的状况: if (_experimentsManager.logAndGetResult("⻚页⾯面重构")) { if (_experimentsManager.logAndGetResult(“关注组件")) { // 新的⻚页⾯面架构,显示⼴广告预览 } else { // 新的⻚页⾯面架构,隐藏⼴广告预览 } } else { // 控制1:旧的⻚页⾯面架构 } • 关注组件实验是可靠地; ⻚页⾯面重构实验会受到污染,实验组中出现了了关注组件实验的数据,控制组却没有 22
- 23.⼤大规模对照试验:解决⽅方案1 1) 确保关注组件实验能在⻚页⾯面重构实验的控制组中⼯工作。 if (_experimentsManager.logAndGetResult("⻚页⾯面重构")) { if (_experimentsManager.logAndGetResult(“关注组件")) { // 新的⻚页⾯面架构,显示⼴广告预览 } else { // 新的⻚页⾯面架构,隐藏⼴广告预览 } } else { if (_experimentsManager.logAndGetResult(“关注组件")) { // 旧的⻚页⾯面架构,显示⼴广告预览 } else { // 旧的⻚页⾯面架构,隐藏⼴广告预览 } } 代价:⼯工程复杂度随着试验的 个数指数型增⻓长 代码量量=2^N 23
- 24.⼤大规模对照试验:解决⽅方案2 2) 空间分离: 之前2个不不同的试验,会导致⼀一个⽤用户出现在2个试验组当中的情况。 可以设计成1个试验,有三个分组: 控制组、⻚页⾯面重构试验组、关注组件实验组 同⼀一个⽤用户只可能处于⼀一个实验组中,⼯工程师不不需要考虑试验的排列列组合 代价: - 每个试验的样本空间变⼩小了了 50% —> 33.3% 试验结果的准确率会下降 - 需要不不同功能协调同时开发 24
- 25.⼤大规模对照试验:解决⽅方案3 3) 时间分离: 多个实验分先后进⾏行行。 代价:试验推进速度变得缓慢 25
- 26.⼤大规模对照试验:审视实验结果 控制组的⽤用户添加了了10000个好友,实验组添加了了10050个好友。 关注组件能够增加 0.5% 的好友关系吗? 根据实验组⼤大⼩小和实验结果的均值,来确定可信度 控制组的好友关系增加了了0.5%,但图⽚片阅读量量下降了了0.2%。 这个交换值吗? 需要团队协同做出决定 好友关系第⼀一周增加了了0.5%,第⼆二周呢?可持续吗? 需要更更⻓长的时间做出决定
- 27.⼤大规模对照试验:减少主观偏差 • ⼈人⼈人都渴望⾃自⼰己的功能和实验有好的结果 • 引⼊入多⼈人多维度解读实验: - 产品经理理、⼯工程师、设计师、数据科学家 - 考虑置信区间 - 权衡得失 - 延⻓长实验时间 - 引⼊入多⼈人共同解读实验数据,减少主观偏差 27
- 28.对照试验:避免复杂性 • 实验的代价: - 实验⽅方案需要花时间科学地确定 - ⼯工程师需要维护多套代码 - 实验结果解读费时费⼒力力 • 降低实验复杂性: - 多个⼩小改动放在⼀一个实验中进⾏行行,做整体评价 - 有些确定性的改动,绕过实验环节,直接发布 28
- 29.⼤大规模对照试验:实验解决不不了了的问题 • “如果乔布斯通过AB实验来设计⼿手机,那么世界上不不会有iPhone,只会有⼀一款更更好的诺基亚⼿手机。” • 颠覆性的产品,前期看起来往往很脆弱,⽆无法和旧的庞然⼤大物进⾏行行公平的实验。 • ⽤用实验来指导稳定的更更新和迭代,寻找产品中的bug;避免⽤用实验来指导产品⼤大⽅方向。 29
- 30.演讲内容 1 复杂列列表的解决⽅方案:IGListKit + MVVM 2 ⼤大规模对照试验 3 加快编译速度:Buck + Focus + Focus Project 30
- 31.编译速度:必经的痛苦 • 之前的努⼒力力:代码解耦重⽤用了了,试验相互分离了了,更更多⼯工程师能⽅方便便地协作了了 • 必然结果:代码量量迅速增⻓长 • XCode不不是为⼤大型代码库所设计 —— Apple⾃自⼰己⼤大量量使⽤用编译好的library,⽆无需XCode编译所有源代码 冷编译速度 ⼗十⼏几秒 三⼗十秒 ⼀一分钟 ⼏几分钟 半⼩小时 ⼯工程师⼼心情 ?????? ?????? ?????? ?????? 崩溃 31
- 32.编译加速:BUCK • 通过并⾏行行编译和结果缓存,加快编译速度 • 确保所有⼯工程师的编译环境⼀一致 •https://buckbuild.com32
- 33.编译加速:FOCUS • Buck的加速不不够,因为本地机器器依然需要编译所有的模块 • 信息流团队能否只编译信息流相关的代码?滤镜团队能否只编译滤镜相关的代码? • 服务器器针对近期的commit,编译并缓存每⼀一个模块 • ⼯工程师决定⾃自⼰己需要Focus在哪⼀一个或⼏几个模块的代码,这部分代码将从⼯工程师的机器器上直接编译;其余所有的模块直 接从服务器器下载编译好的结果 半⼩小时 ⼗十⼏几秒 ?????? 33
- 34.演讲内容 1 复杂列列表的解决⽅方案:IGListKit + MVVM 2 ⼤大规模对照试验 3 加快编译速度:Buck + Focus + Focus Project 34
- 35.⼩小结 • Instagram⼯工程团队的哲学:从简单出发 • 解决⽅方案朝未来看⼏几个⽉月,留留出⼀一定升级空间 • 产品的爆发增⻓长时,根据新的需求升级或重构基础架构 • 基础架构强调代码解耦和迭代效率 35
- 36.