RxSwift: The Complexity Tradeoff

Michael Long
May 23 · 4 min read

I recently published an article, “RxSwift: Better Error Handling With CompactMap”, in which I demonstrated how one of RxSwift 5’s new features could be used to improve and streamline your error handling code.

Many people found the article interesting, helpful and informative… except for one:

Which is not exactly the sort of response one likes to receive…

But it’s understandable.

Simple Examples vs Complex Examples

The problem with demonstrating new techniques using a simplified example is that the new technique often ends up looking way more involved than one doing a “simple function refresh”.

That’s especially true with RxSwift.

But if you increase the complexity to bring the example up to “real world” production levels, then you can easily hide the technique you’re trying to demonstrate beneath all of that extra code.

Nor does a simple example tend to demonstrate the true power of using RxSwift.

That said, I do know of one that does... and you’ve probably already seen it.

Github Search Example

Look at the Github search example on the RxSwift repository page.

It’s a timed API-driven search lookup with all sorts of conditionals bound directly to a table view… and done in less the 20 lines of declarative RxSwift code…

Whereas you’d probably be hard pressed to implement the same exact functionality in less than 100 lines of standard Swift code.

Especially by the time you’ve added the search bar delegate functions, data handling, error handling, thread management, the standard tableview delegate functionality and so on.

Not to mention the time you’d probably take debugging it.

So which is simpler?

In fact, I could easily add just a line or two of RxSwift to the original article’s sample code that would make writing that traditional “simple function refresh” slightly less than simple…

So let’s do that now. ;)

The “Less Than Simple” code

This is the final code sample from the Better Error Handling article, with two new lines of code added inside of the flatMapLatest function.

class CompactMapErrorViewModel {

var data: Observable<[String]>!
var error: Observable<String?>!
var dataService = DataService() init(load: Observable<Void>) {
let loading = load
.flatMapLatest { [unowned self] _ in
self.dataService.load()
.retry(2)
.timeout(.seconds(3), scheduler: MainScheduler.instance)
.materialize()
}
.observeOn(MainScheduler.instance)
.share()
data = loading
.compactMap { $0.element }
error = loading
.compactMap { $0.error?.localizedDescription }
}
}

Automatic Error Retry

The .retry(2) line will automatically retry the API load call on error up to two more times before falling through and failing.

Do this when you think connections may be spotty or when the call must go through.

Automatic Timeout

That said, we don’t want our user to wait too long, so we also added a timeout function that will throw an error after three seconds… unless we receive our data or the aforementioned error when the retry fails.

Requirements

As mentioned, this sort of thing is just as easy as adding a line or two of code in Rx, but it also demonstrates just the sort of thing can give a traditional Swift programmer fits.

Perhaps more to the point, both bits of functionality demonstrate the extra requirements one often finds in production code.

The Business Unit calls down one fine morning and says, “Hey Michael, just how hard would it be to add…”

And you’re off to the races.

So, complex… or not?

You may think RxSwift is complex, or that it’s easier to just do a “simple function refresh”, but in actually RxSwift is a very powerful toolkit that, once learned, contains the potential to turbo-boost your code and your productivity.

Further, the functional / reactive / declarative / stream mindset is very much present in web tools like React, in modern application development environments like Dart/Flutter, and is even inherent today in various Swift application architectures like MVVM, MVP, and others.

So while Rx may not be “simple”, it is powerful, and in my humble opinion the added complexity it might add is well worth it.

And who knows? If you do it long enough, you just might find that it’s not really that complex after all…


EDIT: This story continues in RxSwift and Production-Level Code. There I take the classic Github search example from above and show just what it takes to turn it into modern, production ready RxSwift code.

Michael Long

Written by

Michael Long (RxSwifty) is a Senior Lead iOS engineer at CRi Solutions, a leader in cutting edge iOS, Android, and mobile corporate and financial applications.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade