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.