RxJava反应式编程
上QQ阅读APP看书,第一时间看更新

1.1 反应式编程与RxJava

反应式编程(reactive programming)是一个通用的编程术语,它主要关注对变更做出反应,比如数据值或事件。反应式编程通常可以按照命令式(imperative)的方式来实现。回调就是一种以命令式实现反应式编程的方法。电子表格是反应式编程的一个绝佳例子:某些单元格依赖于其他的单元格,如果被依赖的单元格发生变化,这些单元格也会随之“做出反应”。

函数式反应编程?

尽管Reactive Extensions(通常指Rx,特指的话是RxJava)受到了函数式编程的影响,但它并不是函数式反应编程(Functional Reactive Programming, FRP)。FRP是非常具体的一种反应式编程类型,它涉及连续的时间,而RxJava只处理随时间推移出现的离散事件。在RxJava的早期,我本人也陷入了这样的命名陷阱,将其宣传为“函数式反应”,后来我发现“函数式反应”在数年前就已经被别人定义了。因此除了“反应式编程”之外,没有一个公认的通用术语来描述RxJava。FRP还是经常被误用于描述RxJava和类似的方案。对于是应该拓展FRP的含义(因为在过去的几年间,它已经被非正式地使用了),还是让FRP止于关注连续时间的实现,互联网上也时有争论。

为了消除疑虑,可以把重点放在RxJava确实受到了函数式编程的影响,并且有意地采取了与命令式编程不同的编程模型。这一章提到“反应式”时,指的是RxJava使用的反应式+函数式风格。与之相对,提到“命令式”时,并不是说反应式编程不能以命令式的方式实现,强调的是使用命令式的方式来编程,而不是RxJava的函数式风格。专门对比命令式方式和函数式方式时,为了准确起见,会使用“反应式-函数式”和“反应式-命令式”。

在现在的计算机中,当涉及操作系统和硬件时,一切都会变成命令式的。开发人员必须明确告诉计算机要完成什么以及如何实现。人类不会像CPU和相关系统那样思考,所以我们添加了抽象。反应式-函数式编程就是一种抽象,就像高层级命令式编程术语是对底层二进制和汇编指令的抽象一样。记住并理解“一切都会变成命令式的”很重要,因为它能够帮助理解反应式-函数式编程的思维模型,并理解它最终是如何执行的,这里并没有什么魔法。

因此,作为一种编程方式,反应式-函数式编程是命令式系统之上的一种抽象。它允许开发人员在编写异步和事件驱动的用例时不用像计算机本身那样思考,也不用以命令式的方式来定义复杂的状态交互,尤其是跨线程和网络边界时。在处理异步和事件驱动的系统时,不用像计算机那样思考是一项有用的特质,因为这种情况会涉及并发和并行,而要正确和高效地使用这些功能是非常具有挑战性的。Brian Goetz的著作《Java并发编程实战》、Doug Lea的著作Concurrent Programming in Java以及像Mechanical Sympathy这样的论坛,都表明了掌握并发所面临的深度、广度以及复杂性。使用RxJava以来,通过与这些书的作者、论坛和社区的专家的交流,我更加确信编写高性能、高效、可扩展和正确处理并发的软件相当不容易。这还没有将分布式系统考虑进来呢,它将并发性和并行性的难度提高了一截。

所以,简而言之,反应式-函数式编程解决的问题就是并发和并行。更通俗地说,它解决了回调地狱问题。回调地狱是以命令式的方式来处理反应式和异步用例带来的问题。反应式编程,比如RxJava实现,受到了函数式编程的影响,并且会使用声明式的方式来避免反应式-命令式代码常见的问题。