React Native 源码导读(零) – 创建/运行/调试

2017-7-31 评论(10) 分类:技术文章 Tags:

最近工作需要,重新看 React Native (以下简称RN) 源码,了解机制,寻找优化空间,过程中看能不能整理出一些东西。

RN 这个项目已经是庞然大物,打开 github 项目主页,根目录下文件和文件夹就多达五六十个,看起来一脸懵逼,不知道哪些是源码,在看源码之前先理理 RN 最终用到哪些代码,项目是怎样创建,怎样跑起来的。以下皆以 iOS 端为例。

流程

先看看标准 RN 项目创建和运行过程:

  1. RN 根据教程装完环境后,会有一个全局命令 react-native,执行 react-native init AwesomeProject 可以创建一个新 RN 项目。
  2. XCode 打开自动生成的项目,编译到模拟器或真机,一个 RN hello world 程序成功运行了。
  3. 在模拟器运行同时会在 chrome 打开一个页面,在页面里使用 developer tools 可以直接断点调试 RN 页面上的 JS 源码。

疑问

上述流程跑下来整个过程是个黑盒,对黑盒里的处理有一些疑问点:

  1. react-native init AwesomeProject 这个命令做了什么,是怎样创建 RN 模板项目的?
  2. 项目 JS 源码在哪里,如何跑起来的?
  3. 怎样做到可以在 chrome 调试 JS 源码?

接下来一条条看。
(更多…)

晋升评审的套路

2017-6-26 评论(5) 分类:技术文章

很多中大型互联网公司都会有晋升评审,也就是对技术/产品等职位划分成若干个等级,每个员工都有一个等级,若要晋升到下一级,需要由几个评委面试决定是否合格。这跟传统公司的考职称差不多,只不过传统公司是通过考试,互联网公司是通过面试。

为什么会有这种晋级评审?等级是公司内部对员工的一种评价和定位,等级的参照物是公司内的所有员工,假如一个公司比较小,老板每天跟所有员工一起工作,在老板识人能力又没有问题的前提下,老板就很清楚每个人的能力,直接对他们排等级,不需要什么评审,得出来的结果其实是更公正准确的,因为这是根据平时工作过程中获取的大量信息综合考虑得出的结果。但在中大型公司做不到,老板认识不了那么多人,没在一起工作,没法对每个人给出公正的评价。若把评判权都交给一起工作的组长总监又不妥,因为职级的参照系是全公司,而不是组内或部门内,很容易出现偏颇/标准不一的情况。

于是出现一个评审系统,由公司里一些有经验的人士去判断某个人能不能晋升到下一个等级,而这些人平时很可能没有跟他们一起工作,仅仅是通过大概一个小时的陈述和沟通去评判,这导致了这一个小时里陈述的方式和沟通的技巧变得很重要,同样一个人同样的工作,不同的 PPT 不同的陈述方式,结果会完全不一样。这里大致说下我所了解到的套路,套路并不是贬义词,只是能帮助更好地表现自己的能力,让评委得出更公正的评价。

要点

先列一下在准备晋级评审 PPT 时我认为重要的几个要点:目标,重点,思路,数据。

目标

在准备晋级 PPT 时,得先搞清楚目标,这种 PPT 目标很简单只有一个,就是告诉评委我很NB我完全可以晋升到下个等级。时刻问自己 PPT 表现出这个目标了没有。

重点

只有一个小时时间,不可能面面俱到表现出所有,讲的内容多了评委也不会记得,必须突出一两个重点和亮点,用2/3以上篇幅去深入讲,并且要让人听得懂。有人误解了以为晋升评审是述职,罗列过去一年做的工作,这个其实很为难评委,评委需要帮你在你罗列的众多工作中寻找能体现你技术水平的点,整体印象也大打折扣。

另外需要有一些亮点,如果你陈述的都是业界常规做法,其他人也是这样做的,评委会觉得没什么特别,是个人都会这么做,若有自己独特的创新点和亮点,就算是小的点,让评委眼前一亮也是很好的加分项。其实这是这个评审制度本身的缺陷和局限,因为评委每次评审的人数太多,如果大家能力都没有太突出,那决定谁更好的方式就是谁更特别留下更多的印象,这也就是亮点的意义。

思路

讲思路不要讲细节,特别是代码细节,除非是非常有技术含量的,作为亮点的细节。着重表现自己在解决问题过程中的思路,表达出自己在项目/问题涉及到的方方面面都有考虑到(全局观),有深入思考的能力,面对一个问题有能力抽象出关键点,有能力分解问题,若最终能总结出类似问题的统一解决思路(方法论)更好。

数据

要有数据证明做出的成绩,经过你NB的工作后,是性能提升百分之多少,还是工作效率提高多少,还是投诉率降低多少,还是有多少个产品都在用你的东西,业务的核心数据是怎样,都要有证据证明自己不是在吹牛,尽量使用量化的指标。

