Why you don’t need shit like RxSwift or MVVM
What were you the god of again?
Let’s get shit out of the way
RxSwift is dead, MVVM is dead. Killed by Hela… I mean Swift.
Are you Thor, god of external library, which is a direct port from the implementation of another language, that doesn’t benefit from some of the most powerful and unique Swift features?
This is what you should do
Aren’t you tired of useless shit thrown at your face?
Say you are beginning as an iOS developer in early 2019.
Your first project was a mess.
So you googled to find best practices in app architecture.
OK. Reactive programming. That seems promising. How should I do the reactive part? KVO? Seems weird since KVO is technically from Objective-C and I’m writing Swift but what do I know. Observable? Stream of events? Flow control? Wow, here I am thinking all I need is some kind of automatic callback mechanism. How foolish of me. It’s called FRP and it sounds cool, alright. Let me try it. Wait, complete SDK replacement? Doesn’t that mean a dependency to third-party library instead of iOS official SDK? I guess it’s that good huh? OK. Let me try a simple example. Wow, string is not just a string, it is not a stream of events, and I could bind it to an observer. MIND-BLOWN. Silly me, using property observer this whole time. Oh, what’s this disposeBag? I have to do manual memory management for every flow? Man, this FRP must be insanely good to be worthy of these overheads. Hmm, where do I add conditional logic? Let me go though all these blogs again, I must have missed something. No? I guess I need to go through documents. Where is it… nevermind, I’ll learn how to work with Observable first, hmm… wait, I have to type cast it every time? Isn’t it against static dispatch in Swift…?
Then you gave up. Went and watched some internet porn.
Then you came… back of course.
This time you decided to start with something lighter.
MVVM. That’s a good trick.
OK. Let’s go. Binding? Isn’t property observer… nevermind. Silly me, it must be a shit feature with untold side effects. View model as reference type? I though immutable value type is safer for model type. OK, that is because you need to add networking to view model… wait. What? Why? Uh… but my app is all about displaying networking data, if I move networking out, what should my view controller do? It would be clean now? Sure, but that’s what happens when you create a new class and do things there… I guess that’s the point? But wouldn’t view model become massive as well? Since you are still doing the same amount of work if not more accounting for overheads. Oh! Silly me, that is when you create NESTED or MORE view models and handle interactions. But… but, it looks like you just replaced one big view controller to many smaller ones… oh! Cool. That’s the point. Wait, I though you could do this using protocol extension while maintaining single responsibilty without mataining multiple smaller controllers with their own states and interactions. In fact protocol extension is not used in any meanful sense in MVVM… nevermind. It must be another shit feature with untold side effects.
OK. you finally got it. Went and watched some internet porn.
After you took your shot… with MVVM. You added “extensive MVVM experience” to your resume, and thinking it’s fine now. You’ve now matured as an iOS developer.
In the mean time, this is what you look like from my point of view.
What is the problem
Swift is an evolving language.
RxSwift violates static dispatch, which is the heart of Swift. This alone rules it out to be of any use in Swift development. See Combine, type is determined in compile time. I called this 3 years ago.
MVVM can be replaced by protocol extension. Because it’s implementation is well-known in other languages for many years, it’s natural to just port it to Swift. But people didn’t realize that there are better ways to do separation of concern now. In fact I’d argue MVVM is not that great for it in the first place.
Let the past die, kill it if you have to.
The last thing you want to do in 2019 is to learn either of both.
You don’t need useless shit thrown at your face. The power of Swift comes from simplicity. Its power allows you to forge a great weapon, a king’s weapon.
Elm architecture
The google top result for “Elm architecture in iOS” is a medium article talking about how to use RxSwift.
That is the reason I write this article. Elm architecture is simple. This is Elm architecture in iOS.
var title: String { didSet { label.text = title
}}
Wait, isn’t it just a property observer?
Elm architecture can be described as follows:
msg -> Model -> View -> msg
where msg is used to update model.
Compare this with above, you can see that
- You can use property observer to build view as function of Model which may be a component of overall State.
- You have one way binding from model to view. And that is good enough for most use cases. Because user interaction has side effects, hence often cannot be described by binding. Instead view processes user interaction and generates messages to update model. Side effects on view also appear as messages that update model.
- Network requests produce delayed message to update model. A major design difference with MVVM. Why put networking inside model when you can keep model simple and value-typed? You may argue that networking makes view controller complex which is what motivates MVVM in the first place. But what makes your networking complex? If it is complex, and you move it to view model, doesn’t that make your view model complex? Have you tried making it less complex? By an ancient technique called refactor? What about protocol extension?
Right out of the box, we have view updates as reaction to model changes.
FRP would dial this up to 11, and generalize it to Observable and a stream of events. But in practice you rarely need that shit. If you have a hammer, everything looks like a nail. How often do you do this?
Most of the time, you just need to observe some event and a callback. You can easily do functional part of FRP without the full package of FRP. It’s just a function to map something to something else, and it’d be particular easy in Swift thanks to static dispatch. You’d know every type in compile time.
So in this simplest example, we already have the essences of both RxSwift and MVVM.
Now if you send all messages to a fixed place, and update model from there.
action(.msg) // this function updates model
You have Redux.
You don’t need external dependencies of RxSwift or ReSwift, and you do better MVVM than MVVM since you don’t need reference type model and incur minimum overheads.
From a property observer.
If you’ve played with SwiftUI, you’ll notice SwiftUI builds upon Elm architecture.
struct Model: View {...}
Same model to view binding, except SwiftUI re-renders view automatically on model change for you.
Everything I’ve discussed so far still applies, while RxSwift and MVVM dies.
You can even do cooler Redux with it.
Ragnarok
Or as I called it, paradigm shift.
I’ve outlined the Elm architecture that is easily doable in iOS Swift. One can easily build Redux, uni-direction flow or other paradigms upon which.
But when it is combined with POP (protocol oritented programming) …
I’ve only briefly touch on using protocol extension to replace MVVM. You can’t find much info on it because very few people recognize its potential.
Remember, you’ve heard from me first. Protocol extension can replace MVVM.
I’d leave it as an exercise for interested readers. Send me a mail if you are interested and we can discuss.