Reactive Architecture

Dan Leonardis
AndroidPub
Published in
7 min readDec 24, 2017

--

Software architecture is the art of designing and constructing high level structures of a software system, the discipline of creating such structures, and the documentation of those structures. It’s about making fundamental choices (which are costly to change once implemented) that meet the original product requirements of the system.

Reactive programming is an asynchronous programming paradigm, concerned with streams of information and the propagation of changes. This differs from imperative programming, where that paradigm uses statements to change a program’s state.

Reactive Architecture is nothing more than the combination of reactive programming and software architectures. Also known as reactive systems, the goal is to make the system responsive, resilient, elastic, and message driven.

Reactive Architecture is simple but not easy.

The Usual Suspects

The typical architectures used for UI facing systems are MVC (Model View Controller), MVP (Model View Presenter), and MVVM (Model View ViewModel). You might be tempted to combine any one of these with Rx and say you’re reactive, but we know better than that. There is only one Keyser Söze.

For simplicity’s sake I’m going to thin the herd quickly in order to keep the focus on reactive architecture. MVC was not meant to be a full blow architecture. Instead it was used everywhere creating “massive” view controllers and polluting our business logic. MVP was a great solution but as I wrote about in my previous article it lost it’s shine compared to MVVM. Even before Rx, the Android community was leaning towards MVVM.

Great! So MVVM + Rx = Reactive? Well… not quite.

Kudos

Before continuing I’m going to just state that I didn’t invent these ideas. Instead I reflect on past projects, learn the lessons, and pass the ideas on to others. As a leader, it’s not just my job to run the training, but instead to make sure the training is absorbed. Here are some links of interest that I base a lot of this discussion on.

MVVM + Rx Baseline

Typically when adding reactive to MVVM, Views bind to asynchronous data events from the ViewModel using subjects. Views publish information to subjects in the ViewModel where long running background tasks can take place via subscribers in the ViewModel. The ViewController acts like the glue which sets all this up. Although things slightly change with Android Data Binding, you’re swapping out Rx for Android specific observables so the concept is fairly the same.

  • Views bind to ViewModel events via ViewController
Example of Views subscribing to ViewModel updates
  • Views publish information to ViewModel via ViewController
Example of View events sent to ViewModel
  • ViewModel long running tasks
Example of MVVM ViewModel

The Problems

Let’s visualize the problem as Jake Wharton did in the managing state presentation. Let’s visualize the entire flow of the combined code above.

Single stream with side effects

Each arrow is a general representation of an operator event on a stream. The middle ‘<>’ symbol represents the imperative code that setup Rx connections. The phone image represents the UI, like a ViewModel, and the cloud image represents some kind of network call.

The problem comes from the arrows in red. These red arrows are considered side effects. These are the doOnNext() and onErrorResumeNext() in the above code that imperatively jump out of the stream to update the UI or grab data directly from it. These are hard to test in isolation. Since side effects reach into the UI at random parts, multiple streams will conflict with each other in order to share and get information.

Multiple streams with side effects

Other problems include the large use of subjects to tie ViewModel and Views together. Subjects allow anyone to publish; which is a weaker setup than a well-thought, strictly-defined, source Observables. Subjects are also not thread safe, which runs the risk of causing race conditions with the operators. Subjects, when an error occurs, will tear down the stream and complete the observable. Best to avoid using too many subjects.

A subtler issue is the sharing of data between different threads. If you have objects being accessed from different schedulers, you’ll need to synchronize those objects in order to prevent race conditions.

We’ve now created new problems…

The Solution

One word, simplify. We need to simplify how we use MVVM + Rx. We can achieve this by reducing the number of streams, limiting our dependence on subjects, and simplify sharing data between concurrent events.

Managing State with RxJava

In the diagram above, we cut down the interactions between layers by creating a single stream from start to finish. No matter how many events are in flight, they should all fit down one single pipe. The observable types shown above are base types, from which each entity in the pipe will inherit.

  • UiEvent — any type of UI interaction (ie -button click or scroll event)
  • Action — internal representation of a UiEvent
  • Result — retrieve information based on an action
  • UiModel — a data object that represents the current UI state

Based on where in the pipe the data entity is, a different base type will be used. This helps in creating that clean code modularization we love and cherish. The data types also have the advantage of carrying all the information needed in order to be useful. This eliminates the many side effects that grab information from the UI. All the information you’ll ever need to achieve a task will be inside the data entity.

How do we actually achieve this? There are a few key operators you need to know.

  • Merge — combine multiple Observables into one
  • Publish — convert an ordinary Observable into a connectable Observable
  • Compose — transform an Observable by applying a particular Transformer function to it
  • Scan — apply a function to each item emitted by an Observable, sequentially, and emit each successive value

Combining the above Rx operators allows us to create this simplified approach.

TLDR — Simplify your streams

The Solution — In Marbles

Another way of thinking about this simplification is a funnel. All those Rx marbles converging together to update the UI synchronously. Yea!

Reactive Architecture Be Like…

Let’s look at a sample solution using marbles. Assume we have the following requirements, a button click to submit data and an edit text field we autocomplete.

Requirements

Step 1 — Merges generate substantial synergies

We need to merge all the UI events into one stream. Each event we create will have all the information from the UI before it’s merged into a single stream.

Step 1

Step 2 — Transformers: More than meets the eye

We need to transform UiEvents into Actions. This helps achieve our clean code modularization.

Step 2

Step 3 — The results are in

We need to handle results from our external calls. Transform those APIs (Data Sets) into Results.

Step 3

Step 4 — In God we trust, in all others we scan

Synchornously create a UiModel based on the Results coming in.

Step 4

Final Thoughts

Reactive architecture is the next evolutionary architectural step for iOS and Android platforms. Based on REDUX for the web, this architectural pattern fits all demands from the reactive manifesto.

It’s responsive because you’ll use background schedulers to do most of the heavy lifting. You’re using only the main UI thread to handle UI events and update views. It’s resilient, because an error won’t tear down a stream. It’s responsive, regardless of how many asynchronous events come in from the UI, disk, network, or even the operating system. It’s message driven, because all the data we need is passed through the stream using well defined data types.

Reactive Architecture is simple but not easy.

Where’s the Code?

All that discussion and no example code to share? Nonsense. Just absorb the concepts first. Watch the videos posted. Watch them again. Then read my next article where I will take a deep dive into code to demonstrate exactly how this is accomplished.

However if you can’t wait, click here.

Feel freet to follow me on Twitter, and Medium.

~LEO

--

--