结构

这里列个常用的结构供参考:

我是谁:工作经历
我做出了什么成绩:在本公司做的事情,负责的业务,做出的成绩。
1-3个重点:

  • 碰到什么问题,业界是怎么解决的,我在这基础上做了些什么,相对业界的做法有什么优点,在这过程中碰到什么困难,怎么解决,最终达到什么效果(数据)。
  • 碰到什么需求,业务特点是什么,有哪些技术挑战(安全/架构/协作/性能/稳定性/历史包袱/响应能力/兼容性/开发效率/自动化等等),我是怎样设计的(方案完整性),有什么优点和创新点,最终达到什么效果(数据)。
  • 碰到什么问题,我按什么样的思路尝试过哪些方法,深入钻研到什么程度,虽然最终做法跟业界一样,但经过我深入研究证明了这已经是最佳做法。
  • 碰到什么问题,有哪些开源项目解决了这些问题,它们有什么缺陷,我重新造的轮子比他们NB在哪里,做到这么NB的难点是什么,我怎么做到的,怎么证明真的NB不是我在吹。

未来计划
谢谢

当然并不是说都要按这个结构写,若个人能有创新发挥用更适合自己的方式陈述自然更好。

交流

交流环节里,一般评委都是会根据 PPT 内容问问题。

最容易被挑战的就是数据,若 PPT 上列的数据不是很常规就会被问为什么,对所有数据都必须准备好被质疑。

评委对某个点感兴趣会追问细节,一些重要的技术细节可以以附录的形式附在PPT后面,问到时方便讲解。

PPT 上提到的点最好对相关技术都了解清楚,例如提到客户端网络层优化,最好把网络层底层相关知识都准备好,评委可能会追问下去以考察技术深度。

有些评委喜欢问一些固定问题,例如你觉得为什么你应该晋级,你觉得有哪些不足,你后续的技术规划是什么等等。

公司一般会有每个职级对应的能力表,有些评委喜欢对着能力表问相关问题。

评审也是个双向学习的过程,如果你能让评委觉得学到东西了效果会很好。

很多评委喜欢问他擅长的专业领域内的问题。显然这个环节有一定运气成分存在,遇到匹配度高的评委通过几率直线上升。

最后

这种一小时判断一个人的晋级评审肯定做不到非常公正,有一些运气成分,甚至有一些关系成分,但已经是相对较好的一种形式,而且评审的准备过程中还能让自己梳理总结一下过去做的事情,虽然准备过程会很痛苦,但也会很有收获。晋升的前提当然是要有足够的技术能力/影响力和视野,这里一些套路只供参考,希望能帮助有需要的人更好地表现自己的实力。

信息和学习

2017-5-30 评论(9) 分类:随记

最近上下班路上还在听罗辑思维,虽然我本人很不喜欢罗胖,但他的节目还是会听听。每次听都会听到一些逻辑错误想吐槽,缺啥喊啥,罗辑思维很缺逻辑,不过仔细想想,每天都要出节目并且拼上一些观点和结论,如果每个观点结论都要求逻辑严谨是比较难,可以理解。

一时举不出逻辑错误的具体例子,因为每天听过后基本上都忘了,罗辑思维从以前的一周四十多分钟变成现在的每天八分钟,其中一个原因是说四十多分钟的节目很长很重很多人听了记不住,所以改成八分钟以内,这个逻辑也是挺搞的,四十分钟讲一个话题记不住,八分钟反而能记得住?实际上都记不住,可能跟各人记性好坏有差异,但更多的是大脑机制就不允许你听一遍就记住,如果大脑把每天所见所闻都记住,那就太多了,信息爆炸。只有那些经过脑子不断思考,重复输入输出的信息才会被记住,才能转化成自己的知识。

轻轻松松听人讲讲故事和观点,只是当下接收一下信息,如果没有后续自行琢磨重复思考,实际上留不下什么东西。罗辑思维这种通过加工后的信息输入会让人感觉很有营养很有效率,实际上信息输入是学习中最简单也是作用最小的部分,真正起作用的是自己大脑对信息的加工思考和输出的过程。回想读书时期,知道一条原理公式是不是很容易?大概几分钟就觉得已经理解了,实际做题要用到这条原理公式时,才发现并不容易,需要反复练习不断通过自己大脑的再加工才能掌握和理解。这跟成功学也挺像的,其他人总结的观点技巧只是信息,输入这些信息是最简单也是最无用的,最困难和最有用的是实践。听节目看文章输入信息只是让你知道有这么个事,完成了学习的一小步,后续一大步还得靠自己。

