写点什么

花瓣网李忠:ReactiveCocoa 是 Cocoa 的未来

  • 2014-07-02
  • 本文字数:3912 字

    阅读完需:约 13 分钟

ReactiveCocoa(其简称为 RAC)是由 Github 工程师们开发的一个应用于 iOS 和 OS X 开发的函数响应式编程新框架。ReactiveCocoa 为开发者带来了函数式编程和响应式编程的思想,被 Mattt Thompson 称为开启一个新 Objective-C 纪元。InfoQ 此次专访了花瓣网移动开发主管李忠,另外作为 ArchSummit 深圳 2014 大会《移动互联网,一浪高过一浪》专题的讲师,李忠将会分享 ReactiveCocoa 在花瓣客户端的实践。

InfoQ:使用 ReactiveCocoa 与直接使用 Cocoa 框架相比,性能上(事件的响应速度、回调速度)是否会有影响?

李忠:ReactiveCocoa 底层的实现是比较复杂的,在性能上确实会有一定的影响。一个简单的 [signal subscribeNext: ^(id x){}] 就会有造成很深的 callback stack(近 40 次的调用),相比纯 KVO 不到 10 次的调用,速度上慢了至少 1 个数量级。不过尽管如此,只要 subscribe 的次数不要过多,性能上还是可以接受的。

在事件响应上,RAC 比 KVO 慢了大概 5 倍,不过问题不大,在 iPhone5 上测了下,也就 1ms 多一点,绝大多数的使用场景都不会有问题。

在开发 Mac App 时,可以使用 Cocoa Bindings,但 iOS 却不支持,可能也是出于性能上的考虑。既然 RAC 的性能不如直接使用原生的高,还有必要用它么?我觉得还是有的,性能是我们选择框架的一个参考因素,但不是决定性的因素。开发者在足够了解 RAC 的情况下,RAC 可以提高开发效率并帮助开发者编写更易维护的代码,这两点就值得我们去研究、使用它。

InfoQ:使用 ReactiveCocoa 等于是放弃了 xib 或 StoryBoard,这样的话在开发界面的时候就需要通过代码去控制,这是否会降低开发效率?

李忠:iOS 开发 UI 界面主要有 3 种方式,手写 UI 代码、使用 xibs 来组织 UI、使用 StoryBoard 来组织 xibs,3 种方式各有优缺点。

  • 手写 UI 代码 (也是我目前采用的方式) 既然 xib 可以做的事情,代码都可以做到,而且 xib 做不了的事情,代码也可以做到,那为什么不直接用代码来写呢。很多人担心开发效率上会是一个很大的问题,我觉得或许会慢一点,但问题不大,尤其是结合了这样的 UIView Helper 之后。还有就是涉及到多人开发时,可以减少冲突,尤其是每个人负责各自的模块,基本不会出现这个情况。
  • 使用 xibs 来组织 UI 这也是不少开发者采用的模式,跟手写 UI 相比,最大的好处是直观且高效。Xcode4 的 xib 文件结构复杂且臃肿,很容易产生冲突,不过好在 Xcode5 对它进行了很大的改进,结构更加简单且易读。不过由于 UI 既可以在 xib 里调整,也可以在代码里调整,甚至是代码的不同地方进行调整,调试和维护都容易出现问题。
  • 使用 StoryBoard 好处很明显:非常直观。一共有多少个页面,每个页面是做什么的,页面之间如何关联都可以看得很清楚。问题也很大:多人协作,很容易出现冲突,要频繁地解决冲突还是挺影响效率的。当然如果只是一个人开发,那就没有问题了。

所以三种方式各有优劣,而使用 RAC 并不会强制你使用代码去构建 UI,依然可以用 xib/StoryBoard,它改变的是编程模式,对 UI 的影响其实不大。另外 RAC 还提供了一套 UIKit Extension,很多需要 Delegate/Target-Action 的 UI,可以直接使用 RAC 的方法,这也带来了很大的便利。

InfoQ:苹果每年都会有新的工具、新的 API 开放出来,比如 iOS 6 之后可以实现界面元素的相对布局等等,ReactiveCocoa 可以支持新的功能么?或者是能否基于 ReactiveCocoa 进行自定义扩展?

李忠:好比有一座房子,房子的主人每年都会对里面的家具做一些调整,如灯泡从白炽灯变成节能灯,洗衣机从半自动变成了全自动等等,也会新添置一些器材,如为了更爽地看世界杯,买了个投影仪,或为了更方便地打扫房间,买了个 iRobot 等等。

这座房子就好像 Cocoa,对家具的调整就好比新的 API,新的工具好比新的器材。而 RAC 并不会对现有的家具造成影响,它改变的只是墙体的结构,让它更稳固。

以 AutoLayout 为例,它可以实现界面的相对布局,比如 [NSLayoutConstraint constraintsWithVisualFormat:options:metrics:views:],RAC 并不会干扰这一过程。 但 AutoLayout 的一个特点:描述 View 之间的关系,而不是动态的去计算,是挺符合 RAC 的理念的,所以 RAC 也可以用来做这件事情。比如有两个 View:parentView 和 childView,假如当 parentView 的 bounds 改变时,childView 也要跟着改变,就可以这么做:

[RACObserve(parentView, layer.bounds) subscribeNext:^(id bounds){ childView.frame = CGRectInset(bounds, 5, 5); }];

RAC 的开发者觉得这样可行,于是就有了 ReactiveCocoaLayout,所以是否有必要基于 RAC 进行自定义扩展,需要看是否符合 RAC 的理念。

InfoQ:使用 ReactiveCocoa 带给你和你的团队最大的好处是什么? 最大的弊端是什么?

李忠:先来说说弊端吧,RAC 最大的问题在于它跟正常的编程模式太不一样了,就像第一次穿上溜冰鞋,很多人都会觉得不习惯,然后各种摔跤,因为不能再用“走路”的模式去实践了。所以学习成本是个很大的挑战。

其次 RAC 没有被大规模采纳,很少有人分享 Best Practices,或相关的文章,这时“贸然”地用到项目里,如果影响了开发效率怎么办?项目不能如期交付怎么办?其他团队成员不够熟悉怎么办?遇到问题找不到解决方案怎么办?这些都是要考虑的因素,所以如果要使用,必须对它有相当程度的了解,因此潜在的风险也是个大问题。

有一天同事 Dismory 说他已经用 RAC 开发了一个 App,并且感觉很不错,于是就决定在开发花瓣时用一下。因为我们是模块化开发,每个人会分到多个模块,所以也并不要求每个人都使用 RAC,可以按照自己最熟悉的方式去写,这也进一步降低了风险。

以前没有用 RAC 写过一个完整的项目,自然会遇到不少问题。最大的问题是:如何用 RAC 的理念去思考?因为不够熟悉,所以代码往往两不像,既不像 RAC,也不像 Cocoa。于是我就开始翻 issues 列表,看 RAC 作者写的 App 以及各类文章,慢慢地有点 get the point 了,写起来也顺手了。也会跟团队成员分享经验,讨论遇到的问题。开发效率的提升,代码复杂度降低这两点就是最大的好处。

InfoQ:今年的 WWDC 大会上苹果发布了 Swift 语言,未来苹果应该会大力支持 swift, 你认为 ReactiveCocoa 是否会基于 Swift 开发新版本?难度大吗?

李忠:由于 ObjectiveC 语言自身的限制,也影响到了 RAC 的一些特性,比如无法根据一个 Signal 得知它的 sendNext value 的类型,这是很不方便的,要么推断它的类型,要么去看接口说明,如果没有说明,那只能看源码。而 Swift 的 Generic 特性正好可以弥补这点。

除此之外,因为 Swift 没有 KVO,而 RAC 又是基于 KVO 实现的,所以如果要用 Swift 来重写,底层的改动还是挺大的。不过看起来他们正打算这么做。

这就会带来一些问题,如果项目是用 ObjectiveC 写的,那么就无法调用 Swift 的 Generic 方法,或者其他 Swift 具备的特性。另外目前 Swift 语言还没有到稳定版,接口和使用上也存在变动的可能。

我觉得他们应该是认同 Swift,且相信它会在将来成为主力开发语言,所以不如一次性地支持到位。如果还是使用 OC,那么可以用 RAC2,如果使用 Swift,那么就可以用 RAC3。

RAC3 借鉴了.NET 的 Rx 思想,通过 Observer / Observable / Enumerator / Enumerable 这 4 个基础类来实现 push/pull driven streams,架构上也更清晰了,使用 Swift 来实现这些特性应该也没什么问题。至于难度么,Just trust the github guys。

InfoQ:使用 ReactiveCocoa 需要时间成本,你认为值吗?是否建议新手直接使用 ReactiveCocoa 开发程序?

李忠:相比于其他的框架,ReactiveCocoa 的学习曲线更加陡峭,也就意味着需要花更多的时间。如果对 Cocoa 的设计模式、理念和常用 Framework 都已经很熟悉,也做过了几个成熟的 App,那么可以去更深入地了解下,比如如何用 RAC 的方式去解决 Cococa 编程遇到的问题,如何写出更 RAC 的代码等等。

有两种方法可以写出 bug-free 的代码。 1) 使用那些让 bug 更少的技术 2) 用自己熟悉的技术。如果对第一点吃不准,那么只使用第二点也没什么问题。

不建议新手直接使用 RAC 去开发程序,如果能做到这点,已经不是新手了,至少有不错的编程基础。如果只是自己做 Side Project 还行,涉及到多人合作,说服别人使用也是个难题,毕竟 RAC 不够 popular,且有着不可控的风险,而且将来别人来维护代码也会是个问题。

Cocoa 编程还有很多的挑战,这些不是学会了 RAC 就能解决的,对于大多数人我还是建议先看看,不用急着就在项目里使用,等 RAC3.0 出来后再考虑也不迟。

InfoQ:ReactiveCocoa 为 iOS 开发者带来了函数响应式编程, 统一了消息传递机制,你认为 ReactiveCocoa 还有哪些需要完善的地方?

