A lot has been said in the last years about MVC and its problems and how to tackle them.1 Lately two posts (or series) in particular caught my attention:
The problem with both posts, is that they lack any argument to sustain some of the claims, which is usual in these sort of posts. On the other side of the bulwark, where you would see things like "MVVM is better than MVC because X", like the former, they also lack depth and facts.
And why is that? Because people, no matter how much experience they have, tend to forget that:
- There are no silver bullets.
- Architectures and technologies can be poorly applied and, as you guessed, they will be.
Let's dissect some of the claims:
However, I’ve found that building apps based on these patterns tends to pay negative dividends in the long run.
All of these patterns tend to be “strangers” to UIKit and AppKit. Because of this difference, you end up with additional hurdles to clear when things change.
No evidence, or even an example, is provided besides a quoted strangers.
When your team members change, you have additional work to teach new developers about not just the business logic of your app, but often a whole new architectural pattern. This requires more up-front investment, and a longer lead time before team members can start being productive.
When you are hiring, you take into consideration multiple things:
- Cultural fit.
- Is this a person I would like to work it.
- Does he/she have an interest in learning new things.
- Is this person comfortable with the sort of approach we use internally.
The 4 is one of the reasons why we don't hire people remotely that don't have experience with FRP (independently of the flavour). Bottom line, it would be pretty irresponsible to hire someone that:
- Has no experience with your stack; or
- Has no interest in learning your stack.
As someone mentioned on twitter, team members don't change on the short or medium term. You can expect the same person to be around for more than one year (in average for Silicon Valley).
When the operating system changes, you have additional work to try and shoehorn new features in to architecturally-native concepts. You have to plumb through size classes, safe layout margins, dynamic type, localization, locale changes, preferred attributes (status bar style, etc), lifecycle events, state preservation and restoration, and who knows what else when new paradigms get inevitably added as iOS updates each year.
I don't understand how this relates to MVVM, Viper, MVP, or even FRP. All those approaches make use of UIKit and its features as much as MVC.
Anecdotally, I was of the same opinion when I used AsyncDisplayKit (now named Texture). Kristian Angyal and myself, needed the extra performance that we just couldn't get with
UIKit. One of our initial fears were:
- how well it will play with UIKit: in some parts there was a mix and match of both technologies.
- what would happen when a new OS version would come.
You know what happened? We got an app running at 60fps in an iPhone 4S. Moreover, the way AsyncDisplayKit works when it comes to creating cells and calculating their height, made the whole design simpler. 3
Conclusion: we weren't able to achieve our goals with UIKit.4 It was a humbling experience to be proven wrong.
When your requirements change, you can sometimes be caught in the situation of having to fork someone else’s library, wait for them to catch up, or hope that they’ll accept your pull request.
The post doesn't mention that you can simply fork the library, apply your fix and use your own fork. Which is what we are doing internally with JSQMessagesViewController.
However, you drift further and further away from what the system frameworks are providing, which means adopting new systems features requires more code to bring it to where you are.
There is nothing, in the post, sustaining any of these claims.
Wouldn’t it be nice if you could just get it for free? Wouldn’t it be awesome if you could just use UIKit and AppKit and have it all “just work”? Wouldn’t it be nice to live in a world where you thought 300 lines in a view controller was excessively long?
Well, the problem is that you don't get it for free. A lot of what Apple provides, is either broken, or it's bad (or both). One thing, in particular, that really settled my own career with FRP is how bad NSOperations and NSOperationsQueue are:
Without a way to compose them, they are essentially useless to me.
But not to drift too far, as I mentioned previously, all those approaches use UIKit at the same extent as MVC. As you guessed: you get it for free as well (whatever free means).
The huge advantage of this approach is that system features come free. Trait collection propagation is free. View lifecycle callbacks are free. Safe area layout margins are generally free. The responder chain and preferred UI state callbacks are free. And future additions to UIViewController are also free.
This follows the same line of thinking: I don't understand in what way this has anything to do with MVVM or Viper, or even FRP. You get all that "for free" with all the other approaches.
Cocoa Touch is (I suspect) deliberately very simple: there’s Target-Action pattern, Dependency Injection, Delegate and MVC. That’s about it, really. Apparently it’s way too simple for some.
The paragraph mistakes simplicity with how easy is to understand something. FRP is simple, probably more than some of the approaches mentioned, but not easy.
Most of these have truly noble goals, on paper. They aim to cleanly separate data model, model-view communication, view itself and also the controller that connects the view and the model. They aim to turn the views into declarative API where you puzzle the pieces and the rest of the app follows along.
Diving deeper and deeper into all this I increasingly felt that people are over-complicating what UIKit has to offer — an API proven to work and perform well on its target platform. People were not trying to improve UIKit, they were actively fighting against it.
This is the main point I wanted to touch:
Both posts mix the usage of different architectural approaches with UIKit, which for the majority of times, are completely orthogonal.
MVVM, in particular, still makes use of UIKit at the same degree MVC does. Viper the same. FRP is an umbrella for many things. You can use UI bindings, but they also make use of UIKit. If you want a more conservative approach, you can keep FRP away from the UI and just use it further down the stack. Which is a perfectly valid approach and one that I would recommend when introduced (or introducing someone) to the subject.
The only point at which FRP might be a problem, would be a given UI bind to stop working because UIKit has changed. How many times has that happened? The posts should have provided those numbers, or anecdotal evidence, but none of them did.
Both posts rely on the authors's subjectivity, as expected. The problem is that there is no evidence, facts, numbers, or anything that can be measured objectively when comparing MVC to any other approach.
These sort of posts are always a trap, because they tap directly into our own narrow view of the world, which a lot of time, don't really align with what's out there.
The majority being its misusage. ↩
I am only referencing to the parts where the comparisons are made. The series also describe how to use MVC, which is beyond the focus of this post. ↩
With UIKit, the cell height is calculated in the UITableViewDelegate, with AsyncDisplayKit, the height is provided by the cell. Which frankly makes things easier. (of course, assume we are not using Cell Autosizing) ↩
We spent almost 2 weeks running in circles to achieve it and we couldn't. Most certainly because our own lack of knowledge. ↩