罗辑思维和得到 APP 标榜终身学习,但产品上并没有让用户学习,并没有任何让需要用户动脑思考的产品特性,只是在单方面提供一些信息,你要是觉得每天轻轻松松不怎么动脑听听电台就是学习,就能获得知识上一个档次,就跟看成功学觉得自己能成功,已经跟成功人事思维在一个档次一样。

得到的产品经理们当然明白这些,只是用户都是懒的,如果真要做到像标榜那样的帮助人终身学习,做一些产品特性帮助用户在思考,对输入的信息再加工再输出,这样产品的受众就很小了,永远只有少部分人愿意去思考和真正学习,大部分人不想动脑,而且是不想动脑不想花时间还想学到知识,得到迎合了这个需求,提供了省时间获取信息的方式,让人轻松获得信息并自以为在学习。实际上得到是提供了挺多高质量信息,是个不错的信息源,但他不告诉你我只是提供跟以前商业杂志一样的信息,而是吹嘘能帮助你终身学习,混淆概念,迎合现代人的焦虑和懒惰,挺鸡贼的。

四月

2017-4-30 评论(11) 分类:生活

这个月比较忙,博客拖到最后一天,不知道写啥,写写近况和感受吧。

这个月换工作换城市,从腾讯到蚂蚁金服,从广州到杭州,距我上次回腾讯已经三年,回想起来还是要特别感谢当时给我机会回去的老大们,三年里有很多成长,有很多 nice 靠谱的同事们,也很幸运有微信读书这样的项目,小而美的团队,做自己喜欢的产品,离开时还真是挺舍不得,希望微信读书越来越好。

为什么要离开呢,原因很多,还是想多尝试些不同的东西,在腾讯顺顺利利,舒舒服服,轻车熟路,有点遇到了成长瓶颈,想换个环境见识一下,趁现在还能经得起折腾,另外一辈子住一个城市好像也比较闷,从大学开始来广州接近10年了,换个城市试试也不差,虽然搬迁代价很大。

为什么从一个大公司到另一个大公司,其实大公司之间的差别很大,至少腾讯跟阿里的差别是巨大的,做事的方式不一样,公司大了公司文化这种东西就不是虚的了,是时刻存在并影响着日常的做事方式的,体验学习适应中。

来杭州三个星期,说说三个印象。

1.旅游生活气息浓

这边可以游玩的地方太多了,在老同学的带领下夜游灵隐寺和大运河,大运河旁都开发得跟乌镇那样,团建去了西溪湿地,还有大量旅游景点没去,不止是杭州,听同事说周边还有各种景点,会经常发现小时候读的古诗里的地点,像苏州的“姑苏城外寒山寺”,要是在杭州工作不忙的话,每个周末都像在旅游,幸福感还挺高的,希望后面有周末时间。

2.交通差

在这边开车我都震惊了,红绿灯之多令人发指,在广州我比较讨厌新港西路,10公里就有十几个红绿灯,觉得没天理,但在杭州5公里就能有十几个红绿灯,可怕。另外道路规则还挺复杂,有的左转道在左边有的在右边,有的红灯可以右转有的不行,路也很窄,单行道挺多,战战兢兢,还试过在西湖广场调个头调了半个钟,醉了。不过杭州道路对单车电动车倒挺友好,于是我现在是开电动车上下班。

3.前途光明

看到各种新大楼,科技新区,感觉互联网行业繁荣度比广州好太多,办G20城市面貌有很多改进,城市规划好,多中心,不像广州一样集中在单个中心,据说后续六七条地铁会同时开通,后面还要办亚运会,生机勃勃,人才净流入,城市前景一片光明,杭州去年房价涨得不像样,感觉要不是限购,今年还会继续大涨。

另外杭州似乎雾霾是比广州严重的,不过来的这三周里除了第一天雾和霾比较重,其他时候空气倒还不错。现在应该是气温最好的时候,据说杭州冬天湿冷,夏天又热到40度,比广州还可怕,到时体验一下。

iOS App 签名的原理

2017-3-13 评论(48) 分类:技术文章

iOS 签名机制挺复杂,各种证书,Provisioning Profile,entitlements,CertificateSigningRequest,p12,AppID,概念一堆,也很容易出错,本文尝试从原理出发,一步步推出为什么会有这么多概念,希望能有助于理解 iOS App 签名的原理和流程。

目的

先来看看苹果的签名机制是为了做什么。在 iOS 出来之前,在主流操作系统(Mac/Windows/Linux)上开发和运行软件是不需要签名的,软件随便从哪里下载都能运行,导致平台对第三方软件难以控制,盗版流行。苹果希望解决这样的问题,在 iOS 平台对第三方 APP 有绝对的控制权,一定要保证每一个安装到 iOS 上的 APP 都是经过苹果官方允许的,怎样保证呢?就是通过签名机制。

非对称加密

