First of all, can I say I wasn’t expecting so much buzz around The Reactive Revolution of Swift? I really appreciated feedbacks, compliments and some of the critiques were of a remarkable level. One got my attention, first of all because it’s from a blog I read since I started to develop on the iPhone (2007 right before my Bachelor, yes with JB…), the second is because, at the opposite of some others, it has an argument to present, this article is The Non-Reactive Solution.

πρόλογος (Prologue)

I am not a big fan of “article wars”, they are pretty much pointless and for the reader are annoying, because the context is defined by reading a list of articles in a certain order, but I think Brent kind of asked for it:

PPS I struggled with this article because the last thing I want to do is discourage a developer who’s presumably younger than I am (safe bet) to stop writing. Note to the author: if you’re of a mind to, please write a follow-up! I’ll happily and very gladly link to it.

Probably 5-6 years ago I would have definitely stopped writing, shutting down my blog right after, closing my Twitter account and trying to leave asking for a lift to SpaceX towards Mars to start a new career there… but I think confrontation and discussion is far more interesting, it gives me the chance to learn something new and grow as person and developer.

Not To React

The non react approach suggested starts with a misunderstanding of a part of my article:

There are no locks in the solution I outline above.

The example I proposed was part of a talk about RxSwift, still no video available (but soon will be, I hope), and the article was a kind of follow up. The example I pasted to show the classic imperative way was a clear exasperation, to demonstrate the point of callback-hell. The following part about locks, wasn’t connected to the example, it was a generalization necessary to introduce the fundamentals of Rx, even if, at some point extending that app over messages, a synchronization strategy would become necessary. Anyway, it looks like I have to defend myself, which I don’t think is necessary, but this clarification deserved to stay here for information purposes.

Let’s move on. The non reactive approach suggested is interesting and I had to think a lot about it, because the proposed solution was around NSNotificationCenter, which is an implementation of the observer pattern I was trying to evolve while explaining how Rx works. Honestly this was the last solution I expected in contrast to my proposed reactive-way for the following reasons:

  • NSNotifications are hard to trace and the flow of control becomes hard to understand in a first sight
  • NSNotifications can wrap any type, you can’t be sure the notification is passing a message object and not a unicorn. On this subject I recommend an article on Objc.io
  • Any part of the application can register to the message and, if one of the consumers is slow, considering the synchronous nature of NSNotificationCenter, it might be slow down by a code that is somewhere else
  • Personal: I always worked with an unwritten rule by a former, really talented (probably the best dev I ever worked with), boss: if the whole app doesn’t need to know about a change, don’t use NSNotificationCenter

Compared to the solution I proposed there are few advantages:

  • There’s no fight (Imperative vs Declarative) of the Cocoa frameworks and patterns, as pointed out
  • Notifications are part of the Cocoa API, so no extra dependencies
  • Considering the previous one, the code is readable even by the newbies

but has the following disadvantages:

  • It’s not type safe, unless you add if and guard to prevent unexpected data
  • Once the notifications start to be really fast (multiple users writing on the same time, plus the current user typing), the queue will soon be under pressure with unexpected results
  • The flow is spread around the application, in my example the flow is declared at the beginning of the file, in viewDidLoad
  • External interference is possible: in the example, if we abuse the NSNotificationCenter somewhere else, we might have an impact in the current code, with very hard time to get aware of the source

I have also to point out that the proposed solution probably takes in consideration the single example I showed, not considering a potential extensions of the app, making the whole architecture more sensible while using NSNotificationCenter. It’s a fair thought, because if in a first instance I exaggerated the imperative version, this solution doesn’t take in consideration further extensions of the application.

How would I non-React?

Well, I had the time to think about few examples but the first one that comes to my mind is to use a protocol and use the power of Swift, basically the delegate pattern. Isn’t Swift Protocol oriented?

So, how would my solution look like? I am fan of the MVVM pattern, brought by Microsoft, but in an MVC world I would create a Controller that would take care of processing and stacking my messages.

Disclaimer: this is not intended to be compiled, it’s a potential version, forgive typos and mistakes.

protocol MessageDelegate {
    func userDidReceiveMessage(message: JSQMessage)
}

I would probably then write a controller like the following one:

class MessagesController {
    var delegate: MessageDelegate
    var messages: [JSQMessage] { get }
    // [...] more data to identify the chat
}

messages has to be read-only, because I don’t want to have my view controller to get the power to perform an unexpected change operation over it, which has not to be part of its responsibilities.

At this point I would perform some processing in the controller, using NSOperation or GCD to get the necessary information out of my socket in background, staying in the controller. I favorite class over struct because I believe identity is extremely important here.

I would later use this controller into my MVC approach:

class MessageViewController: JSQMessageTableViewController {
    
    let controller: MessageController 
    
    [...]

    func userDidReceiveMessage(message: JSQMessage) {
        // refresh the message view using controller.messages as data source
        self.finishReceivingMessage()
    }

}

In this way I can clearly follow the flow of my “notification”, having a single entity responsible to collect and manage my messages, my MessagesController, a type-safe entity responsible to delegate process the new messages MessageDelegate that ensures we are processing the right kind of information and a function as callback in my view controller. This approach is easier to scale, easier to test (testing NSNotifications might be really hard) and safer, considering the type-safe nature of Swift.

Why I React

Well, even if the previous example focused on the new shining good things of Swift, it’s something I would definitely code in a MVC project, I still prefer the reactive way for the following reasons:

  • The flow is clear: declared in a single place
  • In case I need to scale the project, I can move to a MVVM pattern and split the code across multiple View Models in a very elegant way, using the previous example I would have to split the code across multiple controllers or end up having a Massive View Controller
  • Personal: You know what? I don’t want to take care about asynchronous programming with CGD or NSOperations, I trust the work of Kruno, considering I helped actively on the project, so I know the quality of RxSwift, plus the massive amount of tests are there to prove it

In the past I worked with languages like Java, Ruby, Scala and did some toy projects in Node.js and Go, always keeping an eye on LISP and derived works, so I am aware of all the potential ways to fight concurrency, because this is what synchronization is about, prevent concurrency to blow up the whole system. I like Rx because it simplifies a lot my daily work and because I know how painful can be synchronizing things across threads, but as I am about to say, it’s a personal preference.

Conclusion

Reactive programing is a matter of preference, it’s not the silver bullet, sorry if I might have stated this on my previous article. The article I linked and that I wanted to reply to has brought back my old Java and OOP (I am sure somebody will probably warn me about using OOP and Java in the same sentence) background, I am a curious person and I will definitely love to hear more potential solutions about this problem using different approaches, maybe using classic dependency injection or KVO (subclassing NSObject).

TL;DR

I believe the declarative approach has a lot more to give if used in the proper manner, and RxSwift (even if it’s an external dependency), it’s a valid framework. About this, Kruno deserves a lot of credit. I would definitely trade the OOP/Imperative way with a declarative/reactive one with the downside of importing an external dependency, but hey, this is me and it’s my personal opinion.

P.S. It’s not my intention to start a flame war, but otherwise to exchange opinions about Rx and how to implement the same thing in the classic imperative way, creating an healthy share of solutions to help people finding the way that best suits their personal need.