李忠:ReactiveCocoa 需要完善的地方包括:

  • 性能 跟 pure KVO 相比,还是差了不少。比如光是 subscribNext 就慢了 1 个数量级,接收到新的 value 也慢了 5 倍左右。如果 signal 一多,subscription 也会跟着多起来,性能问题就会慢慢浮出水面。
  • signal 的 sendNext value 类型未知 感觉回到了脚本语言。只能根据 signal 名字去推断,或是看源码,不够 cool,且影响效率,还有出错的可能(比如正常应该发送 Number 的,忽然发送了 String),不过使用 Swift 应该能够解决这个问题。
  • 调试 目前的 callback stack 实在是深了点,最简单的 [signal subscribeNext^(id x){}] 就会有近 40 次的调用,项目跑起来,如果挂在了某个地方,往前追溯就得绕过那「厚厚」的一层 RAC 调用,真心累啊。
  • 命名 作为编程界的两大难题之一,RAC 在这块也有改进的空间,比如他们内部就会讨论 subscribe 这个名字是不是有问题,再想想 RACChannel 的命名等等,如果名字能够让使用者一看就明白,也算是降低了学习成本。
2014-07-02 04:144901
用户头像

发布了 219 篇内容, 共 140.6 次阅读, 收获喜欢 192 次。

关注

评论

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

JMeter笔记7 | JMeter脚本回放

测试 Jmeter 性能测试 自动化测试 接口测试

等保和网络安全法的关系是什么?怎么理解?

行云管家

网络安全 等保 等级保护

Apache Hudi 在袋鼠云数据湖平台的设计与实践

袋鼠云数栈

数据湖 Hudi Apache Hudi

在 Kubernetes 上实现高速应用交付

NGINX开源社区

nginx Kubernetes

软件测试丨SeleniumIDE 自动化用例录制、测试用例结构分析

测试人

软件测试 自动化测试 测试开发 测试用例 selenium

JMeter笔记8 | JMeter关联

测试 Jmeter 性能测试 自动化测试 接口测试

NFTScan 正式发布 Bitcoin NFT 浏览器,支持 Ordinals NFT 和 BRC20 资产

NFT Research

Bitcoin NFT\

又爆神作!阿里首发并发编程神仙笔记,差距不止一点点

做梦都在改BUG

Java 并发编程

嘉为蓝鲸CMP多云管理平台解决方案成功入选!

嘉为蓝鲸

多云管理 IT运维 蓝鲸

实力上榜!ONES 荣获深圳市「专精特新」企业认定

万事ONES

透明LED显示屏与常规屏的区别

Dylan

LCD1602液晶显示屏 显示器 LED显示屏

GitHub上13个高赞Java项目推荐,会一个就能跟面试官谈笑风生

Java你猿哥

Java 微服务 秒杀系统 网约车项目 java项目

理解JVM工作机制(二) 对象的创建

Geek漫游指南

Java JVM Java web

零信任之访问代理

Flomesh

Pipy

开源赋能 普惠未来|铜锁/Tongsuo诚邀您参与2023开放原子全球开源峰会

开放原子开源基金会

开源

Python从0到1丨了解图像形态学运算中腐蚀和膨胀

华为云开发者联盟

Python 人工智能 华为云 华为云开发者联盟 企业号 5 月 PK 榜

开发者福利来了 | 京东云全系核心产品公开比价:我们承诺,买贵就赔!

京东科技开发者

数据库 云主机 京东云 云主机厂商 企业号 5 月 PK 榜

火山引擎DataLeap联合DataFun发布《数据治理知识地图》

字节跳动数据平台

数据治理 数据开发 数据库开发 数据研发

理解JVM工作机制(三)对象的内存布局

Geek漫游指南

Java JVM

浅谈NFT盲盒游戏系统开发原理

Congge420

ChatGPT聊天系统开发基于GPT-3.5架构

Congge420

SpringBoot 中实现定时任务的几种方式

做梦都在改BUG

Java Spring Boot

发挥数据价值!数据驱动的日志解析与异常检测方法介绍!

嘉为蓝鲸

日志分析 管理日志 日志统计

嘉为蓝鲸DevOps流水线工具如何为企业研发赋能?

嘉为蓝鲸

DevOps 流水线 蓝鲸

【云计算】谷歌云是国外的吗?是公有云还是私有云?

行云管家

公有云 私有云 谷歌云

开源赋能 普惠未来|XuperCore诚邀您参与2023开放原子全球开源峰会

开放原子开源基金会

开源

面试官:怎么保证Kafka的消息不丢失

做梦都在改BUG

Java kafka 面试 消息队列 消息中间件

火山引擎多云安全平台,破解多云异构场景下的安全挑战

科技热闻

分解GameFi链游游戏软件系统如何开发?

Congge420

【技术】多端能力服务统一是一种关键的技术和架构

没有用户名丶

花瓣网李忠:ReactiveCocoa是Cocoa的未来_语言 & 开发_小盖_InfoQ精选文章