通常我们说的签名就是数字签名,它是基于非对称加密算法实现的。对称加密是通过同一份密钥加密和解密数据,而非对称加密则有两份密钥,分别是公钥和私钥,用公钥加密的数据,要用私钥才能解密,用私钥加密的数据,要用公钥才能解密。

简单说一下常用的非对称加密算法 RSA 的数学原理,理解简单的数学原理,就可以理解非对称加密是怎么做到的,为什么会是安全的:

  1. 选两个质数 p 和 q,相乘得出一个大整数n,例如 p = 61,q = 53,n = pq = 3233
  2. 选 1-n 间的随便一个质数e,例如 e = 17
  3. 经过一系列数学公式,算出一个数字 d,满足:
    a.通过 n 和 e 这两个数据一组数据进行数学运算后,可以通过 n 和 d 去反解运算,反过来也可以。
    b.如果只知道 n 和 e,要推导出 d,需要知道 p 和 q,也就是要需要把 n 因数分解。

上述的 (n,e) 这两个数据在一起就是公钥,(n,d) 这两个数据就是私钥,满足用私钥加密,公钥解密,或反过来公钥加密,私钥解密,也满足在只暴露公钥 (只知道 n 和 e)的情况下,要推导出私钥 (n,d),需要把大整数 n 因数分解。目前因数分解只能靠暴力穷举,而 n 数字越大,越难以用穷举计算出因数 p 和 q,也就越安全,当 n 大到二进制 1024 位或 2048 位时,以目前技术要破解几乎不可能,所以非常安全。

若对数字 d 是怎样计算出来的感兴趣,可以详读这两篇文章:RSA 算法原理(一)(二)

数字签名

现在知道了有非对称加密这东西,那数字签名是怎么回事呢?

数字签名的作用是我对某一份数据打个标记,表示我认可了这份数据(签了个名),然后我发送给其他人,其他人可以知道这份数据是经过我认证的,数据没有被篡改过。

有了上述非对称加密算法,就可以实现这个需求:

(更多…)

关于苹果警告

2017-3-9 评论(37) 分类:互联网

昨天早上 iOS 开发者们陆续收到苹果邮件,警告去掉动态下发功能,覆盖面很广,内容没有明确指示是什么库,导致大家各种猜测。

其实上周已经有少量用户收到苹果这份警告邮件,当时还以为是特例,现在看来是在灰度测试扫描代码,可见这事苹果应该讨论已久,并专门排期开发测试了扫描程序,直到昨天才正式上线。

从各方信息看起来,很不幸主要禁的还是 JSPatch / wax/ rollout 这样的热修复框架,特点是可以通过 JS 脚本调用和替换任意 OC 方法,而像 React Native/ 小程序这样用 JS 做功能的暂时不受影响,Weex 不确定,至于其他库像 AFNetworking / SDWebimage 用到那几个接口的,应该只是误伤。

根据苹果要求,收到警告的同学只需要在下次提交版本时去掉相关框架就可以,没有时间期限,目前也不会强制下架。

为什么

苹果为什么这么做呢?苹果对热修复一直以来的态度都是不赞同也不拒绝,JSPatch 本身也并没有违反开发者条例,而且 JSPatch 大多数都用于修复 bug,提升 iOS 平台 App 的质量,对苹果也是件好事,为什么要禁?猜测原因有两点:可控和安全。

可控

苹果一贯作风是让所有事情可控,开发者能用什么不能用什么都尽量在自己的控制范围内。大多数人使用 JSPatch 修复 bug,或者弄一些临时运营的小功能配置,这些没有问题,但总会有少数用户使用 JSPatch 去调用私有API做些事,这是苹果不可控的,也无法知道有多少人这样做了。

不过其实在代码这块苹果其实一直可控程度有限,他会在提交时扫描你有没有用某些私有方法,但只要你对这些私有方法调用做一些变化,加解密字符串拼接什么的,就能绕过扫描,再通过后台配置调用,是一样的。JSPatch 只是让调用私有 API 变得成本更低更方便点而已,可控这里只是个小理由。

安全

去年 FireEye 分析了使用 JSPatch 的安全问题,当时我也写文章回应了,再复述一下,主要安全风险有三点:

  1. 开发者自己本身对 APP 下发恶意代码。
  2. 开发者没有做好加密传输和校验。
  3. 开发者接入的SDK里接入了JSPatch,SDK 作者可以对这些 APP 下发恶意脚本。

第一点其实不算安全风险,因为开发者自己有恶意的话完全不需要借助 JSPatch。

第二点大多数用户使用 JSPatch 时都做好了非对称加密,保证不会在传输过程被第三方篡改。但这里技术上没法保证用户一定使用正确的加密方式,苹果无法知道有多少接入 JSPatch 的用户没有正确加密和校验,这是未知的安全隐患。

第三点在当时并没有什么第三方 SDK 接入 JSPatch,但现在像高德地图/个推等都接入了,如果他们要作恶,或者他们本身服务端被入侵,确实是个安全隐患。

iOS 平台是最安全的,也是最注重安全的,即使热修复带来了 App 质量更高的好处,也无法无视这里的安全隐患,现在 JSPatch 国内覆盖面很大,若出一个安全问题,会影响 iPhone 的声誉,因为这个风险,所以考虑禁掉。

反应

这个警告出来后,国内开发者有各种反应,各种表情贴图还挺搞笑的,不过大家放心,JS没事,iOS 开发该失业的还是失业:)

看到有一些人拍手称赞,赞的理由不是说苹果维护了平台安全,而是:1.国内开发方式low,2.产品经理滥用。这里我有一些想法说一下。

开发方式

他们说国外开发不理解国内为什么要用热修复,国外很少使用,国外开发流程很好很规范,会做好充分的 codereview 和测试,上线后没什么 bug,不需要热修复,也不会有产品经理乱提需求,迭代没像国内这么快,使用热修复是本末倒置,不去考虑提高 APP 质量,国内开发方式太 low,国外的才是正道。

这里有个问题,就是什么是好的开发方式?以什么标准界定?上面的说法可以看出他们是把工程的严谨性,流程的规范性作为好坏的依据。虽然我是个程序员,觉得工程严谨和流程规范确实是好东西,但我比较实用主义,更倾向于以结果作为标准,也就是能不能更低成本更高效地开发出质量更好的产品作为标准。

如果我使用热修复能以更低的人力成本(工程师能力和薪水不如国外,人数少),更高效(测试时间缩短,不需要覆盖到0.01%几率出现的 bug / crash ),做出质量更高的产品( bug / 特殊情况和需求反应速度快),为什么不是一个更好的开发方式呢?

另外客户端的开发方式本身就是落后的,不利于快速迭代,无法对线上产品有控制权,参考另一篇文章。这也就是为什么 Facebook 一开始要用 web hybird 的方式开发,现在又要做 React Native。热修复是这种落后开发方式的弥补。另外我没在国外公司工作过,但感觉他们对bug的容忍程度还是比国内高的,对比一下 IAP 和微信支付的失败率,做过的人都知道。

还有一个声音说国内的人喜欢违反规则,钻空子太不老实。首先前面也说了热修复的方式并没有违反规则,完全符合开发者条例,其次国外也有热修复 rollout,最后如果从开发者条例来说,React Native 反而是违反规则的,因为主要用途动态添加和修改 APP 的功能。

滥用

另一个说法是上了热修复后产品经理来劲了,产品时不时想到一个功能配置说上就上,开发者弱势只能跟着上。

这种情况在我这边团队还没遇到过,我的想法是:如果要上的功能配置对产品是有好处有必要的,开发维护成本又低,为什么不上?如果要上的功能配置是无关紧要的,或者开发维护成本太高,为什么不能讲理拒绝?

开发者把原因定位为自己“弱势”,就把自己从团队剥离开了,变成对人不对事,这种团队氛围是挺糟糕的,而这个锅也不是产品经理的。大家做的事都是为了产品更好,应该不会有那么多故意刁难不讲理的产品经理和老板。至于怎样界定对产品有没有好处和有没有必要,以及开发成本高低,这得自己协商了,以我们团队的做法是以做这个事的性价比计算。

怎么办

接下来如果还想用 JSPatch 怎么办?我没有跟苹果审核团队交流过,不知道他们的想法,短时间内是先不要用,后续再看情况。

热修复的需求很大,很希望苹果可以推出自己的方案,由系统做这个事是可以保证安全的,但现在看起来可能性较低,国外需求量不大,苹果也就不会重视这个需求,何况目前在大力推 Swift。

对于 JSPatch,苹果应该是扫描可执行文件里的关键字,从技术上说是很难禁掉的,可以做各种混淆去绕过检查,但若下发时被查到,会有政策风险,政策有待观察。

实际上动态化还是处于灰色地带,严格来说 RN 是不符合规则的,但还是被允许,只要不给苹果添麻烦,苹果就不会管,JSPatch 因为上面提到的两点风险被管了,怎样做到使用并不给苹果添麻烦呢?

  1. 减少自行接入的使用人数。
  2. 禁止 SDK 接入。
  3. 接入保证传输安全和只用于修复 bug。

第一点警告邮件和代码检查使得自行接入 JSPatch 门槛变高了,显然会减少使用人数。第二点第三点只要有一个平台来管控,由平台保证安全性以及扫描下发的脚本,禁止私有API调用,禁止大量脚本下发,是可以做到的,可能的话希望能跟苹果审核团队协商。

附上 JSPatch 平台初定的解决方案

iOS 开发技术栈与进阶

2017-2-28 评论(20) 分类:技术文章

最近有一些开发朋友问我应该怎样提升自己的能力,回想起来做了这么久 iOS 开发,我也有过那种“让我做一个功能实现个需求我会做,但接下来怎样提高我不知道。”的时期,这里尝试列一下 iOS 开发的相关技术,再说说在学习进阶上我的一些想法。

iOS 技术栈

这里按我的理解给 iOS 相关技术分个类,以工程实现的角度,分成了基础、需求、效率、质量四个类别。基础指程序开发和 iOS 开发的基础知识和技能,需求就是产品的需求,有了基础技能,实现了产品需求后,剩下的事情就都是为了提高项目质量和提升开发效率。

大致的思维导图

iOS技术栈 (更多…)

如何动态创建 block – JPBlock 扩展原理详解

2017-1-23 评论(14) 分类:技术文章

简介

JSPatch 最近新增了扩展 JPBlock,解决之前 block 使用上的一些限制:

  1. block 参数个数最多支持6个。
  2. block 参数类型不能是 double / struct / union 类型。
  3. 不支持 JS 封装的 block 传到 OC 再传回 JS 去调用。

接入 JPBlock 后,就可以:

  1. block 参数支持任意多个。
  2. block 参数类型可以是除 struct / union 以外的任意类型,包括 double。
  3. 支持 JS 封装的 block 传到 OC 再传回 JS 去调用。

这篇文章说说这里的实现原理。

(更多…)

2016

2016-12-31 评论(12) 分类:生活

,照例回顾一下这一年。

工作

微信读书

今年在公司一整年都在做微信读书,用户量一直在增长,UGC方面每天都在产生很多不错的书籍想法和书评,整个产品度过了生死期,进入发展期。产品上有不少地方做得不错,一是保持了简洁的调调,这也是微信相关产品应有的模样,不会有什么乱七八糟的东西,也是很多人喜欢这个APP的原因。二是开放了陌生人想法,一开始微信读书只能看到好友写的想法和书评,跟朋友圈一样保持私密,事实证明在读书这个产品上,开放所有内容才是正道。三是做的阅读时长换书币和赠一得一都取得不错的效果,时长换书币让读书形成正循环。四是做了一些不错的小功能,获得了一些好的口碑,像划线想法制作图片分享,购买/赠送书籍的扉页等。

产品上一直在做一些尝试,但都比较谨慎,很多新需求功能都会经过不断讨论去决定要不要做,也有不少本来已经讨论完觉得可以做,但做到一半或做完时觉得还是不行直接砍掉的需求,谨慎导致不够快速,也做了不少无用功,这里也是我们缺乏经验导致,接下来一年会在这方面寻找解决方法,希望能做到快速迭代,减少无用功。

技术上回顾起来还是做了不少事情的,团队开了个技术博客,今年写了15篇技术文章,几乎每个成员都有贡献,开源了5个库(MLeaksFinder/GYHttpMock/GYBootingProtection/GYDataCenter/GYMonitor),在 APP 质量保证和监控方面做了一些事情,在团队博客上都分享了,另外实施了 code review,团队偶尔也会在项目里做一些新尝试,像尝试使用 RAC,尝试用数据不可变的方式开发,尝试用推荐算法去优化书籍的添加率等等,总的来说还算不错吧。接下来在技术上除了继续保证 APP 质量和开发效率,还应该尝试寻找能帮助产品前进的点。

JSPatch

JSPatch 这一年继续在完善,致力于让 JSPatch 变得更好用,优化了性能,做了一些扩展,填了一些坑,支持了动态调用C函数,做了代码自动补全工具 JSPatchX 等,改进最多的是 JSPatch 平台,从内测到开放注册,添加了灰度下发、条件下发、自定义密钥、在线参数、实时监控、历史补丁、在线编辑、转换器等等功能,已经是一个完善可靠的补丁分发系统,这个以前没有人做过,可以说开拓了在线补丁分发平台这个领域,算是今年主要的作品了,接下来也会继续探索提供更多的服务。

JSPatch 发展到现在已经被很广泛地使用,没有具体统计过接入的 APP 数,仅接入 JSPatch 平台每天有补丁请求的 APP 就有近3000个,在 iOS hotfix 市场占有率应该在 95% 以上,github star 也达到了 8300+,还算不错。

对于 JSPatch 的发展一直想扩展到覆盖 iOS 动态化的全部需求,包括开发功能,上半年也针对这个目标做了些事情,做了性能上的改进,优化开发体验的 JSPatchX 和 playground 等,有一些效果,但开发体验上还是不够好,下半年考虑过做一个100%准确的转换器,实现直接用原生OC开发,动态下发,进一步提升开发体验,但下半年杂事缠身,没能实施,最近看到滴滴和手Q分别实现了这样的方案,也就没打算再做了,后续再看情况。
(更多…)

iOS 动态化的故事

2016-12-21 评论(15) 分类:技术文章

