注:本文是重发公众号上的旧文

昨天,我参加了沪江主办的沪江技术沙龙 / 沙龙,这也是我今年第一次参加技术沙龙。这次参加线下活动开阔了眼界,也认识了一些新朋友。毕竟埋头苦干、坐井观天是不行的,热爱技术的更加要有一颗开放的、有追求的心。

640.jpeg

本来我是打算不写这篇文章的,因为懒啊,但是一想到再懒下去,以后就很难再改变了,很可能就一直傻下去了,所以我也来梳理一下我这次参会的见闻和感受。

关于线下沙龙


如何及时获取线下活动信息

关于这次沙龙的信息是一开始在技术交流群里看到的,后来在微博上也看到了,所以想参加一些线下活动的话,平时可以多关注一下微博。另外一些技术网站上也会公布一些活动,比如 SegmentFault,InfoQ,Swift 社区。

参加线下技术沙龙的意义

在去现场的路上我一直在想,参加线下技术沙龙的意义是什么呢?@vczero 曾经在知乎上也间接回答了我提的这个问题,粗想了一下,我觉得其意义不外乎一下几个方面:

  • 自己正好在学或者用到相关的技术,可以借这个机会去学习交流一下
  • 开阔(zhao)视野(nve),看看业界大拿们都在玩什么,怎么玩的,为什么要这么玩
  • 拓展人脉,混个脸熟,可以方便日后的技术交流,也可以“互挖墙脚”
  • 学习人家是怎么做分享、做演讲,和总结工作的,其实大多数技术分享都是来源于日常工作的,就像我的一位同事经常说的,“遇到问题是提高自己水平的最佳机会
  • 纯粹是为了打发时间,出去透透气,对于那些平时要么工作忙,要么宅在家的同学来说,确实是不一样的体验

从以上几个出发点来看,我们就知道哪些活动该去,哪些活动可以不必去凑热闹了。个人观点是,水平太低或者太高的都不必去,一年去个三五次就差不多了。

听讲座的正确姿势

我以前也参加过不少沙龙,但更多的是英语口语沙龙之类的,技术沙龙倒是去的不多。线下活动一般有两种形式,讨论为主的和讲座为主的。这次的沪江技术沙龙 / 沙龙 就是以讲座为主的形式。

至于该怎么听讲座?我姑且说说我的一点收获和反省:

  • 提前看看会议日程,看看都有哪些人,讲什么主题,找出自己感兴趣的那几场,把主要精力放到那几场上,关注核心的地方,如果你听着想睡觉,基本上也就没什么意思了
  • 不要做伸手党,我们在学生时代已经经历过太多的灌输思想了,听干货,不光要吸收,更要质疑,别人的经历不可复制,别人的干货不要直接纳入自己的知识体系,需要经历消化吸收、独立思考和验证的过程
  • 不光关注干货本身,还要看看干货的生产过程,也就是演讲者的成长经历,为什么有些人有很多干货可以分享,而有些人什么都没有?看看他们面临过什么问题,然后又是如何思考和寻找解决方案的,还有他们采取了什么行动、做出了何种选择后,才得出了今天的干货,设想一下如果自己面临同样的问题,又会得出来什么样的成果?
  • 学习如何做一个优秀的分享者、演讲者,每个演讲都有可学习的地方,比如容易引起共鸣(方向)、PPT / keynote 的设计(视觉)、内容的组织整理、清晰的思路、语言风格和肢体语言(趣味、自然),等等。那些经常演讲的分享者往往是最好的学习榜样,可以找一个适合自己风格的演讲者研究一下
  • 对整个演讲的结构思路要了解,对于有启发的、关键的地方,适当做些笔记,哪怕是一点点,回去后尽早作总结,学东西不在于多,在于精
  • 要敢于提问,但不要为了提问而提问,尽量跟自己平时遇到的问题挂钩,表达尽量清晰、具体,提问是门技术活,最好读读有关如何提问的建议

一些见闻


现在说说我的一些收获吧(还好昨天做了笔记)。

嘉宾和主题

这次分享的嘉宾有四位:

  • 《UI性能优化三招》(沪江 - 周斌)
  • 《iOS FlexBox Layout》(饿了么 - 沈强)
  • 《Swift 内存布局》(思科 - 刘芳林)
  • 《一个 5800 行文件的重构历程》(聚力体育 - 任凯)

1. UI性能优化三招(周斌)

