Reactive Programming with Ruby
Reactive programming (RP) is a relatively new design paradigm. It was created to handle the challenges that arise with modern web development. As the internet has evolved over the past 20 years, so too have the priorities of web applications. Data transference has massively increased in size and speed. As a result, applications are expected to behave in a responsive and interactive way. In order to provide rich user experiences, developers need a way to process and propagate data asynchronously.
Applications have recently been shifting from a poll-based model where data is pulled through by request, to a reactive model where data is pushed through by events. This is the basis of Reactive Programming. We can formally define RP as "a focus on propagating and responding to incoming events over time". The paradigm is actually a combination of two older and well-established design patterns, the Iterable and Observer patterns. Both the Iterable and Observer patterns are behavioral patterns, which characterize the interaction and responsibility of classes and objects. In order to fully understand RP, we must first explore the design patterns from which it originates.
Iterator pattern
The Iterator pattern abstracts how we traverse over a collection by wrapping the collection and providing a uniform API to access the next element. The Iterator class also defines an interface for accessing the elements in order to compare or perform some action on them. This pattern should sound familiar as it is employed in Ruby's Enumerable module.
Observer pattern
The Observer pattern is a design pattern where an object maintains a list of observers, which it notifies of any changes in state. The observable is the subject that is expected to experience some change and the observers are the listeners waiting and watching for those changes. In this way, we can represent an application in terms of its inputs and outputs, asynchronous flows of data that get transformed during the lifetime of the application. These flows of data are called streams, a sequence of data that is made available over time. These streams are composed of events as they occur. An event could be a twitter post, a button click, a change in the weather, and so on. Nearly anything can constitute an event. This makes reactive programming ideal for real time applications. There are many use cases where users want the application's data to consistently update. For example, an instant messaging app or stock price ticker.
Reactive Ruby
Ruby ships with an Observable module in the standard library. This provides a basic mechanism for an object to notify its subscribers (observers) of changes in state. The Observable module is a good starting point but lacks the scalability and fault tolerance for most use production applications. Ideally, we would like to have a system that is more robust, resilient, and flexible, ready to meet modern demands. Introducing the Reactive Manifesto.
The Reactive Manifesto describes the mission of the Reactive Extensions (Rx) library. The library provides an API for a wide range of languages including Python, JavaScript, Go, Java, and many more (including Ruby of course!). The manifesto describes reactive systems as being:
- Responsive - systems should provide rapid and consistent responses
- Resilient - failures are contained and isolated, ensuring recovery without compromising the system as a whole
- Elastic - systems continue to perform under varying workloads, contention points and bottlenecks should be removed
- Message Driven - systems rely on asynchronous message-passing that ensures loose coupling
By utilizing RxRuby, we can compose observable streams that notify subscribers of changes in state. The Rx library demonstrates a variety of examples on their github. Exploring the RP paradigm in full requires a book unto itself. This chapter is meant to provide the reader with a brief introduction to the rapidly growing method of reactive programming. Some web frameworks, such as Google's Angular, have already implemented reactive programming natively and encourage its use as a best practice. As the industry evolves developers must remain aware of trends and innovations that occur and remain open minded to to change.