Being Proactively Reactive

A New Paradigm to Abstract Away Code Complexity

Byte Monk
Capital One Tech
7 min readApr 19, 2017

--

Real-time events are everywhere — be they UI events or data events — and they’re pushing both web and mobile applications to provide highly interactive experiences to the user. As a developer, one can easily get tangled up in a web of implementation details when trying to provide high interactivity. The reactive programming paradigm adds a level of abstraction over imperative callback systems, helping us to stop worrying about complex implementation details.

However, achieving this abstraction can require significant changes in coding style.

What is Reactive Programming?

Everyone has at least a little experience with reactive programming because most of us have worked on Excel spreadsheets before. Does this look familiar?

In the Excel sheet above, if any of the numbers change, the sum is updated accordingly. This was traditionally referred as dataflow programming, but has been modernized and recoined as reactive programming.

In this paradigm, the input data sequences can take many forms; they can be a stream of data from a file or web service such as a Twitter feed, or a series of events such as user input or mouse clicks. One can think of the stream as a transfer of the sequence of events/data ordered in time. Asynchronous programming, being non-blocking in nature, enables delegation of these stream of data sequences to various threads, systems, and/or devices.

Reactive programming is about programming with asynchronous flow of data sequence.

The Reactive Mindset…

When JavaScript was born, C, C++ and Java were commercially popular for non-mainframe computing. Most Java developers, like me, continued to stay in our comfort zone of object-oriented programming, occasionally breaking rules like embedding JavaScript snippets in JSPs.

The JavaScript community really took off in 2005 when Jesse James Garrett released a white paper where he coined the term “Ajax” — of which JavaScript was the backbone. This resulted in a plethora of open source libraries and communities forming around JavaScript. There’s no single accepted definition of functional programming; however, by treating functions as first class objects, Javascript made object-oriented programmers shift their thinking.

Today, JVM languages such as Java8, Scala, Groovy and Clojure have adopted and integrated functional programming as a key part of their language. Coming from an imperative programming background, starting with functional programming can feel daunting. However, within a few weeks of using functional programming techniques, one can quickly build up a set of simple modular functions, as well as utilize language-based parallelism of computation. Thinking in reactive requires similar, if not less, of a programming paradigm shift to force your brain to let go of old typical imperative and functional programming habits.

… Leads to Being Reactive!

Behavioral patterns Observer and Iterator are among the most popular patterns in modern UI frameworks and MVC models. Having a good understanding of these two patterns form the basis in getting started with reactive programming.

Iterator Pattern provides a way to traverse and access or PULL the elements of a container (collection/data source/generator) object without exposing its underlying representation. In Observer Pattern the producer knows about new data when it becomes available and sends or PUSHES that data to a consumer.

Iterator and Observer are prime examples of Pull and Push models which underpin a lot of reactive programming discussions, having a direct correlation with Sync and Async style of programming.

Pull

When you pull, you end up reiterating the dataset to detect changes. In the example below, initial data set has two characters — A and B. First iteration pulls and prints A and B. I then add two new characters, but don’t see the changes unless I iterate thru the same dataset again. This is an Imperative approach.

Of course, one can implement Pull approach by using polling — such as checking array length every 1000ms and traverse if there is change in data. In other words, using pull makes a developer responsible to explicitly ask for any change in data, which usually requires starting multiple threads and is difficult to maintain.

Push

In order to get the latest changes using pull approach, developers ends up writing convoluted code. Push can be implemented using Observer pattern, but that involves a lot of boiler plate code that developers need to write again and again. Push implementation can also be achieved using Callback approach, but unlike Observer pattern, in Callback only one Callback can be informed of the changes. This means developers end up writing convoluted code, which defeats the purpose of Callback. To avoid writing convoluted callbacks or boilerplate Observer pattern, we can get the benefit from Rx library.

In this example, with the help of RX classes Observable and PublishSubject, we have powered ArrayList to push out changes to its subscribers. One might still debate that the code is convoluted, but that is where developers need the paradigm shift — it keeps getting easier as we go deeper. Learning the basics of Observable and PublishSubject will help us understand this example.

rx.Observable

In ReactiveX an observer subscribes to an Observable. Then that observer reacts to whatever item or sequence of items the Observable emits. An Observable emits items or sends notifications to its observers by calling the observers methods. Once an Observer has subscribed, “observer” is sometimes called a “subscriber,” “watcher,” or “reactor.”

rx.subjects.PublishSubject;

A Subject is a sort of bridge or proxy that is available in some implementations of ReactiveX. It acts both as an observer and as an Observable. Because it is an observer, it can subscribe to one or more Observables. Because it is an Observable, it can pass through the items it observes by reemitting them, and it can also emit new items. PublishSubject is one of the four varieties of Subject that are designed for particular use cases. It emits all subsequently observed items to the subscriber and provides the Observer with a new item to observe.

Reactive Extensions (RX)

The popularity of AJAX (Java’s non-blocking I/O API) and Node.js in mainstream web development has really helped concepts of synchronous/asynchronous gain traction. When it comes to data structures, most programmers typically use Finite Collections such as Arrays, Map or Set, and infinite collection are typically handled using Web-sockets.

Reactive Extensions or RX promises to provide consistent APIs to a language, allowing it to seamlessly work across these four dimensions of data sequences: async, sync, finite and infinite.

In a nutshell,

“It extends the observer pattern to support sequences of data and/or events and adds operators that allow you to compose sequences together declaratively while abstracting away concerns about things like low-level threading, synchronization, thread-safety, concurrent data structures, and non-blocking I/O.” — http://reactivex.io/intro.html

Why Not Reactive?

If your code is only handling one event stream, imperative programming with a callback is probably the way to go. Even if you have multiple independent event streams, imperative programming may still be better since it eliminates the abstraction layer of reactive programming, keeping you closer to OS and compiler optimization.

However, providing a highly interactive experience often requires you to combine events, have conditional logic, and handle failure scenarios gracefully — this is where reactive programming really shines.

Summary

Reactive programming is a programming term focused on reacting to changes, such as data values or events, which are often done imperatively. Reactive programming implementations provide an additional abstraction over imperative callbacks. This abstraction layer provides a very powerful tool for doing async and non-blocking programming. However, it requires significant changes to your coding style. When you’ve achieved this change, reactive programming proves to be very effective tool alongside its elder siblings — object-oriented and functional programming. Each having their own important space in the mission to simplify software complexity at enterprise level.

DISCLOSURE STATEMENT: These opinions are those of the author. Unless noted otherwise in this post, Capital One is not affiliated with, nor is it endorsed by, any of the companies mentioned. All trademarks and other intellectual property used or displayed are the ownership of their respective owners. This article is © 2017 Capital One.

For more on APIs, open source, community events, and developer culture at Capital One, visit DevExchange, our one-stop developer portal. developer.capitalone.com/

--

--