UI 卡顿是我们平时在开发中会经常遇到的问题,但是一般在页面不太复杂情况下,问题也不会太明显,最常见的也就是圆角造成的离屏渲染,再加上硬件设备性能的提升,所以我们平时也不太会重视这方面的优化。

周斌以沪江开心词场的单词详情页为背景——左右快速滑动详情页时会出现明显的卡顿,讲解了他们解决卡顿的过程:
首先用 Profile 工具进行分析,找出比较耗时的地方,然后分别从两个方面入手:
① 数据加载的优化:使用列车算法(这个部分没看太清,印象也不太深)
② 屏幕图像显示的优化:

  • 减轻 CPU 的负担——通过对比分别使用 AutoLayout 和 frame 时的性能差异,对于复杂页面采用 frame 的方式来布局控件
  • 减轻 GPU 的负担——解决圆角造成的离屏渲染

③ 除了以上两方面的优化之外,周斌和他们团队还尝试了使用异步绘制 UI 的方式(GCD + CALayer),也就是抛弃了 UIKit 的原生控件,自己写一套 UI 绘制方案来决定何时绘制、如何绘制。他还推荐了 facebook 提供的 AsyncDisplayKit 来作为异步绘制的第三方解决方案。

640-2.jpeg

这两年,关于如何解决 UI 卡顿的问题,业界大厂牛人们也有过不少讨论,比较有代表性的就是 YYKit 作者的 《iOS 保持界面流畅的技巧》、微信团队的《微信 iOS 卡顿监控系统》,这些关于提高性能的文章中提到了很多底层知识,平时老说底层知识有啥用,这个时候就体现出来了。
我之前一直以为异步绘制在开发中是基本上不会用到,除非特别的场景,现场当时也有听众提出了一些不同的观点,我觉得这是很有意思的一件事,百家争鸣,技术讨论就要这种氛围。
对于新技术的应用,比如ReactiveCocoa、React Native,我们也要考虑到学习成本、投入产出比、代码侵入性、潜在风险等问题,所以在投入实际应用前,最好要做好充分了解和实践验证的工作。

2. iOS FlexBox Layout(沈强)

iOS 中的 UIView 布局一直比较蛋疼,感觉不像安卓(XML)和前端(css)那么方便、容易理解。 用 frame 的话,代码要写一大堆,可读性差;用自动布局的话,可以选择 Masonry / SnapKit 来手写约束代码,比起 frame 是要好很多,但是在复杂页面中性能会下降,当然我们还可以用 xib/storyboard 来创建 view、添加约束,可以少写很多代码,但是其弊端也不少,维护成本高,想起每次点开 xib/storyboard 都要卡一下就纠结,所以业界中争议不小,之前也听说过 sunny 他们团队就用的比较多。

沈强向我们介绍了一种类 FlexBox 的框架 FlexBoxLayout(不知道是不是 受了 React Native 和 weex 的启发),FlexBoxLayout 借鉴了 css 中的 FlexBox 布局,具有以下特点:

  • 基于 facebook 开源的跨平台布局引擎 yoga
  • 提供一些 flexbox layout 布局方式
  • 像 Masonry 一样支持链式调用,布局方便
    虚拟视图Div
  • TableView 支持自动高度、布局缓存,contentView缓存,和自动cache 失效机制
  • ScrollView 支持自适应contentSize
    异步计算布局

关于页面布局的方案,主要考虑的问题有两点,一个是好用,另一个就是性能不能太差。我之前也比较倾向于前端开发中用 css 管理控件位置、样式的方式,微信团队就曾经分享过他们的方案,一套屏幕尺寸对应一个 css 样式表配置文件,不过这个样式表中的格式都是自己约定好的,但是他们具体是怎么解析和设置控件的,并没有公布。后来我也打算尝试也采取这种方式来设置 view,先后参考了 NUI 和 StyleKit 框架,发现他们跟微信的做法还是有些区别的,这些框架中都只能配置样式、不能配置布局,而且是像 css 中一样,以“类”为最基础单位来配置的,而不能精确到每一个单独控件。后来我想尝试将这两个框架和微信的方案结合起来,意识到如果像微信那样将配置粒度细化到每个控件的话,可能会存在性能问题,尤其是复杂的页面,我当时想验证一下,可惜由于后来工作太忙,写一个这样的框架的工作量也比较大,就不了了之了。

3. Swift 内存布局(刘芳林)

Swift 已经到 3.0 了,我今年也开始学 Swift 了,单纯从语法上看,跟 Objective-C 相比,Swift 还是有很多优点的——更灵活、更安全、更简洁。从 Objective-C 到 Swift,难免会带着 Objective-C 的思维,一开始写 Swift 更像是把 Objective-C 直接“翻译”成 Swift。

刘芳林讲的内容还是比较偏底层的抽象理论,所以听起来还是比较烧脑,但也能感受到他的深厚功底。刘芳林主要介绍了 Swift 中的内存分配:

  • Swift值类型和值类型和引用类型内存分配和布局
  • 值类型和引用类型的效率,包括内存分配的效率和访问内存的效率
  • Copy-on-write技术结合值类型和引用类型的优点
  • protocol是引用类型还是值类型?
  • protocol类型的变量的内存布局

印象比较深的是他从内存管理的角度讲解了什么时候用值类型,什么时候用引用类型,值类型是分配到栈上的,每次赋值都是 copy,引用类型是分配到堆上的,不同变量可以指向同一个引用类型的内存区域,所以我们在选择使用值类型和引用类型时,可以往内存分配方面想想。
以后有机会还是要再重新学一下 C++,感觉每次提到一些关于语言特性的底层知识都会扯上 C++。
640-3.jpeg

4. 一个 5800 行文件的重构历程(任凯)

重构是个沉重的话题,重构意味着成本,意味着我们需要冒着风险,花费不少时间去重新设计组合原来的逻辑。如果把代码当做一篇文章来看,一篇好文章是经历过一改再改的,思路也是越改越清晰,写代码也是如此。但写代码又有些不同之处,文章写出来的最终目的是给人看的,而代码的首要目标是要实现功能,并且良好运行的,所以重构本身并不直接创造“价值”,一旦修改,就很有可能导致原有功能的破坏,而且,这也是很多人会说的,先实现需求再考虑优化。最好的重构,是一开始编码的时候就尽量想清楚怎么设计。

任凯以 PPTV 的播放器页面为例, 介绍了他是如何将高达 5800 行的 PlayerViewController 重构至 700 多行的:

  • 重构前理清核心播放逻辑、其他业务逻辑以及相关的 UI 层的结构划分
  • 按不同功能进行模块划分
  • 进行项目结构重组(按照可重用度从低到高):基础(开源第三方库、公用工具类)—> 企业内部公用业务层 —> 项目共用业务层 —> 项目具体业务
  • 借助 POP 等手段来最大化地降低耦合度

640-4.jpeg

在问答环节中有个同学提了个很有启发性的问题,他向老板和 leader 反映需要项目中有些页面的代码重构,但是被 leader 以“还能继续用”的理由直接否决了,所以我们应该怎么跟老板和 leader 说呢,究竟什么情况下才需要重构呢?

任凯对此提出了一些建议,一个项目的重构,可以从很小的地方开始改,不必要一上来就大刀阔斧地改,或者直接推倒重来;重构是需要成本的,当代码乱到了一定程度,的确是很有必要去重构,首先我们要看自己是否足够有能力去控制重构的风险和成本,如果你对自己对于业务的了解程度、技术的掌握程度以及经验丰富程度有足够的信心,并且已经想好了一个比较完善的重构方案,可以直接跟你的 leader 去沟通。(原话记不得了,大意是这么说的)

我个人觉得重构和设计模式都是比较有意思的事情,但是真正去实践都是需要很多积累和思考作支撑的。之前刚开始做新项目时,读过一些不错的文章,读后受益匪浅,都是值得反复研读和实践的:

  • iOS 应用架构谈系列(Casa Taloyum)
  • objc.io - Issue 1 Lighter View Controllers系列
  • objc.io - Issue 13 Architecture
  • MrPeak杂货铺-架构系列文章
  • 被误解的MVC和被神化的MVVM(唐巧)
  • 猿题库 iOS 客户端架构设计(蓝晨钰)
  • 面向切面编程(禅与 Objective-C 编程艺术)

一些感受


最大的收获是,做技术,还是需要沉淀,能静得下心去钻研,把一件事做到极致。
非常喜欢这种分享交流的氛围,比较喜欢的、有共鸣的还是任凯大哥的分享,听下来思路清晰、接地气、风趣幽默!
感谢沪江提供的平台,感谢各位嘉宾的分享!

最后跟大家分享一副对联(任凯大哥的 PPT 中看到的)

上联:这个需求很简单
下联:怎么实现我不管
横批:明天上线

O(∩_∩)O哈哈~