今天聊聊 iOS 动态化的故事。

问题

在开发模式上,web 的方式是比较先进的,有各种优点,包括跨平台/UI开发效率高,最重要的是可以时刻保证用户看到的程序是最新的,没有版本概念,整个系统时刻保持在掌握之中,而客户端开发模式相对 web 开发是一种倒退,客户端做不到这样的动态化,无法随时更新,目前一个客户端程序要更新成本是很高的,需要发布版本,也无法保证所有人都能更新到这个版本,这是最大的弱点,也是非常大的一块需求。

原因

为什么会有这种倒退,最主要原因是:苹果引领的体验优先规则。

在 iPhone 出现之前大家并不太在意一个软件的动画体验,一个 web 应用是很少有动画的,点一个按钮,一整块内容直接刷新,再点个链接整个页面变白刷新,PC上网页滚动都是一格格滚动的,而不是现在手机上那种顺滑流畅的滚动,PC客户端软件也一样,大家都觉得没什么问题,用得挺好,但苹果改变了这种情况,iPhone 刚推出时页面间切换的动画,60fps 的丝滑滚动,点击的即时响应,微软的人都惊呼是黑魔法,让人用了就上瘾,再也回不去,而 web 的方式还不足以像原生客户端那样支持这样的流畅性,做不到好的体验,无法被人接受,开发上优势再多也无法干过客户端,参考 facebook 初期用 web 技术构建 app 的惨状,没办法,服了苹果,大家只能按照苹果的方式干,做原生客户端。

当然这里还有手机环境网络不稳定,流量费贵的原因,但这些都可以在技术上通过缓存解决,最主要还是体验问题。

那发展到今天,这个体验问题解决了没有呢?没有,即使发展到今天手机性能已上天,但 web 做出来的东西体验仍然跟客户端有差别,大家也已经习惯了 APP 的方式,也被流畅的 APP 惯坏。现在 APP 里也有不少功能是 web实现,但大家都知道这是牺牲了一些性能体验去换取开发和发布效率,只是一种权衡。

解决方案

那这个问题怎么解决呢,现在业界有两种方案。

1.优化 web 性能

既然用 web 方式开发的劣势只是性能体验跟不上,那就优化性能吧。web 性能瓶颈在哪里?在那个有悠久历史的 webkit 引擎,它有各种历史问题,要改进它并不容易。我们要的是 web 的开发和发布方式,不需要 web 的全部,那能不能重新实现一个渲染引擎呢,这个引擎可以针对原生客户端优化,不需要兼容繁杂的 web 标准,不跟 web 那些历史问题扯上关系,于是就有了 React NativeWeex 这种方案,web 的方式开发,原生的方式渲染,拥有 web 优秀的开发和发布方式,又有不错的性能体验,看起来很完美,很有前途的方案。

一个方案能不能推广开让大家都使用,主要看成本和收益。目前 React Native 和 Weex 等这些方案的接入成本是很高的,一是它们本身就是大型框架,学习成本高,后期维护成本以及团队学习成本同样高。二是它们还不够成熟,还在继续填坑中,使用的过程可能要一起去填坑。收益上也不够理想,就目前状况它们能代替的是那些本来用 H5 实现的模块,换成这种方式实现后性能体验会更好,但也不能保证像原生那样好,很多场景需要深入框架进行优化。整个 APP 都使用这种方案构建还不靠谱,部分使用又无法使整个 APP 保持动态化,总体上来说收益也没有达到有绝对优势的程度,成本高收益低,推广起来会比较困难,还需期待其继续发展。

2.原生动态化

另一种是方案是,我可以放弃用 web 的开发方式,放弃 web 跨平台/UI开发简单的优越性,我想继续用原生的方式开发这个APP,但又希望这个 APP 随时可以更新,让程序时刻在自己掌握中,出了问题可以快速修复,还想要可以随时更新版本快速迭代,可以不?完全可以,用动态库就行了。

动态库

技术上要在 iOS 上做到原生动态化比 Android 更容易,iOS 开发语言 Objective-C 天生动态,运行时都能随意替换方法,运行时加载动态库又是项很老的技术,只要我把增量的代码和资源打包到一个 framework 里,动态下发运行时加载,修 bug,加功能都不在话下,性能完全无损,这件事就结束了。

但是呢。苹果把加载动态库的功能给封了,动态库必须跟随安装包一起签名才能被加载,无法通过别的途径签名后再下发。

为什么这么做呢,这又涉及到苹果另一个创举:审核模式(苹果的创举之多令人发指)。一个软件,要在一个平台上发布,需要先通过这个平台的人工审核,这个好像在苹果之前没见过有别人这样做过,windows 不用,mac 不用,各种 unix 不用,web 也不用,苹果为了对自己的平台有绝对控制权,搞了这样一个东西,审核模式就跟动态化冲突了,如果我一个 APP 可以不经过审核不断下发 framework 添加修改功能, 还需要苹果审核做什么?

