Declarative Programming Using Swift 💋 RxSwift

Bob Godwin
5 min readJul 2, 2018

One of the questions I get asked often is should I introduce RxSwift in a legacy codebase? Before answering this question I would like to define the meaning of being declarative and why you should be declarative when coding.

👉🏿 Definition:

Declarative programming is a style of programming that actually expresses the computational logic without describing it’s workflow. It is self described with intent to communicate a clear correspondence and often said to be anything other than imperative programming.

🙄 Legacy:

This refers to a code that is no longer fully supported or which life cycle is ended. But in recent times engineers have come to describe legacy code as a poorly written code, lacks units tests, difficult to articulate and easy to break.

Now you might be wondering if all the code written before the gang of four published their book on design patterns are considered legacy code?. Well I will leave that to you to answer.

Another question is whether software developers write legacy code today? The answer to this is YES. When you write a code that is incomprehensible, tightly coupled code or any code who’s intent is difficult to articulate.

💂🏿‍♀️Imperative vs Functional:

I don’t want to go into a holy war here because there are some veteran engineers who thinks that Functional is crazy and just a super-flow thing which is not necessary. Well I want to tell you veteran that you are wrong.

The main problem of Imperative coding paradigm is that it mutates the program’s State with statements and uses subroutines to show intent for each given State This naturally leads having a code base full of if, elseif else, switch, while & for statements with tons of mutable data.

Functional programming totally avoids State mutation, it treats computation as an expression of intents and chains it all together making it declarative and easy to understand.

👉🏿 Becoming Declarative with RxSwift 💪🏾

RxSwift is a member framework of ReactiveX designed for the Swift community. It embodies the concept of high level abstraction, reactive, functional and declarative programming which is required for asynchronous event driven computation and many more.

  • 📝 Specification:

Let’s say you have a legacy app that downloads images from a resource from the cloud and you’re also required to show a loading indicator on the screen while download is going on in a background queue.

Imperatively when you think of the above specification you can understand that you need to start managing DispatchQueues which can sometimes be a nightmare, depending on how complicated the requirements are.

My first advice is to introduce a RxSwift through Cocoapods into your code base as indicated in the configuration file below.

If you’re a fan of Carthage you can do so as follows:

  • 👀 ObserverType

Let’s assume you’re using MBProgressHUD framework to manage your loading indicator. You could start by abstracting some of it’s imperative functionalities into an RxSwift ObserverType as follows:

With 23 lines of code we’ve totally changed the way we use MBProgressHUD and also added a flexibility that enables us to pass an Optional UIView within a reactive context. UIView when accessed from a UIViewController is always Optional so we can access it and use it directly without UnWrapping and our ObserverType will take care of the rest for us.

📒 This technique can be applied to SVProgressHUD or any other loading indicators.

  • 👁 Observable

Our model for the download should be pretty straightforward and this could come in form of an extension on top of our legacy class or a structif we are already using Swift within our code-base. But as for best practices we should begin with a protocol as shown below:

The datasource is an Observable concrete type. If you are new to Reactive programming the best way to understand is to visualize the process of how a publishing house gets the news across to it’s subscribers when they want to start listening or reading the news.

Observables are very declarative and it helps you define a function for publishing values, but it is not executed until a consumer subscribes to it.

  • 🤗 Adoption

The Model is self explanatory, we use the .rx property provided by RxSwift to access Observable functions and we can add multiple transformative messages as functions on the same data. e.g .share is saying the sequence shares a single subscription to all listening/observing.

  • 𝌭 Declarative ViewModel

RxSwift puts at your disposition computational tools that helps you become very declarative with your intent. The above protocol ViewModelType enacts readability with the intent to drive an image and finish an event when something completes.

  • 🤝 Conforming to the contract

As we can see from the above implementation, the code reads naturally like a romance novel with zero mystery and clear composition of functions on top of each other.

  • 🐿 Subscribing to the news channel

From line# 22-25 we can clearly see how the image is driven from the source into the UIImageView.image property through the imageView.rx.image binding. This process is known as Subscription to an Observable and it’s exactly at this point that every other function along the Observable chain is executed.

On line# 18 we did reactively used yet another trait property of RxSwift called PublishRelay to turn on the loading indicator, which we later turned off at line# 33 when the download is completed, and this is represented by our viewModel.finished a Completable Type.

  • 🍱 Summary

Being declarative is not difficult as claimed by imperative old school. Declarative code helps us modularize our code, think abstractly by removing the hurdles of implementation details.

Observables are very good in expressing and communicating the developers intent. They are unidirectional data flow which make the application state read only. Changes are communicated purely as functions within the object tree, making it a single source of truth.

  • 🤾🏾‍♂️ Playground

You can find the complete example to my rant here on the RxSwiftObserverType.playground and when you do a test drive from the playground you should see the image downloaded as shown below :-)

Other Articles:

--

--