因为这种限制,没法用最方便的方式进行动态更新了,整个 APP 发出去后就不受控制,有什么严重 bug,需要添加什么功能,都乖乖打个包提交给苹果审核,再等用户慢慢更新,对于急性子的中国人来说,这种事难以容忍。

绕道

苹果把动态库这扇门关了,我们可以绕个道从另一个门进,动态加功能可以缓缓,大家需求还不那么迫切,但修 bug 的需求就很急,很多公司 APP 的 crash 率是 KPI 来着,看着线上 crash 不断增多又毫无办法是很不爽的事,于是有了 waxPatchJSPatch 这种方案,曲线救国。

JSPatch 把 OC 手动翻译成 JS,在运行时通过 OC 的动态特性去调用和替换 OC 方法,实时修复 bug。修 bug 这个需求基本是满足了,虽然小绕了下道,但成本还是很低的,引擎本身也很小很轻量,接入对 APP 不会有任何负面影响,在关键时刻又可以帮大忙,成本低收益高,于是很容易推广开。

人欲望是无穷的,技术宅的折腾是无止境的,JSPatch 满足了修 bug 的需求,但还是无法满足动态化的全部需求,最大的缺点在于需要手写 JS,虽然已经有转换器辅助,但还没做到100%准确,用来修 bug 还好,用来添加功能的话学习成本和开发效率还不够。

于是有了滴滴的 DynamicCocoa 这种方案,绕了一个更大的道,从编译阶段入手,通过 clang 把 OC 代码编译成自己定制的 JS 格式,再动态下发去执行,做到原生开发,动态运行,主打动态添加功能,当然顺便把修 bug 也给支持了。手机 QQ 内部也有一个类似的方案,不过更进一步,他们通过 clang 把 OC 代码编译成自己定制的字节码动态下发,然后开发一个虚拟机去执行(惊呆了),同样实现了原生开发,动态运行,都是 NB 得很的方案。只要底层处理做得足够好,也是个成本低收益高的方案,不过目前都还没开源,还没能看到实际效果和 NB 的源码,挺期待。

审核

这种方案有没有什么问题呢,问题在对于苹果审核比较尴尬。这种方案做到极致后(所有OC/C语法都支持),实际上是绕道实现了动态加载 framework 的全部功能,开发体验还是一致的,如果苹果同意这种方案,那相当于允许加载动态库,那还不如直接把门开了,让大家直接用动态库去做这个事情,用动态库还能在签名时禁止使用私有 API,用这种编译成脚本/字节码下发的方案可就禁止不了了。

这跟 JSPatch 还不太一样,JSPatch 虽然我也想推广动态添加功能的用法,但因为开发体验问题大部分还是用于修 bug,苹果审核对 JSPatch 开始也是有一些拒绝案例,后来估计看到大家只是用它来修 bug 和 crash,提升 APP 的质量,就默许了。但 DynamicCocoa 和手Q的方案一开始目标和效果就是跟加载动态库对齐,大规模推广后苹果会怎么看就不知道了。

我觉得苹果现在的审核方式挺有问题的,有多少APP是审核时用一套,审核通过后又通过后台一些开关把不符合规则的一些功能开放出来?只要能连上网,就有N种方式修改 APP 里的功能,苹果完全拦不住。个人认为审核方式应该改为只在发布新 APP 时审核,发布后允许动态下发代码更新,版本更新也不需要重新审核,而是通过举报和抽查的方式去审核已上线的 APP,这样既能顾及开发效率,方便开发者快速迭代做出更好的 APP,也更能确保审核效果,只是实施起来没有现在简单粗暴。

最后

故事讲到这里已经差不多了,再多说一点,有个让我觉得很奇怪的问题,就是国外开发者只热衷于使用第一种方案解决问题,也就是使用web技术,用 React Native / NativeScript 的方式去做这个事情,对第二种方案很冷淡,包括 iOS Android 都是,原生热更新只在国内火,国外根本不感冒,国外有个 rollout 热更新平台也不温不火,为什么呢?是国外用户更守规则,或是用户对线上 bug 容忍度高,开发者对线上 bug 并不那么着急?还是 Android 被 Google Play 卡死断了这念想,iOS JSPatch 之类的方案推广不利?缺少国外一线开发者的支持,让系统原生支持动态化就比较困难了。

个人认为由系统支持动态化(允许加载动态库)在当前环境下是最好的,兼顾开发效率和 APP 体验,虽然不能跨平台,但也还能接受,可惜这个主动权掌握在苹果手上,开发者无能为力,才会出现这么多强行绕道突破的方案。web 的方式可能是未来,但目前适用范围有限,接下来怎么发展,拭目以待吧。